Index: contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java
===================================================================
--- contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java (revision 0)
+++ contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java (revision 0)
@@ -0,0 +1,195 @@
+package org.apache.lucene.index;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.quartz.CronTrigger;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SchedulerFactory;
+import org.quartz.impl.StdSchedulerFactory;
+
+/**
+ * The CronSplitRule causes a split to occur in the
+ * {@link SplitPolicy} to which it applies, at the points in time specified in
+ * the {@link CronTrigger} for which it is configured.
+ *
+ * @author Karthick Sankarachary
+ */
+public class CronSplitRule extends SplitRuleAdapter implements SplitRule {
+ private static final long serialVersionUID = 3536740140589552908L;
+
+ // A configuration option that specifies the cron trigger expression.
+ public static final String CRON_SPLIT_RULE_TRIGGER = "cron.split.rule.trigger";
+
+ // A standard Quartz scheduler factory.
+ private static transient SchedulerFactory sf = new StdSchedulerFactory();
+
+ // A Quartz scheduler that knows how to run jobs whenever the {@link
+ // #cronTrigger} is satisfied.
+ private transient Scheduler scheduler;
+
+ // A string representation of the {@link CronTrigger} object
+ private String cronTrigger;
+
+ /**
+ * Construct a cron split rule using the default configuration options.
+ */
+ public CronSplitRule() {
+ super();
+ }
+
+ /**
+ * Construct a cron split rule using the specified configuration options.
+ *
+ * @param options
+ * the configuration options
+ */
+ public CronSplitRule(Map options) {
+ super(options);
+ }
+
+ /**
+ * Default the cron trigger to activate at midnight every day
+ */
+ @Override
+ public Map getOptionDefaults() {
+ Map options = super.getOptionDefaults();
+ options.put(CronSplitRule.CRON_SPLIT_RULE_TRIGGER, "0 0 0/24 * * ?");
+ return options;
+ }
+
+ /**
+ * Ensure that the cron trigger is a non-empty string.
+ */
+ @Override
+ public java.util.Map getOptionBounds() {
+ Map bounds = super.getOptionBounds();
+ bounds.put(CronSplitRule.CRON_SPLIT_RULE_TRIGGER, new OptionBound() {
+ public boolean isInbounds(String key, Serializable value) {
+ return value instanceof String && ((String) value).length() > 0;
+ }
+ });
+ return bounds;
+ }
+
+ /**
+ * @return the scheduled job's name, which equates to the split policy's id
+ */
+ private String getJobName() {
+ return getSplitPolicyId();
+ }
+
+ /**
+ * @return the name of the trigger, which equates to the split policy's id
+ */
+ private String getTriggerName() {
+ return getSplitPolicyId();
+ }
+
+ /**
+ * @return the scheduled group's name, which equates to the split policy's id
+ */
+ private String getJobGroup() {
+ return getSplitPolicyId();
+ }
+
+ /**
+ * When the split index is opened, schedule a stateful cron job that is
+ * triggered based on the {@link #cronTrigger} specified in the configuration
+ * options.
+ */
+ public void onOpen(SplitPolicy splitPolicy) {
+ super.onOpen(splitPolicy);
+ try {
+ scheduler = sf.getScheduler();
+
+ // Create a job detail based on the {@link SplitCronJob} job.
+ JobDetail jobDetail = new JobDetail(getJobName(), getJobGroup(),
+ SplitCronJob.class);
+ JobDataMap context = jobDetail.getJobDataMap();
+ context.put(SplitRule.SPLIT_RULE_SPLIT_POLICY_ID, getSplitPolicyId());
+ context.put(SplitRule.SPLIT_RULE_LAST_SPLIT_TIME, 0L);
+ context.put(SplitRule.SPLIT_RULE_LAST_SEGMENT_NAME, null);
+ context.put(SplitRule.SPLIT_RULE_LAST_SEGMENT_SIZE, 0L);
+ context.putAll(this.context);
+
+ cronTrigger = (String) this.splitPolicy
+ .getOption(CRON_SPLIT_RULE_TRIGGER);
+
+ // Define the cron trigger and schedule the above job based on that.
+ CronTrigger trigger = new CronTrigger(getTriggerName(), getJobGroup(),
+ getSplitPolicyId(), getJobGroup(), cronTrigger);
+ scheduler.addJob(jobDetail, true);
+ scheduler.scheduleJob(trigger);
+
+ scheduler.start();
+ } catch (Exception e) {
+ System.out.println("The scheduled split failed (" + e.getMessage()
+ + "), hence pausing split rule");
+ onPause();
+ }
+ }
+
+ /**
+ * When the split index is closed, shutdown the scheduler.
+ */
+ public SplitVote onClose() throws SplitException {
+ try {
+ if (scheduler != null) {
+ scheduler.shutdown();
+ }
+ } catch (SchedulerException e) {
+ throw new SplitException("Could not shutdown cron scheduler", e);
+ }
+ return SplitVote.CARRY_ON;
+ }
+
+ /**
+ * When the split index is paused, pause the scheduler.
+ */
+ public SplitVote onPause() throws SplitException {
+ try {
+ if (scheduler != null) {
+ scheduler.pauseAll();
+ }
+ } catch (SchedulerException e) {
+ throw new SplitException("Could not shutdown cron scheduler", e);
+ }
+ return SplitVote.CARRY_ON;
+ }
+
+ /**
+ * When the split index is resumed, resume the scheduler.
+ */
+ public SplitVote onResume() throws SplitException {
+ try {
+ if (scheduler != null) {
+ scheduler.resumeAll();
+ }
+ } catch (SchedulerException e) {
+ throw new SplitException("Could not shutdown cron scheduler", e);
+ }
+ return SplitVote.CARRY_ON;
+ }
+
+}