Browse Source
* commit '05dc89676950e6c38935cd806aabebb718cca15c': MOBILE-25879 兼容移动端,加老quartz代码 REPORT-27640 调整兼容入参release/10.0
zhouping
5 years ago
157 changed files with 50640 additions and 2 deletions
@ -0,0 +1,3 @@
|
||||
1.`fine-quartz-old`是为了与`fine-quartz`区别开,<br> |
||||
2.源码地址https://cloud.finedevelop.com/projects/PF/repos/thirdtools/browse,<br> |
||||
3.相比源码调整了默认的连接池为druid,以前是dbcp |
@ -0,0 +1,111 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
|
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An interface to be implemented by objects that define spaces of time during |
||||
* which an associated <code>{@link Trigger}</code> may fire. Calendars do not |
||||
* define actual fire times, but rather are used to limit a <code>Trigger</code> |
||||
* from firing on its normal schedule if necessary. Most Calendars include all |
||||
* times by default and allow the user to specify times to exclude. As such, it |
||||
* is often useful to think of Calendars as being used to <I>exclude</I> a block |
||||
* of time — as opposed to <I>include</I> a block of time. (i.e. the |
||||
* schedule "fire every five minutes except on Sundays" could be |
||||
* implemented with a <code>SimpleTrigger</code> and a |
||||
* <code>WeeklyCalendar</code> which excludes Sundays) |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
* @author Juergen Donnerstag |
||||
*/ |
||||
public interface Calendar extends java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
int MONTH = 0; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Set a new base calendar or remove the existing one. |
||||
* </p> |
||||
*/ |
||||
void setBaseCalendar(Calendar baseCalendar); |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the base calendar. Will be null, if not set. |
||||
* </p> |
||||
*/ |
||||
Calendar getBaseCalendar(); |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine whether the given time (in milliseconds) is 'included' by the |
||||
* Calendar. |
||||
* </p> |
||||
*/ |
||||
boolean isTimeIncluded(long timeStamp); |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. |
||||
* </p> |
||||
*/ |
||||
long getNextIncludedTime(long timeStamp); |
||||
|
||||
/** |
||||
* <p> |
||||
* Return the description given to the <code>Calendar</code> instance by |
||||
* its creator (if any). |
||||
* </p> |
||||
* |
||||
* @return null if no description was set. |
||||
*/ |
||||
String getDescription(); |
||||
|
||||
/** |
||||
* <p> |
||||
* Set a description for the <code>Calendar</code> instance - may be |
||||
* useful for remembering/displaying the purpose of the calendar, though |
||||
* the description has no meaning to Quartz. |
||||
* </p> |
||||
*/ |
||||
void setDescription(String description); |
||||
} |
@ -0,0 +1,53 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that is thrown to indicate that there has been a critical |
||||
* failure within the scheduler's core services (such as loss of database |
||||
* connectivity). |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class CriticalSchedulerException extends SchedulerException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>CriticalSchedulerException</code> with the given message. |
||||
* </p> |
||||
*/ |
||||
public CriticalSchedulerException(String msg, int errCode) { |
||||
super(msg); |
||||
setErrorCode(errCode); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* The interface to be implemented by <code>{@link Job}s</code> that provide a |
||||
* mechanism for having their execution interrupted. It is NOT a requirment |
||||
* for jobs to implement this interface - in fact, for most people, none of |
||||
* their jobs will. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The means of actually interrupting the Job must be implemented within the |
||||
* <code>Job</code> itself (the <code>interrupt()</code> method of this |
||||
* interface is simply a means for the scheduler to inform the <code>Job</code> |
||||
* that a request has been made for it to be interrupted). The mechanism that |
||||
* your jobs use to interrupt themselves might vary between implementations. |
||||
* However the principle idea in any implementation should be to have the |
||||
* body of the job's <code>execute(..)</code> periodically check some flag to |
||||
* see if an interruption has been requested, and if the flag is set, somehow |
||||
* abort the performance of the rest of the job's work. An example of |
||||
* interrupting a job can be found in the java source for the class
|
||||
* <code>com.fr.third.org.quartz.examples.DumbInterruptableJob</code>. It is legal to use |
||||
* some combination of <code>wait()</code> and <code>notify()</code> |
||||
* synchronization within <code>interrupt()</code> and <code>execute(..)</code> |
||||
* in order to have the <code>interrupt()</code> method block until the |
||||
* <code>execute(..)</code> signals that it has noticed the set flag. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If the Job performs some form of blocking I/O or similar functions, you may |
||||
* want to consider having the <code>Job.execute(..)</code> method store a |
||||
* reference to the calling <code>Thread</code> as a member variable. Then the |
||||
* impplementation of this interfaces <code>interrupt()</code> method can call |
||||
* <code>interrupt()</code> on that Thread. Before attempting this, make |
||||
* sure that you fully understand what <code>java.lang.Thread.interrupt()</code> |
||||
* does and doesn't do. Also make sure that you clear the Job's member |
||||
* reference to the Thread when the execute(..) method exits (preferrably in a |
||||
* <code>finally</code> block. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* See Example 7 (com.fr.third.org.quartz.examples.example7.DumbInterruptableJob) for a simple |
||||
* implementation demonstration. |
||||
* </p> |
||||
* @see Job |
||||
* @see StatefulJob |
||||
* @see Scheduler#interrupt(String, String) |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface InterruptableJob extends Job { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a user |
||||
* interrupts the <code>Job</code>. |
||||
* </p> |
||||
* |
||||
* @throws UnableToInterruptJobException |
||||
* if there is an exception while interrupting the job. |
||||
*/ |
||||
void interrupt() |
||||
throws UnableToInterruptJobException; |
||||
} |
@ -0,0 +1,79 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* The interface to be implemented by classes which represent a 'job' to be |
||||
* performed. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Instances of <code>Job</code> must have a <code>public</code> |
||||
* no-argument constructor. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>JobDataMap</code> provides a mechanism for 'instance member data' |
||||
* that may be required by some implementations of this interface. |
||||
* </p> |
||||
* |
||||
* @see JobDetail |
||||
* @see StatefulJob |
||||
* @see Trigger |
||||
* @see Scheduler |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface Job { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* fires that is associated with the <code>Job</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The implementation may wish to set a |
||||
* {@link JobExecutionContext#setResult(Object) result} object on the |
||||
* {@link JobExecutionContext} before this method exits. The result itself |
||||
* is meaningless to Quartz, but may be informative to |
||||
* <code>{@link JobListener}s</code> or |
||||
* <code>{@link TriggerListener}s</code> that are watching the job's |
||||
* execution. |
||||
* </p> |
||||
* |
||||
* @throws JobExecutionException |
||||
* if there is an exception while executing the job. |
||||
*/ |
||||
void execute(JobExecutionContext context) |
||||
throws JobExecutionException; |
||||
|
||||
} |
@ -0,0 +1,504 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Map; |
||||
|
||||
import com.fr.third.org.quartz.utils.StringKeyDirtyFlagMap; |
||||
|
||||
/** |
||||
* <p> |
||||
* Holds state information for <code>Job</code> instances. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>JobDataMap</code> instances are stored once when the <code>Job</code> |
||||
* is added to a scheduler. They are also re-persisted after every execution of |
||||
* <code>StatefulJob</code> instances. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>JobDataMap</code> instances can also be stored with a |
||||
* <code>Trigger</code>. This can be useful in the case where you have a Job |
||||
* that is stored in the scheduler for regular/repeated use by multiple |
||||
* Triggers, yet with each independent triggering, you want to supply the |
||||
* Job with different data inputs. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The <code>JobExecutionContext</code> passed to a Job at execution time |
||||
* also contains a convenience <code>JobDataMap</code> that is the result |
||||
* of merging the contents of the trigger's JobDataMap (if any) over the |
||||
* Job's JobDataMap (if any). |
||||
* </p> |
||||
* |
||||
* @see Job |
||||
* @see StatefulJob |
||||
* @see Trigger |
||||
* @see JobExecutionContext |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JobDataMap extends StringKeyDirtyFlagMap implements Serializable { |
||||
|
||||
private static final long serialVersionUID = -6939901990106713909L; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create an empty <code>JobDataMap</code>. |
||||
* </p> |
||||
*/ |
||||
public JobDataMap() { |
||||
super(15); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobDataMap</code> with the given data. |
||||
* </p> |
||||
*/ |
||||
public JobDataMap(Map map) { |
||||
this(); |
||||
|
||||
putAll(map); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>boolean</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, boolean value) { |
||||
String strValue = new Boolean(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Boolean</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Boolean value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>char</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, char value) { |
||||
String strValue = new Character(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Character</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Character value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>double</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, double value) { |
||||
String strValue = new Double(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Double</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Double value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>float</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, float value) { |
||||
String strValue = new Float(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Float</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Float value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>int</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, int value) { |
||||
String strValue = new Integer(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Integer</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Integer value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>long</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, long value) { |
||||
String strValue = new Long(value).toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Adds the given <code>Long</code> value as a string version to the |
||||
* <code>Job</code>'s data map. |
||||
* </p> |
||||
*/ |
||||
public void putAsString(String key, Long value) { |
||||
String strValue = value.toString(); |
||||
|
||||
super.put(key, strValue); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>int</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public int getIntFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Integer((String) obj).intValue(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>int</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String or Integer. |
||||
*/ |
||||
public int getIntValue(String key) { |
||||
Object obj = get(key); |
||||
|
||||
if(obj instanceof String) { |
||||
return getIntFromString(key); |
||||
} else { |
||||
return getInt(key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>int</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Integer getIntegerFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Integer((String) obj); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>boolean</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public boolean getBooleanValueFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Boolean((String) obj).booleanValue(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>boolean</code> value from the |
||||
* <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String or Boolean. |
||||
*/ |
||||
public boolean getBooleanValue(String key) { |
||||
Object obj = get(key); |
||||
|
||||
if(obj instanceof String) { |
||||
return getBooleanValueFromString(key); |
||||
} else { |
||||
return getBoolean(key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>Boolean</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Boolean getBooleanFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Boolean((String) obj); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>char</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public char getCharFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return ((String) obj).charAt(0); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>Character</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Character getCharacterFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Character(((String) obj).charAt(0)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>double</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public double getDoubleValueFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Double((String) obj).doubleValue(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>double</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String or Double. |
||||
*/ |
||||
public double getDoubleValue(String key) { |
||||
Object obj = get(key); |
||||
|
||||
if(obj instanceof String) { |
||||
return getDoubleValueFromString(key); |
||||
} else { |
||||
return getDouble(key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>Double</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Double getDoubleFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Double((String) obj); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>float</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public float getFloatValueFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Float((String) obj).floatValue(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>float</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String or Float. |
||||
*/ |
||||
public float getFloatValue(String key) { |
||||
Object obj = get(key); |
||||
|
||||
if(obj instanceof String) { |
||||
return getFloatValueFromString(key); |
||||
} else { |
||||
return getFloat(key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>Float</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Float getFloatFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Float((String) obj); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>long</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public long getLongValueFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Long((String) obj).longValue(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>long</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String or Long. |
||||
*/ |
||||
public long getLongValue(String key) { |
||||
Object obj = get(key); |
||||
|
||||
if(obj instanceof String) { |
||||
return getLongValueFromString(key); |
||||
} else { |
||||
return getLong(key); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Retrieve the identified <code>Long</code> value from the <code>JobDataMap</code>. |
||||
* </p> |
||||
* |
||||
* @throws ClassCastException |
||||
* if the identified object is not a String. |
||||
*/ |
||||
public Long getLongFromString(String key) { |
||||
Object obj = get(key); |
||||
|
||||
return new Long((String) obj); |
||||
} |
||||
} |
@ -0,0 +1,537 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.quartz.collections.ListOrderedSet; |
||||
import com.fr.third.org.quartz.utils.Key; |
||||
|
||||
/** |
||||
* <p> |
||||
* Conveys the detail properties of a given <code>Job</code> instance. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Quartz does not store an actual instance of a <code>Job</code> class, but |
||||
* instead allows you to define an instance of one, through the use of a <code>JobDetail</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>Job</code>s have a name and group associated with them, which |
||||
* should uniquely identify them within a single <code>{@link Scheduler}</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>Trigger</code>s are the 'mechanism' by which <code>Job</code>s |
||||
* are scheduled. Many <code>Trigger</code>s can point to the same <code>Job</code>, |
||||
* but a single <code>Trigger</code> can only point to one <code>Job</code>. |
||||
* </p> |
||||
* |
||||
* @see Job |
||||
* @see StatefulJob |
||||
* @see JobDataMap |
||||
* @see Trigger |
||||
* |
||||
* @author James House |
||||
* @author Sharada Jambula |
||||
*/ |
||||
public class JobDetail implements Cloneable, java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private String name; |
||||
|
||||
private String group = Scheduler.DEFAULT_GROUP; |
||||
|
||||
private String description; |
||||
|
||||
private Class jobClass; |
||||
|
||||
private JobDataMap jobDataMap; |
||||
|
||||
private boolean volatility = false; |
||||
|
||||
private boolean durability = false; |
||||
|
||||
private boolean shouldRecover = false; |
||||
|
||||
private Set jobListeners = ListOrderedSet.decorate(new HashSet()); |
||||
|
||||
private transient Key key = null; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobDetail</code> with no specified name or group, and |
||||
* the default settings of all the other properties. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that the {@link #setName(String)},{@link #setGroup(String)}and |
||||
* {@link #setJobClass(Class)}methods must be called before the job can be |
||||
* placed into a {@link Scheduler} |
||||
* </p> |
||||
*/ |
||||
public JobDetail() { |
||||
// do nothing...
|
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobDetail</code> with the given name, and group, and |
||||
* the default settings of all the other properties. |
||||
* </p> |
||||
* |
||||
* @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used. |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if nameis null or empty, or the group is an empty string. |
||||
*/ |
||||
public JobDetail(String name, String group, Class jobClass) { |
||||
setName(name); |
||||
setGroup(group); |
||||
setJobClass(jobClass); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobDetail</code> with the given name, and group, and |
||||
* the given settings of all the other properties. |
||||
* </p> |
||||
* |
||||
* @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used. |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if nameis null or empty, or the group is an empty string. |
||||
*/ |
||||
public JobDetail(String name, String group, Class jobClass, |
||||
boolean volatility, boolean durability, boolean recover) { |
||||
setName(name); |
||||
setGroup(group); |
||||
setJobClass(jobClass); |
||||
setVolatility(volatility); |
||||
setDurability(durability); |
||||
setRequestsRecovery(recover); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name of this <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the name of this <code>Job</code>. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if name is null or empty. |
||||
*/ |
||||
public void setName(String name) { |
||||
if (name == null || name.trim().length() == 0) { |
||||
throw new IllegalArgumentException("Job name cannot be empty."); |
||||
} |
||||
|
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the group of this <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public String getGroup() { |
||||
return group; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the group of this <code>Job</code>. |
||||
* </p> |
||||
* |
||||
* @param group if <code>null</code>, Scheduler.DEFAULT_GROUP will be used. |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if the group is an empty string. |
||||
*/ |
||||
public void setGroup(String group) { |
||||
if (group != null && group.trim().length() == 0) { |
||||
throw new IllegalArgumentException( |
||||
"Group name cannot be empty."); |
||||
} |
||||
|
||||
if (group == null) { |
||||
group = Scheduler.DEFAULT_GROUP; |
||||
} |
||||
|
||||
this.group = group; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the 'full name' of the <code>JobDetail</code> in the format |
||||
* "group.name". |
||||
* </p> |
||||
*/ |
||||
public String getFullName() { |
||||
return group + "." + name; |
||||
} |
||||
|
||||
public Key getKey() { |
||||
if(key == null) { |
||||
key = new Key(getName(), getGroup()); |
||||
} |
||||
|
||||
return key; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return the description given to the <code>Job</code> instance by its |
||||
* creator (if any). |
||||
* </p> |
||||
* |
||||
* @return null if no description was set. |
||||
*/ |
||||
public String getDescription() { |
||||
return description; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set a description for the <code>Job</code> instance - may be useful |
||||
* for remembering/displaying the purpose of the job, though the |
||||
* description has no meaning to Quartz. |
||||
* </p> |
||||
*/ |
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the instance of <code>Job</code> that will be executed. |
||||
* </p> |
||||
*/ |
||||
public Class getJobClass() { |
||||
return jobClass; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the instance of <code>Job</code> that will be executed. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if jobClass is null or the class is not a <code>Job</code>. |
||||
*/ |
||||
public void setJobClass(Class jobClass) { |
||||
if (jobClass == null) { |
||||
throw new IllegalArgumentException("Job class cannot be null."); |
||||
} |
||||
|
||||
if (!Job.class.isAssignableFrom(jobClass)) { |
||||
throw new IllegalArgumentException( |
||||
"Job class must implement the Job interface."); |
||||
} |
||||
|
||||
this.jobClass = jobClass; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>JobDataMap</code> that is associated with the <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public JobDataMap getJobDataMap() { |
||||
if (jobDataMap == null) { |
||||
jobDataMap = new JobDataMap(); |
||||
} |
||||
return jobDataMap; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the <code>JobDataMap</code> to be associated with the <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public void setJobDataMap(JobDataMap jobDataMap) { |
||||
this.jobDataMap = jobDataMap; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Validates whether the properties of the <code>JobDetail</code> are |
||||
* valid for submission into a <code>Scheduler</code>. |
||||
* |
||||
* @throws IllegalStateException |
||||
* if a required property (such as Name, Group, Class) is not |
||||
* set. |
||||
*/ |
||||
public void validate() throws SchedulerException { |
||||
if (name == null) { |
||||
throw new SchedulerException("Job's name cannot be null", |
||||
SchedulerException.ERR_CLIENT_ERROR); |
||||
} |
||||
|
||||
if (group == null) { |
||||
throw new SchedulerException("Job's group cannot be null", |
||||
SchedulerException.ERR_CLIENT_ERROR); |
||||
} |
||||
|
||||
if (jobClass == null) { |
||||
throw new SchedulerException("Job's class cannot be null", |
||||
SchedulerException.ERR_CLIENT_ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set whether or not the <code>Job</code> should be persisted in the |
||||
* <code>{@link com.fr.third.org.quartz.spi.JobStore}</code> for re-use after program |
||||
* restarts. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
*/ |
||||
public void setVolatility(boolean volatility) { |
||||
this.volatility = volatility; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set whether or not the <code>Job</code> should remain stored after it |
||||
* is orphaned (no <code>{@link Trigger}s</code> point to it). |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
*/ |
||||
public void setDurability(boolean durability) { |
||||
this.durability = durability; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set whether or not the the <code>Scheduler</code> should re-execute |
||||
* the <code>Job</code> if a 'recovery' or 'fail-over' situation is |
||||
* encountered. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
* |
||||
* @see JobExecutionContext#isRecovering() |
||||
*/ |
||||
public void setRequestsRecovery(boolean shouldRecover) { |
||||
this.shouldRecover = shouldRecover; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Whether or not the <code>Job</code> should not be persisted in the |
||||
* <code>{@link com.fr.third.org.quartz.spi.JobStore}</code> for re-use after program |
||||
* restarts. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
* |
||||
* @return <code>true</code> if the <code>Job</code> should be garbage |
||||
* collected along with the <code>{@link Scheduler}</code>. |
||||
*/ |
||||
public boolean isVolatile() { |
||||
return volatility; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Whether or not the <code>Job</code> should remain stored after it is |
||||
* orphaned (no <code>{@link Trigger}s</code> point to it). |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
* |
||||
* @return <code>true</code> if the Job should remain persisted after |
||||
* being orphaned. |
||||
*/ |
||||
public boolean isDurable() { |
||||
return durability; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Whether or not the <code>Job</code> implements the interface <code>{@link StatefulJob}</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean isStateful() { |
||||
if (jobClass == null) { |
||||
return false; |
||||
} |
||||
|
||||
return (StatefulJob.class.isAssignableFrom(jobClass)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>Scheduler</code> whether or not the <code>Job</code> |
||||
* should be re-executed if a 'recovery' or 'fail-over' situation is |
||||
* encountered. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If not explicitly set, the default value is <code>false</code>. |
||||
* </p> |
||||
* |
||||
* @see JobExecutionContext#isRecovering() |
||||
*/ |
||||
public boolean requestsRecovery() { |
||||
return shouldRecover; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Add the specified name of a <code>{@link JobListener}</code> to the |
||||
* end of the <code>Job</code>'s list of listeners. |
||||
* </p> |
||||
*/ |
||||
public void addJobListener(String name) { |
||||
if (jobListeners.add(name) == false) { |
||||
throw new IllegalArgumentException( |
||||
"Job listener '" + name + "' is already registered for job detail: " + getFullName()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Remove the specified name of a <code>{@link JobListener}</code> from |
||||
* the <code>Job</code>'s list of listeners. |
||||
* </p> |
||||
* |
||||
* @return true if the given name was found in the list, and removed |
||||
*/ |
||||
public boolean removeJobListener(String name) { |
||||
return jobListeners.remove(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns an array of <code>String</code> s containing the names of all |
||||
* <code>{@link JobListener}</code>s assigned to the <code>Job</code>, |
||||
* in the order in which they should be notified. |
||||
* </p> |
||||
*/ |
||||
public String[] getJobListenerNames() { |
||||
return (String[])jobListeners.toArray(new String[jobListeners.size()]); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return a simple string representation of this object. |
||||
* </p> |
||||
*/ |
||||
public String toString() { |
||||
return "JobDetail '" + getFullName() + "': jobClass: '" |
||||
+ ((getJobClass() == null) ? null : getJobClass().getName()) |
||||
+ " isStateful: " + isStateful() + " isVolatile: " |
||||
+ isVolatile() + " isDurable: " + isDurable() |
||||
+ " requestsRecovers: " + requestsRecovery(); |
||||
} |
||||
|
||||
public boolean equals(Object obj) { |
||||
if (!(obj instanceof JobDetail)) { |
||||
return false; |
||||
} |
||||
|
||||
JobDetail other = (JobDetail) obj; |
||||
|
||||
if (other.getName() == null && getName() != null) { |
||||
return false; |
||||
} |
||||
if (other.getName() != null && !other.getName().equals(getName())) { |
||||
return false; |
||||
} |
||||
|
||||
if (other.getGroup() == null && getGroup() != null) { |
||||
return false; |
||||
} |
||||
if (other.getGroup() != null && !other.getGroup().equals(getGroup())) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public int hashCode() { |
||||
return getFullName().hashCode(); |
||||
} |
||||
|
||||
public Object clone() { |
||||
JobDetail copy; |
||||
try { |
||||
copy = (JobDetail) super.clone(); |
||||
copy.jobListeners = ListOrderedSet.decorate(new HashSet()); |
||||
copy.jobListeners.addAll(jobListeners); |
||||
if (jobDataMap != null) { |
||||
copy.jobDataMap = (JobDataMap) jobDataMap.clone(); |
||||
} |
||||
} catch (CloneNotSupportedException ex) { |
||||
throw new IncompatibleClassChangeError("Not Cloneable."); |
||||
} |
||||
|
||||
return copy; |
||||
} |
||||
} |
@ -0,0 +1,368 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
|
||||
import com.fr.third.org.quartz.spi.TriggerFiredBundle; |
||||
|
||||
/** |
||||
* <p> |
||||
* A context bundle containing handles to various environment information, that |
||||
* is given to a <code>{@link com.fr.third.org.quartz.JobDetail}</code> instance as it is |
||||
* executed, and to a <code>{@link Trigger}</code> instance after the |
||||
* execution completes. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The <code>JobDataMap</code> found on this object (via the |
||||
* <code>getMergedJobDataMap()</code> method) serves as a convenience - |
||||
* it is a merge of the <code>JobDataMap</code> found on the |
||||
* <code>JobDetail</code> and the one found on the <code>Trigger</code>, with |
||||
* the value in the latter overriding any same-named values in the former. |
||||
* <i>It is thus considered a 'best practice' that the execute code of a Job |
||||
* retrieve data from the JobDataMap found on this object</i> NOTE: Do not |
||||
* expect value 'set' into this JobDataMap to somehow be set back onto a |
||||
* <code>StatefulJob</code>'s own JobDataMap. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>JobExecutionContext</code> s are also returned from the |
||||
* <code>Scheduler.getCurrentlyExecutingJobs()</code> |
||||
* method. These are the same instances as those passed into the jobs that are |
||||
* currently executing within the scheduler. The exception to this is when your |
||||
* application is using Quartz remotely (i.e. via RMI) - in which case you get |
||||
* a clone of the <code>JobExecutionContext</code>s, and their references to |
||||
* the <code>Scheduler</code> and <code>Job</code> instances have been lost (a |
||||
* clone of the <code>JobDetail</code> is still available - just not a handle |
||||
* to the job instance that is running). |
||||
* </p> |
||||
* |
||||
* @see #getJobDetail() |
||||
* @see #getScheduler() |
||||
* @see #getMergedJobDataMap() |
||||
* |
||||
* @see Job |
||||
* @see Trigger |
||||
* @see JobDataMap |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JobExecutionContext implements java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private transient Scheduler scheduler; |
||||
|
||||
private Trigger trigger; |
||||
|
||||
private JobDetail jobDetail; |
||||
|
||||
private JobDataMap jobDataMap; |
||||
|
||||
private transient Job job; |
||||
|
||||
private Calendar calendar; |
||||
|
||||
private boolean recovering = false; |
||||
|
||||
private int numRefires = 0; |
||||
|
||||
private Date fireTime; |
||||
|
||||
private Date scheduledFireTime; |
||||
|
||||
private Date prevFireTime; |
||||
|
||||
private Date nextFireTime; |
||||
|
||||
private long jobRunTime = -1; |
||||
|
||||
private Object result; |
||||
|
||||
private HashMap data = new HashMap(); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionContext with the given context data. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionContext(Scheduler scheduler, |
||||
TriggerFiredBundle firedBundle, Job job) { |
||||
this.scheduler = scheduler; |
||||
this.trigger = firedBundle.getTrigger(); |
||||
this.calendar = firedBundle.getCalendar(); |
||||
this.jobDetail = firedBundle.getJobDetail(); |
||||
this.job = job; |
||||
this.recovering = firedBundle.isRecovering(); |
||||
this.fireTime = firedBundle.getFireTime(); |
||||
this.scheduledFireTime = firedBundle.getScheduledFireTime(); |
||||
this.prevFireTime = firedBundle.getPrevFireTime(); |
||||
this.nextFireTime = firedBundle.getNextFireTime(); |
||||
|
||||
this.jobDataMap = new JobDataMap(); |
||||
this.jobDataMap.putAll(jobDetail.getJobDataMap()); |
||||
this.jobDataMap.putAll(trigger.getJobDataMap()); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get a handle to the <code>Scheduler</code> instance that fired the |
||||
* <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public Scheduler getScheduler() { |
||||
return scheduler; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get a handle to the <code>Trigger</code> instance that fired the |
||||
* <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public Trigger getTrigger() { |
||||
return trigger; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get a handle to the <code>Calendar</code> referenced by the <code>Trigger</code> |
||||
* instance that fired the <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public Calendar getCalendar() { |
||||
return calendar; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* If the <code>Job</code> is being re-executed because of a 'recovery' |
||||
* situation, this method will return <code>true</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean isRecovering() { |
||||
return recovering; |
||||
} |
||||
|
||||
public void incrementRefireCount() { |
||||
numRefires++; |
||||
} |
||||
|
||||
public int getRefireCount() { |
||||
return numRefires; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the convenience <code>JobDataMap</code> of this execution context. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The <code>JobDataMap</code> found on this object serves as a convenience - |
||||
* it is a merge of the <code>JobDataMap</code> found on the |
||||
* <code>JobDetail</code> and the one found on the <code>Trigger</code>, with |
||||
* the value in the latter overriding any same-named values in the former. |
||||
* <i>It is thus considered a 'best practice' that the execute code of a Job |
||||
* retrieve data from the JobDataMap found on this object.</i> |
||||
* </p> |
||||
* |
||||
* <p>NOTE: Do not |
||||
* expect value 'set' into this JobDataMap to somehow be set back onto a |
||||
* <code>StatefulJob</code>'s own JobDataMap. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Attempts to change the contents of this map typically result in an |
||||
* <code>IllegalStateException</code>. |
||||
* </p> |
||||
* |
||||
*/ |
||||
public JobDataMap getMergedJobDataMap() { |
||||
return jobDataMap; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>JobDetail</code> associated with the <code>Job</code>. |
||||
* </p> |
||||
*/ |
||||
public JobDetail getJobDetail() { |
||||
return jobDetail; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the instance of the <code>Job</code> that was created for this |
||||
* execution. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note: The Job instance is not available through remote scheduler |
||||
* interfaces. |
||||
* </p> |
||||
*/ |
||||
public Job getJobInstance() { |
||||
return job; |
||||
} |
||||
|
||||
/** |
||||
* The actual time the trigger fired. For instance the scheduled time may |
||||
* have been 10:00:00 but the actual fire time may have been 10:00:03 if |
||||
* the scheduler was too busy. |
||||
* |
||||
* @return Returns the fireTime. |
||||
* @see #getScheduledFireTime() |
||||
*/ |
||||
public Date getFireTime() { |
||||
return fireTime; |
||||
} |
||||
|
||||
/** |
||||
* The scheduled time the trigger fired for. For instance the scheduled |
||||
* time may have been 10:00:00 but the actual fire time may have been |
||||
* 10:00:03 if the scheduler was too busy. |
||||
* |
||||
* @return Returns the scheduledFireTime. |
||||
* @see #getFireTime() |
||||
*/ |
||||
public Date getScheduledFireTime() { |
||||
return scheduledFireTime; |
||||
} |
||||
|
||||
public Date getPreviousFireTime() { |
||||
return prevFireTime; |
||||
} |
||||
|
||||
public Date getNextFireTime() { |
||||
return nextFireTime; |
||||
} |
||||
|
||||
public String toString() { |
||||
return "JobExecutionContext:" + " trigger: '" |
||||
+ getTrigger().getFullName() + " job: " |
||||
+ getJobDetail().getFullName() + " fireTime: '" + getFireTime() |
||||
+ " scheduledFireTime: " + getScheduledFireTime() |
||||
+ " previousFireTime: '" + getPreviousFireTime() |
||||
+ " nextFireTime: " + getNextFireTime() + " isRecovering: " |
||||
+ isRecovering() + " refireCount: " + getRefireCount(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the result (if any) that the <code>Job</code> set before its |
||||
* execution completed (the type of object set as the result is entirely up |
||||
* to the particular job). |
||||
* |
||||
* <p> |
||||
* The result itself is meaningless to Quartz, but may be informative |
||||
* to <code>{@link JobListener}s</code> or |
||||
* <code>{@link TriggerListener}s</code> that are watching the job's |
||||
* execution. |
||||
* </p> |
||||
* |
||||
* @return Returns the result. |
||||
*/ |
||||
public Object getResult() { |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Set the result (if any) of the <code>Job</code>'s execution (the type of |
||||
* object set as the result is entirely up to the particular job). |
||||
* |
||||
* <p> |
||||
* The result itself is meaningless to Quartz, but may be informative |
||||
* to <code>{@link JobListener}s</code> or |
||||
* <code>{@link TriggerListener}s</code> that are watching the job's |
||||
* execution. |
||||
* </p> |
||||
*/ |
||||
public void setResult(Object result) { |
||||
this.result = result; |
||||
} |
||||
|
||||
/** |
||||
* The amount of time the job ran for (in milliseconds). The returned |
||||
* value will be -1 until the job has actually completed (or thrown an |
||||
* exception), and is therefore generally only useful to |
||||
* <code>JobListener</code>s and <code>TriggerListener</code>s. |
||||
* |
||||
* @return Returns the jobRunTime. |
||||
*/ |
||||
public long getJobRunTime() { |
||||
return jobRunTime; |
||||
} |
||||
|
||||
/** |
||||
* @param jobRunTime The jobRunTime to set. |
||||
*/ |
||||
public void setJobRunTime(long jobRunTime) { |
||||
this.jobRunTime = jobRunTime; |
||||
} |
||||
|
||||
/** |
||||
* Put the specified value into the context's data map with the given key. |
||||
* Possibly useful for sharing data between listeners and jobs. |
||||
* |
||||
* <p>NOTE: this data is volatile - it is lost after the job execution |
||||
* completes, and all TriggerListeners and JobListeners have been |
||||
* notified.</p> |
||||
* |
||||
* @param key |
||||
* @param value |
||||
*/ |
||||
public void put(Object key, Object value) { |
||||
data.put(key, value); |
||||
} |
||||
|
||||
/** |
||||
* Get the value with the given key from the context's data map. |
||||
* |
||||
* @param key |
||||
*/ |
||||
public Object get(Object key) { |
||||
return data.get(key); |
||||
} |
||||
} |
@ -0,0 +1,182 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that can be thrown by a <code>{@link com.fr.third.org.quartz.Job}</code> |
||||
* to indicate to the Quartz <code>{@link Scheduler}</code> that an error |
||||
* occured while executing, and whether or not the <code>Job</code> requests |
||||
* to be re-fired immediately (using the same <code>{@link JobExecutionContext}</code>, |
||||
* or whether it wants to be unscheduled. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that if the flag for 'refire immediately' is set, the flags for |
||||
* unscheduling the Job are ignored. |
||||
* </p> |
||||
* |
||||
* @see Job |
||||
* @see JobExecutionContext |
||||
* @see SchedulerException |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JobExecutionException extends SchedulerException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private boolean refire = false; |
||||
|
||||
private boolean unscheduleTrigg = false; |
||||
|
||||
private boolean unscheduleAllTriggs = false; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException, with the 're-fire immediately' flag set |
||||
* to <code>false</code>. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException() { |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException, with the given cause. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(Throwable cause) { |
||||
super(cause); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException, with the given message. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException with the 're-fire immediately' flag set |
||||
* to the given value. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(boolean refireImmediately) { |
||||
refire = refireImmediately; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException with the given underlying exception, and |
||||
* the 're-fire immediately' flag set to the given value. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(Throwable cause, boolean refireImmediately) { |
||||
super(cause); |
||||
|
||||
refire = refireImmediately; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException with the given message, and underlying |
||||
* exception. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(String msg, Throwable cause) { |
||||
super(msg, cause); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobExcecutionException with the given message, and underlying |
||||
* exception, and the 're-fire immediately' flag set to the given value. |
||||
* </p> |
||||
*/ |
||||
public JobExecutionException(String msg, Throwable cause, |
||||
boolean refireImmediately) { |
||||
super(msg, cause); |
||||
|
||||
refire = refireImmediately; |
||||
} |
||||
|
||||
/** |
||||
* Create a JobExcecutionException with the given message and the 're-fire |
||||
* immediately' flag set to the given value. |
||||
*/ |
||||
public JobExecutionException(String msg, boolean refireImmediately) { |
||||
super(msg); |
||||
|
||||
refire = refireImmediately; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public void setRefireImmediately(boolean refire) { |
||||
this.refire = refire; |
||||
} |
||||
|
||||
public boolean refireImmediately() { |
||||
return refire; |
||||
} |
||||
|
||||
public void setUnscheduleFiringTrigger(boolean unscheduleTrigg) { |
||||
this.unscheduleTrigg = unscheduleTrigg; |
||||
} |
||||
|
||||
public boolean unscheduleFiringTrigger() { |
||||
return unscheduleTrigg; |
||||
} |
||||
|
||||
public void setUnscheduleAllTriggers(boolean unscheduleAllTriggs) { |
||||
this.unscheduleAllTriggs = unscheduleAllTriggs; |
||||
} |
||||
|
||||
public boolean unscheduleAllTriggers() { |
||||
return unscheduleAllTriggs; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,96 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* The interface to be implemented by classes that want to be informed when a |
||||
* <code>{@link com.fr.third.org.quartz.JobDetail}</code> executes. In general, |
||||
* applications that use a <code>Scheduler</code> will not have use for this |
||||
* mechanism. |
||||
* </p> |
||||
* |
||||
* @see Scheduler |
||||
* @see Job |
||||
* @see JobExecutionContext |
||||
* @see JobExecutionException |
||||
* @see TriggerListener |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface JobListener { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name of the <code>JobListener</code>. |
||||
* </p> |
||||
*/ |
||||
String getName(); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* is about to be executed (an associated <code>{@link Trigger}</code> |
||||
* has occured). |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This method will not be invoked if the execution of the Job was vetoed |
||||
* by a <code>{@link TriggerListener}</code>. |
||||
* </p> |
||||
* |
||||
* @see #jobExecutionVetoed(JobExecutionContext) |
||||
*/ |
||||
void jobToBeExecuted(JobExecutionContext context); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* was about to be executed (an associated <code>{@link Trigger}</code> |
||||
* has occured), but a <code>{@link TriggerListener}</code> vetoed it's |
||||
* execution. |
||||
* </p> |
||||
* |
||||
* @see #jobToBeExecuted(JobExecutionContext) |
||||
*/ |
||||
void jobExecutionVetoed(JobExecutionContext context); |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> after a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* has been executed, and be for the associated <code>Trigger</code>'s |
||||
* <code>triggered(xx)</code> method has been called. |
||||
* </p> |
||||
*/ |
||||
void jobWasExecuted(JobExecutionContext context, |
||||
JobExecutionException jobException); |
||||
|
||||
} |
@ -0,0 +1,83 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that is thrown to indicate that there has been a failure in the |
||||
* scheduler's underlying persistence mechanism. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JobPersistenceException extends SchedulerException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message. |
||||
* </p> |
||||
*/ |
||||
public JobPersistenceException(String msg) { |
||||
super(msg); |
||||
setErrorCode(ERR_PERSISTENCE); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message |
||||
* and error code. |
||||
* </p> |
||||
*/ |
||||
public JobPersistenceException(String msg, int errCode) { |
||||
super(msg, errCode); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message |
||||
* and cause. |
||||
* </p> |
||||
*/ |
||||
public JobPersistenceException(String msg, Throwable cause) { |
||||
super(msg, cause); |
||||
setErrorCode(ERR_PERSISTENCE); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message, |
||||
* cause and error code. |
||||
* </p> |
||||
*/ |
||||
public JobPersistenceException(String msg, Throwable cause, int errorCode) { |
||||
super(msg, cause, errorCode); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,89 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that is thrown to indicate that an attempt to store a new |
||||
* object (i.e. <code>{@link com.fr.third.org.quartz.JobDetail}</code>,<code>{@link Trigger}</code> |
||||
* or <code>{@link Calendar}</code>) in a <code>{@link Scheduler}</code> |
||||
* failed, because one with the same name & group already exists. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class ObjectAlreadyExistsException extends JobPersistenceException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>ObjectAlreadyExistsException</code> with the given |
||||
* message. |
||||
* </p> |
||||
*/ |
||||
public ObjectAlreadyExistsException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>ObjectAlreadyExistsException</code> and auto-generate a |
||||
* message using the name/group from the given <code>JobDetail</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The message will read: <BR>"Unable to store Job with name: '__' and |
||||
* group: '__', because one already exists with this identification." |
||||
* </p> |
||||
*/ |
||||
public ObjectAlreadyExistsException(JobDetail offendingJob) { |
||||
super("Unable to store Job with name: '" + offendingJob.getName() |
||||
+ "' and group: '" + offendingJob.getGroup() |
||||
+ "', because one already exists with this identification."); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>ObjectAlreadyExistsException</code> and auto-generate a |
||||
* message using the name/group from the given <code>Trigger</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The message will read: <BR>"Unable to store Trigger with name: '__' and |
||||
* group: '__', because one already exists with this identification." |
||||
* </p> |
||||
*/ |
||||
public ObjectAlreadyExistsException(Trigger offendingTrigger) { |
||||
super("Unable to store Trigger with name: '" |
||||
+ offendingTrigger.getName() + "' and group: '" |
||||
+ offendingTrigger.getGroup() |
||||
+ "', because one already exists with this identification."); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,63 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that is thrown to indicate that there is a misconfiguration of |
||||
* the <code>SchedulerFactory</code>- or one of the components it |
||||
* configures. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerConfigException extends SchedulerException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message. |
||||
* </p> |
||||
*/ |
||||
public SchedulerConfigException(String msg) { |
||||
super(msg, ERR_BAD_CONFIGURATION); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>JobPersistenceException</code> with the given message |
||||
* and cause. |
||||
* </p> |
||||
*/ |
||||
public SchedulerConfigException(String msg, Throwable cause) { |
||||
super(msg, cause); |
||||
setErrorCode(ERR_BAD_CONFIGURATION); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,62 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Map; |
||||
|
||||
import com.fr.third.org.quartz.utils.StringKeyDirtyFlagMap; |
||||
|
||||
/** |
||||
* <p> |
||||
* Holds context/environment data that can be made available to Jobs as they |
||||
* are executed. This feature is much like the ServletContext feature when |
||||
* working with J2EE servlets. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Future versions of Quartz may make distinctions on how it propogates |
||||
* data in <code>SchedulerContext</code> between instances of proxies to a |
||||
* single scheduler instance - i.e. if Quartz is being used via RMI. |
||||
* </p> |
||||
* |
||||
* @see Scheduler#getContext |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerContext extends StringKeyDirtyFlagMap implements Serializable { |
||||
/** |
||||
* Create an empty <code>SchedulerContext</code>. |
||||
*/ |
||||
public SchedulerContext() { |
||||
super(15); |
||||
} |
||||
|
||||
/** |
||||
* Create a <code>SchedulerContext</code> with the given data. |
||||
*/ |
||||
public SchedulerContext(Map map) { |
||||
this(); |
||||
|
||||
putAll(map); |
||||
} |
||||
} |
@ -0,0 +1,335 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.io.PrintStream; |
||||
import java.io.PrintWriter; |
||||
|
||||
import com.fr.third.org.quartz.utils.ExceptionHelper; |
||||
|
||||
/** |
||||
* <p> |
||||
* Base class for exceptions thrown by the Quartz <code>{@link Scheduler}</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>SchedulerException</code> s may contain a reference to another |
||||
* <code>Exception</code>, which was the underlying cause of the <code>SchedulerException</code>. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerException extends Exception { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final int ERR_UNSPECIFIED = 0; |
||||
|
||||
public static final int ERR_BAD_CONFIGURATION = 50; |
||||
|
||||
public static final int ERR_TIME_BROKER_FAILURE = 70; |
||||
|
||||
public static final int ERR_CLIENT_ERROR = 100; |
||||
|
||||
public static final int ERR_COMMUNICATION_FAILURE = 200; |
||||
|
||||
public static final int ERR_UNSUPPORTED_FUNCTION_IN_THIS_CONFIGURATION = 210; |
||||
|
||||
public static final int ERR_PERSISTENCE = 400; |
||||
|
||||
public static final int ERR_PERSISTENCE_JOB_DOES_NOT_EXIST = 410; |
||||
|
||||
public static final int ERR_PERSISTENCE_CALENDAR_DOES_NOT_EXIST = 420; |
||||
|
||||
public static final int ERR_PERSISTENCE_TRIGGER_DOES_NOT_EXIST = 430; |
||||
|
||||
public static final int ERR_PERSISTENCE_CRITICAL_FAILURE = 499; |
||||
|
||||
public static final int ERR_THREAD_POOL = 500; |
||||
|
||||
public static final int ERR_THREAD_POOL_EXHAUSTED = 510; |
||||
|
||||
public static final int ERR_THREAD_POOL_CRITICAL_FAILURE = 599; |
||||
|
||||
public static final int ERR_JOB_LISTENER = 600; |
||||
|
||||
public static final int ERR_JOB_LISTENER_NOT_FOUND = 610; |
||||
|
||||
public static final int ERR_TRIGGER_LISTENER = 700; |
||||
|
||||
public static final int ERR_TRIGGER_LISTENER_NOT_FOUND = 710; |
||||
|
||||
public static final int ERR_JOB_EXECUTION_THREW_EXCEPTION = 800; |
||||
|
||||
public static final int ERR_TRIGGER_THREW_EXCEPTION = 850; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Throwable cause; |
||||
|
||||
private int errorCode = ERR_UNSPECIFIED; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public SchedulerException() { |
||||
super(); |
||||
} |
||||
|
||||
public SchedulerException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
public SchedulerException(String msg, int errorCode) { |
||||
super(msg); |
||||
setErrorCode(errorCode); |
||||
} |
||||
|
||||
public SchedulerException(Throwable cause) { |
||||
super(cause.toString()); |
||||
setCause(cause); |
||||
} |
||||
|
||||
public SchedulerException(String msg, Throwable cause) { |
||||
super(msg); |
||||
setCause(cause); |
||||
} |
||||
|
||||
public SchedulerException(String msg, Throwable cause, int errorCode) { |
||||
super(msg); |
||||
setCause(cause); |
||||
setErrorCode(errorCode); |
||||
} |
||||
|
||||
private void setCause(Throwable cause) { |
||||
if (ExceptionHelper.supportsNestedThrowable()) { |
||||
ExceptionHelper.setCause(this, cause); |
||||
} else { |
||||
this.cause = cause; |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Return the exception that is the underlying cause of this exception. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This may be used to find more detail about the cause of the error. |
||||
* </p> |
||||
* |
||||
* @return the underlying exception, or <code>null</code> if there is not |
||||
* one. |
||||
*/ |
||||
public Throwable getUnderlyingException() { |
||||
return (ExceptionHelper.supportsNestedThrowable()) ? |
||||
ExceptionHelper.getCause(this) : cause; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the error code associated with this exception. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This may be used to find more detail about the cause of the error. |
||||
* </p> |
||||
* |
||||
* @return one of the ERR_XXX constants defined in this class. |
||||
*/ |
||||
public int getErrorCode() { |
||||
return errorCode; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the error code associated with this exception. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This may be used to provide more detail about the cause of the error. |
||||
* </p> |
||||
* |
||||
* @param errorCode |
||||
* one of the ERR_XXX constants defined in this class. |
||||
*/ |
||||
public void setErrorCode(int errorCode) { |
||||
this.errorCode = errorCode; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_PERSISTENCE'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isPersistenceError() { |
||||
return (errorCode >= ERR_PERSISTENCE && errorCode <= ERR_PERSISTENCE + 99); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_THREAD_POOL'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isThreadPoolError() { |
||||
return (errorCode >= ERR_THREAD_POOL && errorCode <= ERR_THREAD_POOL + 99); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_JOB_LISTENER'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isJobListenerError() { |
||||
return (errorCode >= ERR_JOB_LISTENER && errorCode <= ERR_JOB_LISTENER + 99); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_TRIGGER_LISTENER'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isTriggerListenerError() { |
||||
return (errorCode >= ERR_TRIGGER_LISTENER && errorCode <= ERR_TRIGGER_LISTENER + 99); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_CLIENT_ERROR'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isClientError() { |
||||
return (errorCode >= ERR_CLIENT_ERROR && errorCode <= ERR_CLIENT_ERROR + 99); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine if the specified error code is in the <code>'ERR_CLIENT_ERROR'</code> |
||||
* category of errors. |
||||
* </p> |
||||
*/ |
||||
public boolean isConfigurationError() { |
||||
return (errorCode >= ERR_BAD_CONFIGURATION && errorCode <= ERR_BAD_CONFIGURATION + 49); |
||||
} |
||||
|
||||
public String toString() { |
||||
Throwable cause = getUnderlyingException(); |
||||
if (cause == null || cause == this) { |
||||
return super.toString(); |
||||
} else { |
||||
return super.toString() + " [See nested exception: " + cause + "]"; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <P> |
||||
* Print a stack trace to the standard error stream. |
||||
* </P> |
||||
* |
||||
* <P> |
||||
* This overridden version will print the nested stack trace if available, |
||||
* otherwise it prints only this exception's stack. |
||||
* </P> |
||||
*/ |
||||
public void printStackTrace() { |
||||
printStackTrace(System.err); |
||||
} |
||||
|
||||
/** |
||||
* <P> |
||||
* Print a stack trace to the specified stream. |
||||
* </P> |
||||
* |
||||
* <P> |
||||
* This overridden version will print the nested stack trace if available, |
||||
* otherwise it prints only this exception's stack. |
||||
* </P> |
||||
* |
||||
* @param out |
||||
* the stream to which the stack traces will be printed. |
||||
*/ |
||||
public void printStackTrace(PrintStream out) { |
||||
super.printStackTrace(out); |
||||
|
||||
if (cause != null) { |
||||
synchronized (out) { |
||||
out.println("* Nested Exception (Underlying Cause) ---------------"); |
||||
cause.printStackTrace(out); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <P> |
||||
* Print a stack trace to the specified writer. |
||||
* </P> |
||||
* |
||||
* <P> |
||||
* This overridden version will print the nested stack trace if available, |
||||
* otherwise it prints this exception's stack. |
||||
* </P> |
||||
* |
||||
* @param out |
||||
* the writer to which the stack traces will be printed. |
||||
*/ |
||||
public void printStackTrace(PrintWriter out) { |
||||
super.printStackTrace(out); |
||||
|
||||
if (cause != null) { |
||||
synchronized (out) { |
||||
out.println("* Nested Exception (Underlying Cause) ---------------"); |
||||
cause.printStackTrace(out); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,72 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* <p> |
||||
* Provides a mechanism for obtaining client-usable handles to <code>Scheduler</code> |
||||
* instances. |
||||
* </p> |
||||
* |
||||
* @see Scheduler |
||||
* @see com.fr.third.org.quartz.impl.StdSchedulerFactory |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface SchedulerFactory { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a client-usable handle to a <code>Scheduler</code>. |
||||
* </p> |
||||
* |
||||
* @throws SchedulerException |
||||
* if there is a problem with the underlying <code>Scheduler</code>. |
||||
*/ |
||||
Scheduler getScheduler() throws SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a handle to the Scheduler with the given name, if it exists. |
||||
* </p> |
||||
*/ |
||||
Scheduler getScheduler(String schedName) throws SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns handles to all known Schedulers (made by any SchedulerFactory |
||||
* within this jvm.). |
||||
* </p> |
||||
*/ |
||||
Collection getAllSchedulers() throws SchedulerException; |
||||
|
||||
} |
@ -0,0 +1,148 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* The interface to be implemented by classes that want to be informed of major |
||||
* <code>{@link Scheduler}</code> events. |
||||
* </p> |
||||
* |
||||
* @see Scheduler |
||||
* @see JobListener |
||||
* @see TriggerListener |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface SchedulerListener { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* is scheduled. |
||||
* </p> |
||||
*/ |
||||
void jobScheduled(Trigger trigger); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* is unscheduled. |
||||
* </p> |
||||
*/ |
||||
void jobUnscheduled(String triggerName, String triggerGroup); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* has reached the condition in which it will never fire again. |
||||
* </p> |
||||
*/ |
||||
void triggerFinalized(Trigger trigger); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* or group of <code>{@link Trigger}s</code> has been paused. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If a group was paused, then the <code>triggerName</code> parameter |
||||
* will be null. |
||||
* </p> |
||||
*/ |
||||
void triggersPaused(String triggerName, String triggerGroup); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* or group of <code>{@link Trigger}s</code> has been un-paused. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If a group was resumed, then the <code>triggerName</code> parameter |
||||
* will be null. |
||||
* </p> |
||||
*/ |
||||
void triggersResumed(String triggerName, String triggerGroup); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* or group of <code>{@link com.fr.third.org.quartz.JobDetail}s</code> has been |
||||
* paused. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If a group was paused, then the <code>jobName</code> parameter will be |
||||
* null. If all jobs were paused, then both parameters will be null. |
||||
* </p> |
||||
*/ |
||||
void jobsPaused(String jobName, String jobGroup); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* or group of <code>{@link com.fr.third.org.quartz.JobDetail}s</code> has been |
||||
* un-paused. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If a group was resumed, then the <code>jobName</code> parameter will |
||||
* be null. If all jobs were paused, then both parameters will be null. |
||||
* </p> |
||||
*/ |
||||
void jobsResumed(String jobName, String jobGroup); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a serious error has |
||||
* occured within the scheduler - such as repeated failures in the <code>JobStore</code>, |
||||
* or the inability to instantiate a <code>Job</code> instance when its |
||||
* <code>Trigger</code> has fired. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The <code>getErrorCode()</code> method of the given SchedulerException |
||||
* can be used to determine more specific information about the type of |
||||
* error that was encountered. |
||||
* </p> |
||||
*/ |
||||
void schedulerError(String msg, SchedulerException cause); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> to inform the listener |
||||
* that it has shutdown. |
||||
* </p> |
||||
*/ |
||||
void schedulerShutdown(); |
||||
|
||||
} |
@ -0,0 +1,350 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* <p> |
||||
* Describes the settings and capabilities of a given <code>{@link Scheduler}</code> |
||||
* instance. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerMetaData implements java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private String schedName; |
||||
|
||||
private String schedInst; |
||||
|
||||
private Class schedClass; |
||||
|
||||
private boolean isRemote; |
||||
|
||||
private boolean started; |
||||
|
||||
private boolean isInStandbyMode; |
||||
|
||||
private boolean shutdown; |
||||
|
||||
private Date startTime; |
||||
|
||||
private int numJobsExec; |
||||
|
||||
private Class jsClass; |
||||
|
||||
private boolean jsPersistent; |
||||
|
||||
private Class tpClass; |
||||
|
||||
private int tpSize; |
||||
|
||||
private String version; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public SchedulerMetaData(String schedName, String schedInst, |
||||
Class schedClass, boolean isRemote, boolean started, |
||||
boolean isInStandbyMode, boolean shutdown, Date startTime, int numJobsExec, |
||||
Class jsClass, boolean jsPersistent, Class tpClass, int tpSize, |
||||
String version) { |
||||
this.schedName = schedName; |
||||
this.schedInst = schedInst; |
||||
this.schedClass = schedClass; |
||||
this.isRemote = isRemote; |
||||
this.started = started; |
||||
this.isInStandbyMode = isInStandbyMode; |
||||
this.shutdown = shutdown; |
||||
this.startTime = startTime; |
||||
this.numJobsExec = numJobsExec; |
||||
this.jsClass = jsClass; |
||||
this.jsPersistent = jsPersistent; |
||||
this.tpClass = tpClass; |
||||
this.tpSize = tpSize; |
||||
this.version = version; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the name of the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public String getSchedulerName() { |
||||
return schedName; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the instance Id of the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public String getSchedulerInstanceId() { |
||||
return schedInst; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the class-name of the <code>Scheduler</code> instance. |
||||
* </p> |
||||
*/ |
||||
public Class getSchedulerClass() { |
||||
return schedClass; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the <code>Date</code> at which the Scheduler started running. |
||||
* </p> |
||||
* |
||||
* @return null if the scheduler has not been started. |
||||
*/ |
||||
public Date runningSince() { |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the number of jobs executed since the <code>Scheduler</code> |
||||
* started.. |
||||
* </p> |
||||
*/ |
||||
public int numJobsExecuted() { |
||||
return numJobsExec; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns whether the <code>Scheduler</code> is being used remotely (via |
||||
* RMI). |
||||
* </p> |
||||
*/ |
||||
public boolean isSchedulerRemote() { |
||||
return isRemote; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns whether the scheduler has been started. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note: <code>isStarted()</code> may return <code>true</code> even if |
||||
* <code>isInStandbyMode()</code> returns <code>true</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean isStarted() { |
||||
return started; |
||||
} |
||||
|
||||
/** |
||||
* Reports whether the <code>Scheduler</code> is in standby mode. |
||||
*/ |
||||
public boolean isInStandbyMode() { |
||||
return isInStandbyMode; |
||||
} |
||||
|
||||
/** |
||||
* Reports whether the <code>Scheduler</code> is paused. |
||||
* |
||||
* @deprecated Please use <code>{@link #isInStandbyMode()}</code>. |
||||
* |
||||
* @see #isInStandbyMode() |
||||
*/ |
||||
public boolean isPaused() { |
||||
return isInStandbyMode(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Reports whether the <code>Scheduler</code> has been shutdown. |
||||
* </p> |
||||
*/ |
||||
public boolean isShutdown() { |
||||
return shutdown; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the class-name of the <code>JobStore</code> instance that is |
||||
* being used by the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public Class getJobStoreClass() { |
||||
return jsClass; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns whether or not the <code>Scheduler</code>'s<code>JobStore</code> |
||||
* instance supports persistence. |
||||
* </p> |
||||
*/ |
||||
public boolean jobStoreSupportsPersistence() { |
||||
return jsPersistent; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the class-name of the <code>ThreadPool</code> instance that is |
||||
* being used by the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public Class getThreadPoolClass() { |
||||
return tpClass; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the number of threads currently in the <code>Scheduler</code>'s |
||||
* <code>ThreadPool</code>. |
||||
* </p> |
||||
*/ |
||||
public int getThreadPoolSize() { |
||||
return tpSize; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the version of Quartz that is running. |
||||
* </p> |
||||
*/ |
||||
public String getVersion() { |
||||
return version; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return a simple string representation of this object. |
||||
* </p> |
||||
*/ |
||||
public String toString() { |
||||
try { |
||||
return getSummary(); |
||||
} catch (SchedulerException se) { |
||||
return "SchedulerMetaData: undeterminable."; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a formatted (human readable) String describing all the <code>Scheduler</code>'s |
||||
* meta-data values. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The format of the String looks something like this: |
||||
* |
||||
* <pre> |
||||
* |
||||
* |
||||
* Quartz Scheduler 'SchedulerName' with instanceId 'SchedulerInstanceId' Scheduler class: 'com.fr.third.org.quartz.impl.StdScheduler' - running locally. Running since: '11:33am on Jul 19, 2002' Not currently paused. Number of Triggers fired: '123' Using thread pool 'com.fr.third.org.quartz.simpl.SimpleThreadPool' - with '8' threads Using job-store 'com.fr.third.org.quartz.impl.JDBCJobStore' - which supports persistence. |
||||
* </pre> |
||||
* |
||||
* </p> |
||||
*/ |
||||
public String getSummary() throws SchedulerException { |
||||
StringBuffer str = new StringBuffer("Quartz Scheduler (v"); |
||||
str.append(getVersion()); |
||||
str.append(") '"); |
||||
|
||||
str.append(getSchedulerName()); |
||||
str.append("' with instanceId '"); |
||||
str.append(getSchedulerInstanceId()); |
||||
str.append("'\n"); |
||||
|
||||
str.append(" Scheduler class: '"); |
||||
str.append(getSchedulerClass().getName()); |
||||
str.append("'"); |
||||
if (isSchedulerRemote()) { |
||||
str.append(" - access via RMI."); |
||||
} else { |
||||
str.append(" - running locally."); |
||||
} |
||||
str.append("\n"); |
||||
|
||||
if (!isShutdown()) { |
||||
if (runningSince() != null) { |
||||
str.append(" Running since: "); |
||||
str.append(runningSince()); |
||||
} else { |
||||
str.append("NOT STARTED."); |
||||
} |
||||
str.append("\n"); |
||||
|
||||
if (isInStandbyMode()) { |
||||
str.append(" Currently in standby mode."); |
||||
} else { |
||||
str.append(" Not currently in standby mode."); |
||||
} |
||||
} else { |
||||
str.append(" Scheduler has been SHUTDOWN."); |
||||
} |
||||
str.append("\n"); |
||||
|
||||
str.append(" Number of jobs executed: "); |
||||
str.append(numJobsExecuted()); |
||||
str.append("\n"); |
||||
|
||||
str.append(" Using thread pool '"); |
||||
str.append(getThreadPoolClass().getName()); |
||||
str.append("' - with "); |
||||
str.append(getThreadPoolSize()); |
||||
str.append(" threads."); |
||||
str.append("\n"); |
||||
|
||||
str.append(" Using job-store '"); |
||||
str.append(getJobStoreClass().getName()); |
||||
str.append("' - which "); |
||||
if (jobStoreSupportsPersistence()) { |
||||
str.append("supports persistence."); |
||||
} else { |
||||
str.append("does not support persistence."); |
||||
} |
||||
str.append("\n"); |
||||
|
||||
return str.toString(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,955 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
import java.util.Date; |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* A concrete <code>{@link Trigger}</code> that is used to fire a <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* at a given moment in time, and optionally repeated at a specified interval. |
||||
* </p> |
||||
* |
||||
* @see Trigger |
||||
* @see CronTrigger |
||||
* @see TriggerUtils |
||||
* |
||||
* @author James House |
||||
* @author contributions by Lieven Govaerts of Ebitec Nv, Belgium. |
||||
*/ |
||||
public class SimpleTrigger extends Trigger { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Required for serialization support. Introduced in Quartz 1.6.1 to |
||||
* maintain compatibility after the introduction of hasAdditionalProperties |
||||
* method. |
||||
* |
||||
* @see java.io.Serializable |
||||
*/ |
||||
private static final long serialVersionUID = -3735980074222850397L; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>{@link Scheduler}</code> that upon a mis-fire |
||||
* situation, the <code>{@link SimpleTrigger}</code> wants to be fired |
||||
* now by <code>Scheduler</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE:</i> This instruction should typically only be used for |
||||
* 'one-shot' (non-repeating) Triggers. If it is used on a trigger with a |
||||
* repeat count > 0 then it is equivalent to the instruction <code>{@link #MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT} |
||||
* </code>. |
||||
* </p> |
||||
*/ |
||||
public static final int MISFIRE_INSTRUCTION_FIRE_NOW = 1; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>{@link Scheduler}</code> that upon a mis-fire |
||||
* situation, the <code>{@link SimpleTrigger}</code> wants to be |
||||
* re-scheduled to 'now' (even if the associated <code>{@link Calendar}</code> |
||||
* excludes 'now') with the repeat count left as-is. This does obey the |
||||
* <code>Trigger</code> end-time however, so if 'now' is after the |
||||
* end-time the <code>Trigger</code> will not fire again. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE:</i> Use of this instruction causes the trigger to 'forget' |
||||
* the start-time and repeat-count that it was originally setup with (this |
||||
* is only an issue if you for some reason wanted to be able to tell what |
||||
* the original values were at some later time). |
||||
* </p> |
||||
*/ |
||||
public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>{@link Scheduler}</code> that upon a mis-fire |
||||
* situation, the <code>{@link SimpleTrigger}</code> wants to be |
||||
* re-scheduled to 'now' (even if the associated <code>{@link Calendar}</code> |
||||
* excludes 'now') with the repeat count set to what it would be, if it had |
||||
* not missed any firings. This does obey the <code>Trigger</code> end-time |
||||
* however, so if 'now' is after the end-time the <code>Trigger</code> will |
||||
* not fire again. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE:</i> Use of this instruction causes the trigger to 'forget' |
||||
* the start-time and repeat-count that it was originally setup with. |
||||
* Instead, the repeat count on the trigger will be changed to whatever |
||||
* the remaining repeat count is (this is only an issue if you for some |
||||
* reason wanted to be able to tell what the original values were at some |
||||
* later time). |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE:</i> This instruction could cause the <code>Trigger</code> |
||||
* to go to the 'COMPLETE' state after firing 'now', if all the |
||||
* repeat-fire-times where missed. |
||||
* </p> |
||||
*/ |
||||
public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>{@link Scheduler}</code> that upon a mis-fire |
||||
* situation, the <code>{@link SimpleTrigger}</code> wants to be |
||||
* re-scheduled to the next scheduled time after 'now' - taking into |
||||
* account any associated <code>{@link Calendar}</code>, and with the |
||||
* repeat count set to what it would be, if it had not missed any firings. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE/WARNING:</i> This instruction could cause the <code>Trigger</code> |
||||
* to go directly to the 'COMPLETE' state if all fire-times where missed. |
||||
* </p> |
||||
*/ |
||||
public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instructs the <code>{@link Scheduler}</code> that upon a mis-fire |
||||
* situation, the <code>{@link SimpleTrigger}</code> wants to be |
||||
* re-scheduled to the next scheduled time after 'now' - taking into |
||||
* account any associated <code>{@link Calendar}</code>, and with the |
||||
* repeat count left unchanged. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <i>NOTE/WARNING:</i> This instruction could cause the <code>Trigger</code> |
||||
* to go directly to the 'COMPLETE' state if the end-time of the trigger |
||||
* has arrived. |
||||
* </p> |
||||
*/ |
||||
public static final int MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5; |
||||
|
||||
/** |
||||
* <p> |
||||
* Used to indicate the 'repeat count' of the trigger is indefinite. Or in |
||||
* other words, the trigger should repeat continually until the trigger's |
||||
* ending timestamp. |
||||
* </p> |
||||
*/ |
||||
public static final int REPEAT_INDEFINITELY = -1; |
||||
|
||||
private static final int YEAR_TO_GIVEUP_SCHEDULING_AT = 2299; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Date startTime = null; |
||||
|
||||
private Date endTime = null; |
||||
|
||||
private Date nextFireTime = null; |
||||
|
||||
private Date previousFireTime = null; |
||||
|
||||
private int repeatCount = 0; |
||||
|
||||
private long repeatInterval = 0; |
||||
|
||||
private int timesTriggered = 0; |
||||
|
||||
private boolean complete = false; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> with no settings. |
||||
* </p> |
||||
*/ |
||||
public SimpleTrigger() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> that will occur immediately, and |
||||
* not repeat. |
||||
* </p> |
||||
*/ |
||||
public SimpleTrigger(String name, String group) { |
||||
this(name, group, new Date(), null, 0, 0); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> that will occur immediately, and |
||||
* repeat at the the given interval the given number of times. |
||||
* </p> |
||||
*/ |
||||
public SimpleTrigger(String name, String group, int repeatCount, |
||||
long repeatInterval) { |
||||
this(name, group, new Date(), null, repeatCount, repeatInterval); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> that will occur at the given time, |
||||
* and not repeat. |
||||
* </p> |
||||
*/ |
||||
public SimpleTrigger(String name, String group, Date startTime) { |
||||
this(name, group, startTime, null, 0, 0); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> that will occur at the given time, |
||||
* and repeat at the the given interval the given number of times, or until |
||||
* the given end time. |
||||
* </p> |
||||
* |
||||
* @param startTime |
||||
* A <code>Date</code> set to the time for the <code>Trigger</code> |
||||
* to fire. |
||||
* @param endTime |
||||
* A <code>Date</code> set to the time for the <code>Trigger</code> |
||||
* to quit repeat firing. |
||||
* @param repeatCount |
||||
* The number of times for the <code>Trigger</code> to repeat |
||||
* firing, use {@link #REPEAT_INDEFINITELY} for unlimited times. |
||||
* @param repeatInterval |
||||
* The number of milliseconds to pause between the repeat firing. |
||||
*/ |
||||
public SimpleTrigger(String name, String group, Date startTime, |
||||
Date endTime, int repeatCount, long repeatInterval) { |
||||
super(name, group); |
||||
|
||||
setStartTime(startTime); |
||||
setEndTime(endTime); |
||||
setRepeatCount(repeatCount); |
||||
setRepeatInterval(repeatInterval); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>SimpleTrigger</code> that will occur at the given time, |
||||
* fire the identified <code>Job</code> and repeat at the the given |
||||
* interval the given number of times, or until the given end time. |
||||
* </p> |
||||
* |
||||
* @param startTime |
||||
* A <code>Date</code> set to the time for the <code>Trigger</code> |
||||
* to fire. |
||||
* @param endTime |
||||
* A <code>Date</code> set to the time for the <code>Trigger</code> |
||||
* to quit repeat firing. |
||||
* @param repeatCount |
||||
* The number of times for the <code>Trigger</code> to repeat |
||||
* firing, use {@link #REPEAT_INDEFINITELY}for unlimitted times. |
||||
* @param repeatInterval |
||||
* The number of milliseconds to pause between the repeat firing. |
||||
*/ |
||||
public SimpleTrigger(String name, String group, String jobName, |
||||
String jobGroup, Date startTime, Date endTime, int repeatCount, |
||||
long repeatInterval) { |
||||
super(name, group, jobName, jobGroup); |
||||
|
||||
setStartTime(startTime); |
||||
setEndTime(endTime); |
||||
setRepeatCount(repeatCount); |
||||
setRepeatInterval(repeatInterval); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the time at which the <code>SimpleTrigger</code> should occur. |
||||
* </p> |
||||
*/ |
||||
public Date getStartTime() { |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the time at which the <code>SimpleTrigger</code> should occur. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if startTime is <code>null</code>. |
||||
*/ |
||||
public void setStartTime(Date startTime) { |
||||
if (startTime == null) { |
||||
throw new IllegalArgumentException("Start time cannot be null"); |
||||
} |
||||
|
||||
Date eTime = getEndTime(); |
||||
if (eTime != null && startTime != null && eTime.before(startTime)) { |
||||
throw new IllegalArgumentException( |
||||
"End time cannot be before start time"); |
||||
} |
||||
|
||||
this.startTime = startTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the time at which the <code>SimpleTrigger</code> should quit |
||||
* repeating - even if repeastCount isn't yet satisfied. |
||||
* </p> |
||||
* |
||||
* @see #getFinalFireTime() |
||||
*/ |
||||
public Date getEndTime() { |
||||
return endTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the time at which the <code>SimpleTrigger</code> should quit |
||||
* repeating (and be automatically deleted). |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if endTime is before start time. |
||||
*/ |
||||
public void setEndTime(Date endTime) { |
||||
Date sTime = getStartTime(); |
||||
if (sTime != null && endTime != null && sTime.after(endTime)) { |
||||
throw new IllegalArgumentException( |
||||
"End time cannot be before start time"); |
||||
} |
||||
|
||||
this.endTime = endTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the the number of times the <code>SimpleTrigger</code> should |
||||
* repeat, after which it will be automatically deleted. |
||||
* </p> |
||||
* |
||||
* @see #REPEAT_INDEFINITELY |
||||
*/ |
||||
public int getRepeatCount() { |
||||
return repeatCount; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the the number of time the <code>SimpleTrigger</code> should |
||||
* repeat, after which it will be automatically deleted. |
||||
* </p> |
||||
* |
||||
* @see #REPEAT_INDEFINITELY |
||||
* @exception IllegalArgumentException |
||||
* if repeatCount is < 0 |
||||
*/ |
||||
public void setRepeatCount(int repeatCount) { |
||||
if (repeatCount < 0 && repeatCount != REPEAT_INDEFINITELY) { |
||||
throw new IllegalArgumentException( |
||||
"Repeat count must be >= 0, use the " |
||||
+ "constant REPEAT_INDEFINITELY for infinite."); |
||||
} |
||||
|
||||
this.repeatCount = repeatCount; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the the time interval (in milliseconds) at which the <code>SimpleTrigger</code> |
||||
* should repeat. |
||||
* </p> |
||||
*/ |
||||
public long getRepeatInterval() { |
||||
return repeatInterval; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the the time interval (in milliseconds) at which the <code>SimpleTrigger</code> |
||||
* should repeat. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if repeatInterval is <= 0 |
||||
*/ |
||||
public void setRepeatInterval(long repeatInterval) { |
||||
if (repeatInterval < 0) { |
||||
throw new IllegalArgumentException( |
||||
"Repeat interval must be >= 0"); |
||||
} |
||||
|
||||
this.repeatInterval = repeatInterval; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the number of times the <code>SimpleTrigger</code> has already |
||||
* fired. |
||||
* </p> |
||||
*/ |
||||
public int getTimesTriggered() { |
||||
return timesTriggered; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the number of times the <code>SimpleTrigger</code> has already |
||||
* fired. |
||||
* </p> |
||||
*/ |
||||
public void setTimesTriggered(int timesTriggered) { |
||||
this.timesTriggered = timesTriggered; |
||||
} |
||||
|
||||
protected boolean validateMisfireInstruction(int misfireInstruction) { |
||||
if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) { |
||||
return false; |
||||
} |
||||
|
||||
if (misfireInstruction > MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Updates the <code>SimpleTrigger</code>'s state based on the |
||||
* MISFIRE_INSTRUCTION_XXX that was selected when the <code>SimpleTrigger</code> |
||||
* was created. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, |
||||
* then the following scheme will be used: <br> |
||||
* <ul> |
||||
* <li>If the Repeat Count is <code>0</code>, then the instruction will |
||||
* be interpreted as <code>MISFIRE_INSTRUCTION_FIRE_NOW</code>.</li> |
||||
* <li>If the Repeat Count is <code>REPEAT_INDEFINITELY</code>, then |
||||
* the instruction will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT</code>. |
||||
* <b>WARNING:</b> using MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT |
||||
* with a trigger that has a non-null end-time may cause the trigger to |
||||
* never fire again if the end-time arrived during the misfire time span. |
||||
* </li> |
||||
* <li>If the Repeat Count is <code>> 0</code>, then the instruction |
||||
* will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>. |
||||
* </li> |
||||
* </ul> |
||||
* </p> |
||||
*/ |
||||
public void updateAfterMisfire(Calendar cal) { |
||||
int instr = getMisfireInstruction(); |
||||
if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) { |
||||
if (getRepeatCount() == 0) { |
||||
instr = MISFIRE_INSTRUCTION_FIRE_NOW; |
||||
} else if (getRepeatCount() == REPEAT_INDEFINITELY) { |
||||
instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT; |
||||
} else { |
||||
// if (getRepeatCount() > 0)
|
||||
instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT; |
||||
} |
||||
} else if (instr == MISFIRE_INSTRUCTION_FIRE_NOW && getRepeatCount() != 0) { |
||||
instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT; |
||||
} |
||||
|
||||
if (instr == MISFIRE_INSTRUCTION_FIRE_NOW) { |
||||
setNextFireTime(new Date()); |
||||
} else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) { |
||||
Date newFireTime = getFireTimeAfter(new Date()); |
||||
while (newFireTime != null && cal != null |
||||
&& !cal.isTimeIncluded(newFireTime.getTime())) { |
||||
newFireTime = getFireTimeAfter(newFireTime); |
||||
|
||||
if(newFireTime == null) |
||||
break; |
||||
|
||||
//avoid infinite loop
|
||||
java.util.Calendar c = java.util.Calendar.getInstance(); |
||||
c.setTime(newFireTime); |
||||
if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { |
||||
newFireTime = null; |
||||
} |
||||
} |
||||
setNextFireTime(newFireTime); |
||||
} else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT) { |
||||
Date newFireTime = getFireTimeAfter(new Date()); |
||||
while (newFireTime != null && cal != null |
||||
&& !cal.isTimeIncluded(newFireTime.getTime())) { |
||||
newFireTime = getFireTimeAfter(newFireTime); |
||||
|
||||
if(newFireTime == null) |
||||
break; |
||||
|
||||
//avoid infinite loop
|
||||
java.util.Calendar c = java.util.Calendar.getInstance(); |
||||
c.setTime(newFireTime); |
||||
if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { |
||||
newFireTime = null; |
||||
} |
||||
} |
||||
if (newFireTime != null) { |
||||
int timesMissed = computeNumTimesFiredBetween(nextFireTime, |
||||
newFireTime); |
||||
setTimesTriggered(getTimesTriggered() + timesMissed); |
||||
} |
||||
|
||||
setNextFireTime(newFireTime); |
||||
} else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT) { |
||||
Date newFireTime = new Date(); |
||||
if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { |
||||
setRepeatCount(getRepeatCount() - getTimesTriggered()); |
||||
setTimesTriggered(0); |
||||
} |
||||
|
||||
if (getEndTime() != null && getEndTime().before(newFireTime)) { |
||||
setNextFireTime(null); // We are past the end time
|
||||
} else { |
||||
setStartTime(newFireTime); |
||||
setNextFireTime(newFireTime); |
||||
} |
||||
} else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT) { |
||||
Date newFireTime = new Date(); |
||||
|
||||
int timesMissed = computeNumTimesFiredBetween(nextFireTime, |
||||
newFireTime); |
||||
|
||||
if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { |
||||
int remainingCount = getRepeatCount() |
||||
- (getTimesTriggered() + timesMissed); |
||||
if (remainingCount <= 0) { |
||||
remainingCount = 0; |
||||
} |
||||
setRepeatCount(remainingCount); |
||||
setTimesTriggered(0); |
||||
} |
||||
|
||||
if (getEndTime() != null && getEndTime().before(newFireTime)) { |
||||
setNextFireTime(null); // We are past the end time
|
||||
} else { |
||||
setStartTime(newFireTime); |
||||
setNextFireTime(newFireTime); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called when the <code>{@link Scheduler}</code> has decided to 'fire' |
||||
* the trigger (execute the associated <code>Job</code>), in order to |
||||
* give the <code>Trigger</code> a chance to update itself for its next |
||||
* triggering (if any). |
||||
* </p> |
||||
* |
||||
* @see #executionComplete(JobExecutionContext, JobExecutionException) |
||||
*/ |
||||
public void triggered(Calendar calendar) { |
||||
timesTriggered++; |
||||
previousFireTime = nextFireTime; |
||||
nextFireTime = getFireTimeAfter(nextFireTime); |
||||
|
||||
while (nextFireTime != null && calendar != null |
||||
&& !calendar.isTimeIncluded(nextFireTime.getTime())) { |
||||
|
||||
nextFireTime = getFireTimeAfter(nextFireTime); |
||||
|
||||
if(nextFireTime == null) |
||||
break; |
||||
|
||||
//avoid infinite loop
|
||||
java.util.Calendar c = java.util.Calendar.getInstance(); |
||||
c.setTime(nextFireTime); |
||||
if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { |
||||
nextFireTime = null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @see com.fr.third.org.quartz.Trigger#updateWithNewCalendar(com.fr.third.org.quartz.Calendar, long) |
||||
*/ |
||||
public void updateWithNewCalendar(Calendar calendar, long misfireThreshold) |
||||
{ |
||||
nextFireTime = getFireTimeAfter(previousFireTime); |
||||
|
||||
if (nextFireTime == null || calendar == null) { |
||||
return; |
||||
} |
||||
|
||||
Date now = new Date(); |
||||
while (nextFireTime != null && !calendar.isTimeIncluded(nextFireTime.getTime())) { |
||||
|
||||
nextFireTime = getFireTimeAfter(nextFireTime); |
||||
|
||||
if(nextFireTime == null) |
||||
break; |
||||
|
||||
//avoid infinite loop
|
||||
java.util.Calendar c = java.util.Calendar.getInstance(); |
||||
c.setTime(nextFireTime); |
||||
if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { |
||||
nextFireTime = null; |
||||
} |
||||
|
||||
if(nextFireTime != null && nextFireTime.before(now)) { |
||||
long diff = now.getTime() - nextFireTime.getTime(); |
||||
if(diff >= misfireThreshold) { |
||||
nextFireTime = getFireTimeAfter(nextFireTime); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the scheduler at the time a <code>Trigger</code> is first |
||||
* added to the scheduler, in order to have the <code>Trigger</code> |
||||
* compute its first fire time, based on any associated calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* After this method has been called, <code>getNextFireTime()</code> |
||||
* should return a valid answer. |
||||
* </p> |
||||
* |
||||
* @return the first time at which the <code>Trigger</code> will be fired |
||||
* by the scheduler, which is also the same value <code>getNextFireTime()</code> |
||||
* will return (until after the first firing of the <code>Trigger</code>). |
||||
* </p> |
||||
*/ |
||||
public Date computeFirstFireTime(Calendar calendar) { |
||||
nextFireTime = getStartTime(); |
||||
|
||||
while (nextFireTime != null && calendar != null |
||||
&& !calendar.isTimeIncluded(nextFireTime.getTime())) { |
||||
nextFireTime = getFireTimeAfter(nextFireTime); |
||||
|
||||
if(nextFireTime == null) |
||||
break; |
||||
|
||||
//avoid infinite loop
|
||||
java.util.Calendar c = java.util.Calendar.getInstance(); |
||||
c.setTime(nextFireTime); |
||||
if (c.get(java.util.Calendar.YEAR) > YEAR_TO_GIVEUP_SCHEDULING_AT) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
return nextFireTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called after the <code>{@link Scheduler}</code> has executed the |
||||
* <code>{@link com.fr.third.org.quartz.JobDetail}</code> associated with the <code>Trigger</code> |
||||
* in order to get the final instruction code from the trigger. |
||||
* </p> |
||||
* |
||||
* @param context |
||||
* is the <code>JobExecutionContext</code> that was used by the |
||||
* <code>Job</code>'s<code>execute(xx)</code> method. |
||||
* @param result |
||||
* is the <code>JobExecutionException</code> thrown by the |
||||
* <code>Job</code>, if any (may be null). |
||||
* @return one of the Trigger.INSTRUCTION_XXX constants. |
||||
* |
||||
* @see #INSTRUCTION_NOOP |
||||
* @see #INSTRUCTION_RE_EXECUTE_JOB |
||||
* @see #INSTRUCTION_DELETE_TRIGGER |
||||
* @see #INSTRUCTION_SET_TRIGGER_COMPLETE |
||||
* @see #triggered(Calendar) |
||||
*/ |
||||
public int executionComplete(JobExecutionContext context, |
||||
JobExecutionException result) { |
||||
if (result != null && result.refireImmediately()) { |
||||
return INSTRUCTION_RE_EXECUTE_JOB; |
||||
} |
||||
|
||||
if (result != null && result.unscheduleFiringTrigger()) { |
||||
return INSTRUCTION_SET_TRIGGER_COMPLETE; |
||||
} |
||||
|
||||
if (result != null && result.unscheduleAllTriggers()) { |
||||
return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE; |
||||
} |
||||
|
||||
if (!mayFireAgain()) { |
||||
return INSTRUCTION_DELETE_TRIGGER; |
||||
} |
||||
|
||||
return INSTRUCTION_NOOP; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the next time at which the <code>Trigger</code> is scheduled to fire. If |
||||
* the trigger will not fire again, <code>null</code> will be returned. Note that |
||||
* the time returned can possibly be in the past, if the time that was computed |
||||
* for the trigger to next fire has already arrived, but the scheduler has not yet |
||||
* been able to fire the trigger (which would likely be due to lack of resources |
||||
* e.g. threads). |
||||
* </p> |
||||
* |
||||
* <p>The value returned is not guaranteed to be valid until after the <code>Trigger</code> |
||||
* has been added to the scheduler. |
||||
* </p> |
||||
* |
||||
* @see TriggerUtils#computeFireTimesBetween(Trigger, Calendar, Date, Date) |
||||
*/ |
||||
public Date getNextFireTime() { |
||||
return nextFireTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the previous time at which the <code>SimpleTrigger</code> |
||||
* fired. If the trigger has not yet fired, <code>null</code> will be |
||||
* returned. |
||||
*/ |
||||
public Date getPreviousFireTime() { |
||||
return previousFireTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the next time at which the <code>SimpleTrigger</code> should fire. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <b>This method should not be invoked by client code.</b> |
||||
* </p> |
||||
*/ |
||||
public void setNextFireTime(Date nextFireTime) { |
||||
this.nextFireTime = nextFireTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the previous time at which the <code>SimpleTrigger</code> fired. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <b>This method should not be invoked by client code.</b> |
||||
* </p> |
||||
*/ |
||||
public void setPreviousFireTime(Date previousFireTime) { |
||||
this.previousFireTime = previousFireTime; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the next time at which the <code>SimpleTrigger</code> will |
||||
* fire, after the given time. If the trigger will not fire after the given |
||||
* time, <code>null</code> will be returned. |
||||
* </p> |
||||
*/ |
||||
public Date getFireTimeAfter(Date afterTime) { |
||||
if (complete) { |
||||
return null; |
||||
} |
||||
|
||||
if ((timesTriggered > repeatCount) |
||||
&& (repeatCount != REPEAT_INDEFINITELY)) { |
||||
return null; |
||||
} |
||||
|
||||
if (afterTime == null) { |
||||
afterTime = new Date(); |
||||
} |
||||
|
||||
if (repeatCount == 0 && afterTime.compareTo(getStartTime()) >= 0) { |
||||
return null; |
||||
} |
||||
|
||||
long startMillis = getStartTime().getTime(); |
||||
long afterMillis = afterTime.getTime(); |
||||
long endMillis = (getEndTime() == null) ? Long.MAX_VALUE : getEndTime() |
||||
.getTime(); |
||||
|
||||
if (endMillis <= afterMillis) { |
||||
return null; |
||||
} |
||||
|
||||
if (afterMillis < startMillis) { |
||||
return new Date(startMillis); |
||||
} |
||||
|
||||
long numberOfTimesExecuted = ((afterMillis - startMillis) / repeatInterval) + 1; |
||||
|
||||
if ((numberOfTimesExecuted > repeatCount) && |
||||
(repeatCount != REPEAT_INDEFINITELY)) { |
||||
return null; |
||||
} |
||||
|
||||
Date time = new Date(startMillis + (numberOfTimesExecuted * repeatInterval)); |
||||
|
||||
if (endMillis <= time.getTime()) { |
||||
return null; |
||||
} |
||||
|
||||
return time; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the last time at which the <code>SimpleTrigger</code> will |
||||
* fire, before the given time. If the trigger will not fire before the |
||||
* given time, <code>null</code> will be returned. |
||||
* </p> |
||||
*/ |
||||
public Date getFireTimeBefore(Date end) { |
||||
if (end.getTime() < getStartTime().getTime()) { |
||||
return null; |
||||
} |
||||
|
||||
int numFires = computeNumTimesFiredBetween(getStartTime(), end); |
||||
|
||||
return new Date(getStartTime().getTime() + (numFires * repeatInterval)); |
||||
} |
||||
|
||||
public int computeNumTimesFiredBetween(Date start, Date end) { |
||||
|
||||
if(repeatInterval < 1) { |
||||
return 0; |
||||
} |
||||
|
||||
long time = end.getTime() - start.getTime(); |
||||
|
||||
return (int) (time / repeatInterval); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the final time at which the <code>SimpleTrigger</code> will |
||||
* fire, if repeatCount is REPEAT_INDEFINITELY, null will be returned. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that the return time may be in the past. |
||||
* </p> |
||||
*/ |
||||
public Date getFinalFireTime() { |
||||
if (repeatCount == 0) { |
||||
return startTime; |
||||
} |
||||
|
||||
if (repeatCount == REPEAT_INDEFINITELY) { |
||||
return (getEndTime() == null) ? null : getFireTimeBefore(getEndTime()); |
||||
} |
||||
|
||||
long lastTrigger = startTime.getTime() + (repeatCount * repeatInterval); |
||||
|
||||
if ((getEndTime() == null) || (lastTrigger < getEndTime().getTime())) { |
||||
return new Date(lastTrigger); |
||||
} else { |
||||
return getFireTimeBefore(getEndTime()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determines whether or not the <code>SimpleTrigger</code> will occur |
||||
* again. |
||||
* </p> |
||||
*/ |
||||
public boolean mayFireAgain() { |
||||
return (getNextFireTime() != null); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Validates whether the properties of the <code>JobDetail</code> are |
||||
* valid for submission into a <code>Scheduler</code>. |
||||
* |
||||
* @throws IllegalStateException |
||||
* if a required property (such as Name, Group, Class) is not |
||||
* set. |
||||
*/ |
||||
public void validate() throws SchedulerException { |
||||
super.validate(); |
||||
|
||||
if (repeatCount != 0 && repeatInterval < 1) { |
||||
throw new SchedulerException("Repeat Interval cannot be zero.", |
||||
SchedulerException.ERR_CLIENT_ERROR); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Used by extensions of SimpleTrigger to imply that there are additional |
||||
* properties, specifically so that extensions can choose whether to be |
||||
* stored as a serialized blob, or as a flattened SimpleTrigger table. |
||||
*/ |
||||
public boolean hasAdditionalProperties() { |
||||
return false; |
||||
} |
||||
|
||||
public static void main(String[] args) // TODO: remove method after good
|
||||
// unit testing
|
||||
throws Exception { |
||||
|
||||
Date sdt = new Date(); |
||||
|
||||
Date edt = new Date(sdt.getTime() + 55000L); |
||||
|
||||
SimpleTrigger st = new SimpleTrigger("t", "g", "j", "g", sdt, edt, 10, |
||||
10000L); |
||||
|
||||
System.err.println(); |
||||
|
||||
st.computeFirstFireTime(null); |
||||
|
||||
System.err.println("lastTime=" + st.getFinalFireTime()); |
||||
|
||||
java.util.List times = TriggerUtils.computeFireTimes(st, null, 50); |
||||
|
||||
for (int i = 0; i < times.size(); i++) { |
||||
System.err.println("firetime = " + times.get(i)); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,57 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* A marker interface for <code>{@link com.fr.third.org.quartz.JobDetail}</code> s that |
||||
* wish to have their state maintained between executions. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <code>StatefulJob</code> instances follow slightly different rules from |
||||
* regular <code>Job</code> instances. The key difference is that their |
||||
* associated <code>{@link JobDataMap}</code> is re-persisted after every |
||||
* execution of the job, thus preserving state for the next execution. The |
||||
* other difference is that stateful jobs are not allowed to execute |
||||
* concurrently, which means new triggers that occur before the completion of |
||||
* the <code>execute(xx)</code> method will be delayed. |
||||
* </p> |
||||
* |
||||
* @see Job |
||||
* @see JobDetail |
||||
* @see JobDataMap |
||||
* @see Scheduler |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface StatefulJob extends Job { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,134 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* The interface to be implemented by classes that want to be informed when a |
||||
* <code>{@link Trigger}</code> fires. In general, applications that use a |
||||
* <code>Scheduler</code> will not have use for this mechanism. |
||||
* </p> |
||||
* |
||||
* @see Scheduler |
||||
* @see Trigger |
||||
* @see JobListener |
||||
* @see JobExecutionContext |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface TriggerListener { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name of the <code>TriggerListener</code>. |
||||
* </p> |
||||
*/ |
||||
String getName(); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* has fired, and it's associated <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* is about to be executed. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* It is called before the <code>vetoJobExecution(..)</code> method of this |
||||
* interface. |
||||
* </p> |
||||
* |
||||
* @param trigger |
||||
* The <code>Trigger</code> that has fired. |
||||
* @param context |
||||
* The <code>JobExecutionContext</code> that will be passed to |
||||
* the <code>Job</code>'s<code>execute(xx)</code> method. |
||||
*/ |
||||
void triggerFired(Trigger trigger, JobExecutionContext context); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* has fired, and it's associated <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* is about to be executed. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* It is called after the <code>triggerFired(..)</code> method of this |
||||
* interface. |
||||
* </p> |
||||
* |
||||
* @param trigger |
||||
* The <code>Trigger</code> that has fired. |
||||
* @param context |
||||
* The <code>JobExecutionContext</code> that will be passed to |
||||
* the <code>Job</code>'s<code>execute(xx)</code> method. |
||||
*/ |
||||
boolean vetoJobExecution(Trigger trigger, JobExecutionContext context); |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* has misfired. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Consideration should be given to how much time is spent in this method, |
||||
* as it will affect all triggers that are misfiring. If you have lots |
||||
* of triggers misfiring at once, it could be an issue it this method |
||||
* does a lot. |
||||
* </p> |
||||
* |
||||
* @param trigger |
||||
* The <code>Trigger</code> that has misfired. |
||||
*/ |
||||
void triggerMisfired(Trigger trigger); |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> |
||||
* has fired, it's associated <code>{@link com.fr.third.org.quartz.JobDetail}</code> |
||||
* has been executed, and it's <code>triggered(xx)</code> method has been |
||||
* called. |
||||
* </p> |
||||
* |
||||
* @param trigger |
||||
* The <code>Trigger</code> that was fired. |
||||
* @param context |
||||
* The <code>JobExecutionContext</code> that was passed to the |
||||
* <code>Job</code>'s<code>execute(xx)</code> method. |
||||
* @param triggerInstructionCode |
||||
* the result of the call on the <code>Trigger</code>'s<code>triggered(xx)</code> |
||||
* method. |
||||
*/ |
||||
void triggerComplete(Trigger trigger, JobExecutionContext context, |
||||
int triggerInstructionCode); |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,63 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz; |
||||
|
||||
/** |
||||
* <p> |
||||
* An exception that is thrown to indicate that a call to |
||||
* InterruptableJob.interrupt() failed without interrupting the Job. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.InterruptableJob#interrupt() |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class UnableToInterruptJobException extends SchedulerException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>UnableToInterruptJobException</code> with the given message. |
||||
* </p> |
||||
*/ |
||||
public UnableToInterruptJobException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a <code>UnableToInterruptJobException</code> with the given cause. |
||||
* </p> |
||||
*/ |
||||
public UnableToInterruptJobException(Throwable cause) { |
||||
super(cause); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,132 @@
|
||||
package com.fr.third.org.quartz.collections; |
||||
|
||||
|
||||
import java.util.Collection; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Decorates another <code>Collection</code> to provide additional behaviour. |
||||
* <p> |
||||
* Each method call made on this <code>Collection</code> is forwarded to the |
||||
* decorated <code>Collection</code>. This class is used as a framework on which |
||||
* to build to extensions such as synchronized and unmodifiable behaviour. The |
||||
* main advantage of decoration is that one decorator can wrap any implementation |
||||
* of <code>Collection</code>, whereas sub-classing requires a new class to be |
||||
* written for each implementation. |
||||
* <p> |
||||
* This implementation does not perform any special processing with |
||||
* {@link #iterator()}. Instead it simply returns the value from the |
||||
* wrapped collection. This may be undesirable, for example if you are trying |
||||
* to write an unmodifiable implementation it might provide a loophole. |
||||
* |
||||
* @since Commons Collections 3.0 |
||||
* @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ |
||||
* |
||||
* @author Stephen Colebourne |
||||
* @author Paul Jack |
||||
*/ |
||||
public abstract class AbstractCollectionDecorator implements Collection { |
||||
|
||||
/** The collection being decorated */ |
||||
protected Collection collection; |
||||
|
||||
/** |
||||
* Constructor only used in deserialization, do not use otherwise. |
||||
* @since Commons Collections 3.1 |
||||
*/ |
||||
protected AbstractCollectionDecorator() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Constructor that wraps (not copies). |
||||
* |
||||
* @param coll the collection to decorate, must not be null |
||||
* @throws IllegalArgumentException if the collection is null |
||||
*/ |
||||
protected AbstractCollectionDecorator(Collection coll) { |
||||
if (coll == null) { |
||||
throw new IllegalArgumentException("Collection must not be null"); |
||||
} |
||||
this.collection = coll; |
||||
} |
||||
|
||||
/** |
||||
* Gets the collection being decorated. |
||||
* |
||||
* @return the decorated collection |
||||
*/ |
||||
protected Collection getCollection() { |
||||
return collection; |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public boolean add(Object object) { |
||||
return collection.add(object); |
||||
} |
||||
|
||||
public boolean addAll(Collection coll) { |
||||
return collection.addAll(coll); |
||||
} |
||||
|
||||
public void clear() { |
||||
collection.clear(); |
||||
} |
||||
|
||||
public boolean contains(Object object) { |
||||
return collection.contains(object); |
||||
} |
||||
|
||||
public boolean isEmpty() { |
||||
return collection.isEmpty(); |
||||
} |
||||
|
||||
public Iterator iterator() { |
||||
return collection.iterator(); |
||||
} |
||||
|
||||
public boolean remove(Object object) { |
||||
return collection.remove(object); |
||||
} |
||||
|
||||
public int size() { |
||||
return collection.size(); |
||||
} |
||||
|
||||
public Object[] toArray() { |
||||
return collection.toArray(); |
||||
} |
||||
|
||||
public Object[] toArray(Object[] object) { |
||||
return collection.toArray(object); |
||||
} |
||||
|
||||
public boolean containsAll(Collection coll) { |
||||
return collection.containsAll(coll); |
||||
} |
||||
|
||||
public boolean removeAll(Collection coll) { |
||||
return collection.removeAll(coll); |
||||
} |
||||
|
||||
public boolean retainAll(Collection coll) { |
||||
return collection.retainAll(coll); |
||||
} |
||||
|
||||
public boolean equals(Object object) { |
||||
if (object == this) { |
||||
return true; |
||||
} |
||||
return collection.equals(object); |
||||
} |
||||
|
||||
public int hashCode() { |
||||
return collection.hashCode(); |
||||
} |
||||
|
||||
public String toString() { |
||||
return collection.toString(); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,58 @@
|
||||
package com.fr.third.org.quartz.collections; |
||||
|
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Provides basic behaviour for decorating an iterator with extra functionality. |
||||
* <p> |
||||
* All methods are forwarded to the decorated iterator. |
||||
* |
||||
* @since Commons Collections 3.0 |
||||
* @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ |
||||
* |
||||
* @author James Strachan |
||||
* @author Stephen Colebourne |
||||
*/ |
||||
public class AbstractIteratorDecorator implements Iterator { |
||||
|
||||
/** The iterator being decorated */ |
||||
protected final Iterator iterator; |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/** |
||||
* Constructor that decorates the specified iterator. |
||||
* |
||||
* @param iterator the iterator to decorate, must not be null |
||||
* @throws IllegalArgumentException if the collection is null |
||||
*/ |
||||
public AbstractIteratorDecorator(Iterator iterator) { |
||||
super(); |
||||
if (iterator == null) { |
||||
throw new IllegalArgumentException("Iterator must not be null"); |
||||
} |
||||
this.iterator = iterator; |
||||
} |
||||
|
||||
/** |
||||
* Gets the iterator being decorated. |
||||
* |
||||
* @return the decorated iterator |
||||
*/ |
||||
protected Iterator getIterator() { |
||||
return iterator; |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public boolean hasNext() { |
||||
return iterator.hasNext(); |
||||
} |
||||
|
||||
public Object next() { |
||||
return iterator.next(); |
||||
} |
||||
|
||||
public void remove() { |
||||
iterator.remove(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,55 @@
|
||||
package com.fr.third.org.quartz.collections; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.io.ObjectInputStream; |
||||
import java.io.ObjectOutputStream; |
||||
import java.io.Serializable; |
||||
import java.util.Collection; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Serializable subclass of AbstractSetDecorator. |
||||
* |
||||
* @author Stephen Colebourne |
||||
* @since Commons Collections 3.1 |
||||
*/ |
||||
public abstract class AbstractSerializableSetDecorator |
||||
extends AbstractSetDecorator |
||||
implements Serializable { |
||||
|
||||
/** Serialization version */ |
||||
private static final long serialVersionUID = 1229469966212206107L; |
||||
|
||||
/** |
||||
* Constructor. |
||||
*/ |
||||
protected AbstractSerializableSetDecorator(Set set) { |
||||
super(set); |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/** |
||||
* Write the set out using a custom routine. |
||||
* |
||||
* @param out the output stream |
||||
* @throws IOException |
||||
*/ |
||||
private void writeObject(ObjectOutputStream out) throws IOException { |
||||
out.defaultWriteObject(); |
||||
out.writeObject(collection); |
||||
} |
||||
|
||||
/** |
||||
* Read the set in using a custom routine. |
||||
* |
||||
* @param in the input stream |
||||
* @throws IOException |
||||
* @throws ClassNotFoundException |
||||
*/ |
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
||||
in.defaultReadObject(); |
||||
collection = (Collection) in.readObject(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,44 @@
|
||||
package com.fr.third.org.quartz.collections; |
||||
|
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Decorates another <code>Set</code> to provide additional behaviour. |
||||
* <p> |
||||
* Methods are forwarded directly to the decorated set. |
||||
* |
||||
* @since Commons Collections 3.0 |
||||
* @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ |
||||
* |
||||
* @author Stephen Colebourne |
||||
*/ |
||||
public abstract class AbstractSetDecorator extends AbstractCollectionDecorator implements Set { |
||||
|
||||
/** |
||||
* Constructor only used in deserialization, do not use otherwise. |
||||
* @since Commons Collections 3.1 |
||||
*/ |
||||
protected AbstractSetDecorator() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Constructor that wraps (not copies). |
||||
* |
||||
* @param set the set to decorate, must not be null |
||||
* @throws IllegalArgumentException if set is null |
||||
*/ |
||||
protected AbstractSetDecorator(Set set) { |
||||
super(set); |
||||
} |
||||
|
||||
/** |
||||
* Gets the set being decorated. |
||||
* |
||||
* @return the decorated set |
||||
*/ |
||||
protected Set getSet() { |
||||
return (Set) getCollection(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,296 @@
|
||||
package com.fr.third.org.quartz.collections; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.HashSet; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.quartz.collections.AbstractIteratorDecorator; |
||||
|
||||
/** |
||||
* Decorates another <code>Set</code> to ensure that the order of addition |
||||
* is retained and used by the iterator. |
||||
* <p> |
||||
* If an object is added to the set for a second time, it will remain in the |
||||
* original position in the iteration. |
||||
* The order can be observed from the set via the iterator or toArray methods. |
||||
* <p> |
||||
* The ListOrderedSet also has various useful direct methods. These include many |
||||
* from <code>List</code>, such as <code>get(int)</code>, <code>remove(int)</code> |
||||
* and <code>indexOf(int)</code>. An unmodifiable <code>List</code> view of |
||||
* the set can be obtained via <code>asList()</code>. |
||||
* <p> |
||||
* This class cannot implement the <code>List</code> interface directly as |
||||
* various interface methods (notably equals/hashCode) are incompatable with a set. |
||||
* <p> |
||||
* This class is Serializable from Commons Collections 3.1. |
||||
* |
||||
* @since Commons Collections 3.0 |
||||
* @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ |
||||
* |
||||
* @author Stephen Colebourne |
||||
* @author Henning P. Schmiedehausen |
||||
*/ |
||||
public class ListOrderedSet extends AbstractSerializableSetDecorator implements Set { |
||||
|
||||
/** Serialization version */ |
||||
private static final long serialVersionUID = -228664372470420141L; |
||||
|
||||
/** Internal list to hold the sequence of objects */ |
||||
protected final List setOrder; |
||||
|
||||
/** |
||||
* Factory method to create an ordered set specifying the list and set to use. |
||||
* <p> |
||||
* The list and set must both be empty. |
||||
* |
||||
* @param set the set to decorate, must be empty and not null |
||||
* @param list the list to decorate, must be empty and not null |
||||
* @throws IllegalArgumentException if set or list is null |
||||
* @throws IllegalArgumentException if either the set or list is not empty |
||||
* @since Commons Collections 3.1 |
||||
*/ |
||||
public static ListOrderedSet decorate(Set set, List list) { |
||||
if (set == null) { |
||||
throw new IllegalArgumentException("Set must not be null"); |
||||
} |
||||
if (list == null) { |
||||
throw new IllegalArgumentException("List must not be null"); |
||||
} |
||||
if (set.size() > 0 || list.size() > 0) { |
||||
throw new IllegalArgumentException("Set and List must be empty"); |
||||
} |
||||
return new ListOrderedSet(set, list); |
||||
} |
||||
|
||||
/** |
||||
* Factory method to create an ordered set. |
||||
* <p> |
||||
* An <code>ArrayList</code> is used to retain order. |
||||
* |
||||
* @param set the set to decorate, must not be null |
||||
* @throws IllegalArgumentException if set is null |
||||
*/ |
||||
public static ListOrderedSet decorate(Set set) { |
||||
return new ListOrderedSet(set); |
||||
} |
||||
|
||||
/** |
||||
* Factory method to create an ordered set using the supplied list to retain order. |
||||
* <p> |
||||
* A <code>HashSet</code> is used for the set behaviour. |
||||
* <p> |
||||
* NOTE: If the list contains duplicates, the duplicates are removed, |
||||
* altering the specified list. |
||||
* |
||||
* @param list the list to decorate, must not be null |
||||
* @throws IllegalArgumentException if list is null |
||||
*/ |
||||
public static ListOrderedSet decorate(List list) { |
||||
if (list == null) { |
||||
throw new IllegalArgumentException("List must not be null"); |
||||
} |
||||
Set set = new HashSet(list); |
||||
list.retainAll(set); |
||||
|
||||
return new ListOrderedSet(set, list); |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/** |
||||
* Constructs a new empty <code>ListOrderedSet</code> using |
||||
* a <code>HashSet</code> and an <code>ArrayList</code> internally. |
||||
* |
||||
* @since Commons Collections 3.1 |
||||
*/ |
||||
public ListOrderedSet() { |
||||
super(new HashSet()); |
||||
setOrder = new ArrayList(); |
||||
} |
||||
|
||||
/** |
||||
* Constructor that wraps (not copies). |
||||
* |
||||
* @param set the set to decorate, must not be null |
||||
* @throws IllegalArgumentException if set is null |
||||
*/ |
||||
protected ListOrderedSet(Set set) { |
||||
super(set); |
||||
setOrder = new ArrayList(set); |
||||
} |
||||
|
||||
/** |
||||
* Constructor that wraps (not copies) the Set and specifies the list to use. |
||||
* <p> |
||||
* The set and list must both be correctly initialised to the same elements. |
||||
* |
||||
* @param set the set to decorate, must not be null |
||||
* @param list the list to decorate, must not be null |
||||
* @throws IllegalArgumentException if set or list is null |
||||
*/ |
||||
protected ListOrderedSet(Set set, List list) { |
||||
super(set); |
||||
if (list == null) { |
||||
throw new IllegalArgumentException("List must not be null"); |
||||
} |
||||
setOrder = list; |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/** |
||||
* Gets an unmodifiable view of the order of the Set. |
||||
* |
||||
* @return an unmodifiable list view |
||||
*/ |
||||
//p:ûÓбØҪת³ÉList
|
||||
// public List asList() {
|
||||
// return UnmodifiableList.decorate(setOrder);
|
||||
// }
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public void clear() { |
||||
collection.clear(); |
||||
setOrder.clear(); |
||||
} |
||||
|
||||
public Iterator iterator() { |
||||
return new OrderedSetIterator(setOrder.iterator(), collection); |
||||
} |
||||
|
||||
public boolean add(Object object) { |
||||
if (collection.contains(object)) { |
||||
// re-adding doesn't change order
|
||||
return collection.add(object); |
||||
} else { |
||||
// first add, so add to both set and list
|
||||
boolean result = collection.add(object); |
||||
setOrder.add(object); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
public boolean addAll(Collection coll) { |
||||
boolean result = false; |
||||
for (Iterator it = coll.iterator(); it.hasNext();) { |
||||
Object object = it.next(); |
||||
result = result | add(object); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public boolean remove(Object object) { |
||||
boolean result = collection.remove(object); |
||||
setOrder.remove(object); |
||||
return result; |
||||
} |
||||
|
||||
public boolean removeAll(Collection coll) { |
||||
boolean result = false; |
||||
for (Iterator it = coll.iterator(); it.hasNext();) { |
||||
Object object = it.next(); |
||||
result = result | remove(object); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public boolean retainAll(Collection coll) { |
||||
boolean result = collection.retainAll(coll); |
||||
if (result == false) { |
||||
return false; |
||||
} else if (collection.size() == 0) { |
||||
setOrder.clear(); |
||||
} else { |
||||
for (Iterator it = setOrder.iterator(); it.hasNext();) { |
||||
Object object = it.next(); |
||||
if (collection.contains(object) == false) { |
||||
it.remove(); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public Object[] toArray() { |
||||
return setOrder.toArray(); |
||||
} |
||||
|
||||
public Object[] toArray(Object a[]) { |
||||
return setOrder.toArray(a); |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public Object get(int index) { |
||||
return setOrder.get(index); |
||||
} |
||||
|
||||
public int indexOf(Object object) { |
||||
return setOrder.indexOf(object); |
||||
} |
||||
|
||||
public void add(int index, Object object) { |
||||
if (contains(object) == false) { |
||||
collection.add(object); |
||||
setOrder.add(index, object); |
||||
} |
||||
} |
||||
|
||||
public boolean addAll(int index, Collection coll) { |
||||
boolean changed = false; |
||||
for (Iterator it = coll.iterator(); it.hasNext();) { |
||||
Object object = it.next(); |
||||
if (contains(object) == false) { |
||||
collection.add(object); |
||||
setOrder.add(index, object); |
||||
index++; |
||||
changed = true; |
||||
} |
||||
} |
||||
return changed; |
||||
} |
||||
|
||||
public Object remove(int index) { |
||||
Object obj = setOrder.remove(index); |
||||
remove(obj); |
||||
return obj; |
||||
} |
||||
|
||||
/** |
||||
* Uses the underlying List's toString so that order is achieved. |
||||
* This means that the decorated Set's toString is not used, so |
||||
* any custom toStrings will be ignored. |
||||
*/ |
||||
// Fortunately List.toString and Set.toString look the same
|
||||
public String toString() { |
||||
return setOrder.toString(); |
||||
} |
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/** |
||||
* Internal iterator handle remove. |
||||
*/ |
||||
static class OrderedSetIterator extends AbstractIteratorDecorator { |
||||
|
||||
/** Object we iterate on */ |
||||
protected final Collection set; |
||||
/** Last object retrieved */ |
||||
protected Object last; |
||||
|
||||
private OrderedSetIterator(Iterator iterator, Collection set) { |
||||
super(iterator); |
||||
this.set = set; |
||||
} |
||||
|
||||
public Object next() { |
||||
last = iterator.next(); |
||||
return last; |
||||
} |
||||
|
||||
public void remove() { |
||||
set.remove(last); |
||||
iterator.remove(); |
||||
last = null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,431 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.Job; |
||||
import com.fr.third.org.quartz.JobDetail; |
||||
import com.fr.third.org.quartz.JobExecutionContext; |
||||
import com.fr.third.org.quartz.JobExecutionException; |
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
import com.fr.third.org.quartz.spi.TriggerFiredBundle; |
||||
|
||||
/** |
||||
* <p> |
||||
* JobRunShell instances are responsible for providing the 'safe' environment |
||||
* for <code>Job</code> s to run in, and for performing all of the work of |
||||
* executing the <code>Job</code>, catching ANY thrown exceptions, updating |
||||
* the <code>Trigger</code> with the <code>Job</code>'s completion code, |
||||
* etc. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* A <code>JobRunShell</code> instance is created by a <code>JobRunShellFactory</code> |
||||
* on behalf of the <code>QuartzSchedulerThread</code> which then runs the |
||||
* shell in a thread from the configured <code>ThreadPool</code> when the |
||||
* scheduler determines that a <code>Job</code> has been triggered. |
||||
* </p> |
||||
* |
||||
* @see JobRunShellFactory |
||||
* @see com.fr.third.org.quartz.core.QuartzSchedulerThread |
||||
* @see com.fr.third.org.quartz.Job |
||||
* @see com.fr.third.org.quartz.Trigger |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JobRunShell implements Runnable { |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected JobExecutionContext jec = null; |
||||
|
||||
protected QuartzScheduler qs = null; |
||||
|
||||
protected Scheduler scheduler = null; |
||||
|
||||
protected SchedulingContext schdCtxt = null; |
||||
|
||||
protected JobRunShellFactory jobRunShellFactory = null; |
||||
|
||||
protected boolean shutdownRequested = false; |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JobRunShell instance with the given settings. |
||||
* </p> |
||||
* |
||||
* @param jobRunShellFactory |
||||
* A handle to the <code>JobRunShellFactory</code> that produced |
||||
* this <code>JobRunShell</code>. |
||||
* @param scheduler |
||||
* The <code>Scheduler</code> instance that should be made |
||||
* available within the <code>JobExecutionContext</code>. |
||||
* @param schdCtxt |
||||
* the <code>SchedulingContext</code> that should be used by the |
||||
* <code>JobRunShell</code> when making updates to the <code>JobStore</code>. |
||||
*/ |
||||
public JobRunShell(JobRunShellFactory jobRunShellFactory, |
||||
Scheduler scheduler, SchedulingContext schdCtxt) { |
||||
this.jobRunShellFactory = jobRunShellFactory; |
||||
this.scheduler = scheduler; |
||||
this.schdCtxt = schdCtxt; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
public void initialize(QuartzScheduler qs, TriggerFiredBundle firedBundle) |
||||
throws SchedulerException { |
||||
this.qs = qs; |
||||
|
||||
Job job = null; |
||||
JobDetail jobDetail = firedBundle.getJobDetail(); |
||||
|
||||
try { |
||||
job = qs.getJobFactory().newJob(firedBundle); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured instantiating job to be executed. job= '" |
||||
+ jobDetail.getFullName() + "'", se); |
||||
throw se; |
||||
} catch (Throwable ncdfe) { // such as NoClassDefFoundError
|
||||
SchedulerException se = new SchedulerException( |
||||
"Problem instantiating class '" |
||||
+ jobDetail.getJobClass().getName() + "' - ", ncdfe); |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured instantiating job to be executed. job= '" |
||||
+ jobDetail.getFullName() + "'", se); |
||||
throw se; |
||||
} |
||||
|
||||
this.jec = new JobExecutionContext(scheduler, firedBundle, job); |
||||
} |
||||
|
||||
public void requestShutdown() { |
||||
shutdownRequested = true; |
||||
} |
||||
|
||||
public void run() { |
||||
try { |
||||
Trigger trigger = jec.getTrigger(); |
||||
JobDetail jobDetail = jec.getJobDetail(); |
||||
|
||||
do { |
||||
|
||||
JobExecutionException jobExEx = null; |
||||
Job job = jec.getJobInstance(); |
||||
|
||||
try { |
||||
begin(); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError("Error executing Job (" |
||||
+ jec.getJobDetail().getFullName() |
||||
+ ": couldn't begin execution.", se); |
||||
break; |
||||
} |
||||
|
||||
// notify job & trigger listeners...
|
||||
try { |
||||
if (!notifyListenersBeginning(jec)) { |
||||
break; |
||||
} |
||||
} catch(VetoedException ve) { |
||||
try { |
||||
int instCode = trigger.executionComplete(jec, null); |
||||
try { |
||||
qs.notifyJobStoreJobVetoed(schdCtxt, trigger, jobDetail, instCode); |
||||
} catch(JobPersistenceException jpe) { |
||||
vetoedJobRetryLoop(trigger, jobDetail, instCode); |
||||
} |
||||
complete(true); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError("Error during veto of Job (" |
||||
+ jec.getJobDetail().getFullName() |
||||
+ ": couldn't finalize execution.", se); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
long startTime = System.currentTimeMillis(); |
||||
long endTime = startTime; |
||||
|
||||
// execute the job
|
||||
try { |
||||
log.debug("Calling execute on job " + jobDetail.getFullName()); |
||||
job.execute(jec); |
||||
endTime = System.currentTimeMillis(); |
||||
} catch (JobExecutionException jee) { |
||||
endTime = System.currentTimeMillis(); |
||||
jobExEx = jee; |
||||
getLog().info("Job " + jobDetail.getFullName() + |
||||
" threw a JobExecutionException: ", jobExEx); |
||||
} catch (Throwable e) { |
||||
endTime = System.currentTimeMillis(); |
||||
getLog().error("Job " + jobDetail.getFullName() + |
||||
" threw an unhandled Exception: ", e); |
||||
SchedulerException se = new SchedulerException( |
||||
"Job threw an unhandled exception.", e); |
||||
se.setErrorCode(SchedulerException.ERR_JOB_EXECUTION_THREW_EXCEPTION); |
||||
qs.notifySchedulerListenersError("Job (" |
||||
+ jec.getJobDetail().getFullName() |
||||
+ " threw an exception.", se); |
||||
jobExEx = new JobExecutionException(se, false); |
||||
jobExEx.setErrorCode(JobExecutionException.ERR_JOB_EXECUTION_THREW_EXCEPTION); |
||||
} |
||||
|
||||
jec.setJobRunTime(endTime - startTime); |
||||
|
||||
// notify all job listeners
|
||||
if (!notifyJobListenersComplete(jec, jobExEx)) { |
||||
break; |
||||
} |
||||
|
||||
int instCode = Trigger.INSTRUCTION_NOOP; |
||||
|
||||
// update the trigger
|
||||
try { |
||||
instCode = trigger.executionComplete(jec, jobExEx); |
||||
} catch (Exception e) { |
||||
// If this happens, there's a bug in the trigger...
|
||||
SchedulerException se = new SchedulerException( |
||||
"Trigger threw an unhandled exception.", e); |
||||
se.setErrorCode(SchedulerException.ERR_TRIGGER_THREW_EXCEPTION); |
||||
qs.notifySchedulerListenersError( |
||||
"Please report this error to the Quartz developers.", |
||||
se); |
||||
} |
||||
|
||||
// notify all trigger listeners
|
||||
if (!notifyTriggerListenersComplete(jec, instCode)) { |
||||
break; |
||||
} |
||||
|
||||
// update job/trigger or re-execute job
|
||||
if (instCode == Trigger.INSTRUCTION_RE_EXECUTE_JOB) { |
||||
jec.incrementRefireCount(); |
||||
try { |
||||
complete(false); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError("Error executing Job (" |
||||
+ jec.getJobDetail().getFullName() |
||||
+ ": couldn't finalize execution.", se); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
complete(true); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError("Error executing Job (" |
||||
+ jec.getJobDetail().getFullName() |
||||
+ ": couldn't finalize execution.", se); |
||||
continue; |
||||
} |
||||
|
||||
try { |
||||
qs.notifyJobStoreJobComplete(schdCtxt, trigger, jobDetail, |
||||
instCode); |
||||
} catch (JobPersistenceException jpe) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while marking executed job complete. job= '" |
||||
+ jobDetail.getFullName() + "'", jpe); |
||||
if (!completeTriggerRetryLoop(trigger, jobDetail, instCode)) { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
break; |
||||
} while (true); |
||||
|
||||
} finally { |
||||
jobRunShellFactory.returnJobRunShell(this); |
||||
} |
||||
} |
||||
|
||||
protected void begin() throws SchedulerException { |
||||
} |
||||
|
||||
protected void complete(boolean successfulExecution) |
||||
throws SchedulerException { |
||||
} |
||||
|
||||
public void passivate() { |
||||
jec = null; |
||||
qs = null; |
||||
} |
||||
|
||||
private boolean notifyListenersBeginning(JobExecutionContext jec) throws VetoedException { |
||||
|
||||
boolean vetoed = false; |
||||
|
||||
// notify all trigger listeners
|
||||
try { |
||||
vetoed = qs.notifyTriggerListenersFired(jec); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"Unable to notify TriggerListener(s) while firing trigger " |
||||
+ "(Trigger and Job will NOT be fired!). trigger= " |
||||
+ jec.getTrigger().getFullName() + " job= " |
||||
+ jec.getJobDetail().getFullName(), se); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
if(vetoed) { |
||||
try { |
||||
qs.notifyJobListenersWasVetoed(jec); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"Unable to notify JobListener(s) of vetoed execution " + |
||||
"while firing trigger (Trigger and Job will NOT be " + |
||||
"fired!). trigger= " |
||||
+ jec.getTrigger().getFullName() + " job= " |
||||
+ jec.getJobDetail().getFullName(), se); |
||||
|
||||
} |
||||
throw new VetoedException(); |
||||
} |
||||
|
||||
// notify all job listeners
|
||||
try { |
||||
qs.notifyJobListenersToBeExecuted(jec); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"Unable to notify JobListener(s) of Job to be executed: " |
||||
+ "(Job will NOT be executed!). trigger= " |
||||
+ jec.getTrigger().getFullName() + " job= " |
||||
+ jec.getJobDetail().getFullName(), se); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private boolean notifyJobListenersComplete(JobExecutionContext jec, |
||||
JobExecutionException jobExEx) { |
||||
try { |
||||
qs.notifyJobListenersWasExecuted(jec, jobExEx); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"Unable to notify JobListener(s) of Job that was executed: " |
||||
+ "(error will be ignored). trigger= " |
||||
+ jec.getTrigger().getFullName() + " job= " |
||||
+ jec.getJobDetail().getFullName(), se); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private boolean notifyTriggerListenersComplete(JobExecutionContext jec, |
||||
int instCode) { |
||||
try { |
||||
qs.notifyTriggerListenersComplete(jec, instCode); |
||||
|
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"Unable to notify TriggerListener(s) of Job that was executed: " |
||||
+ "(error will be ignored). trigger= " |
||||
+ jec.getTrigger().getFullName() + " job= " |
||||
+ jec.getJobDetail().getFullName(), se); |
||||
|
||||
return false; |
||||
} |
||||
if (jec.getTrigger().getNextFireTime() == null) { |
||||
qs.notifySchedulerListenersFinalized(jec.getTrigger()); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public boolean completeTriggerRetryLoop(Trigger trigger, |
||||
JobDetail jobDetail, int instCode) { |
||||
while (!shutdownRequested) { |
||||
try { |
||||
Thread.sleep(5 * 1000L); // retry every 5 seconds (the db
|
||||
// connection must be failed)
|
||||
qs.notifyJobStoreJobComplete(schdCtxt, trigger, jobDetail, |
||||
instCode); |
||||
return true; |
||||
} catch (JobPersistenceException jpe) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while marking executed job complete. job= '" |
||||
+ jobDetail.getFullName() + "'", jpe); |
||||
} catch (InterruptedException ignore) { |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public boolean vetoedJobRetryLoop(Trigger trigger, JobDetail jobDetail, int instCode) { |
||||
while (!shutdownRequested) { |
||||
try { |
||||
Thread.sleep(5 * 1000L); // retry every 5 seconds (the db
|
||||
// connection must be failed)
|
||||
qs.notifyJobStoreJobVetoed(schdCtxt, trigger, jobDetail, instCode); |
||||
return true; |
||||
} catch (JobPersistenceException jpe) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while marking executed job vetoed. job= '" |
||||
+ jobDetail.getFullName() + "'", jpe); |
||||
} catch (InterruptedException ignore) { |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
class VetoedException extends Exception { |
||||
public VetoedException() { |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,82 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerConfigException; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Responsible for creating the instances of <code>{@link JobRunShell}</code> |
||||
* to be used within the <class>{@link QuartzScheduler}</code> instance. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Although this interface looks a lot like an 'object pool', implementations |
||||
* do not have to support the re-use of instances. If an implementation does |
||||
* not wish to pool instances, then the <code>borrowJobRunShell()</code> |
||||
* method would simply create a new instance, and the <code>returnJobRunShell |
||||
* </code> method would do nothing. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public interface JobRunShellFactory { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Initialize the factory, providing a handle to the <code>Scheduler</code> |
||||
* that should be made available within the <code>JobRunShell</code> and |
||||
* the <code>JobExecutionCOntext</code> s within it, and a handle to the |
||||
* <code>SchedulingContext</code> that the shell will use in its own |
||||
* operations with the <code>JobStore</code>. |
||||
* </p> |
||||
*/ |
||||
void initialize(Scheduler scheduler, SchedulingContext schedCtxt) |
||||
throws SchedulerConfigException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread}</code> |
||||
* to obtain instances of <code>{@link JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
JobRunShell borrowJobRunShell() throws SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread}</code> |
||||
* to return instances of <code>{@link JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
void returnJobRunShell(JobRunShell jobRunShell); |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,519 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import com.fr.third.org.quartz.spi.JobStore; |
||||
import com.fr.third.org.quartz.spi.SchedulerPlugin; |
||||
import com.fr.third.org.quartz.spi.ThreadPool; |
||||
|
||||
/** |
||||
* <p> |
||||
* Contains all of the resources (<code>JobStore</code>,<code>ThreadPool</code>, |
||||
* etc.) necessary to create a <code>{@link QuartzScheduler}</code> instance. |
||||
* </p> |
||||
* |
||||
* @see QuartzScheduler |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class QuartzSchedulerResources { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final String CREATE_REGISTRY_NEVER = "never"; |
||||
|
||||
public static final String CREATE_REGISTRY_ALWAYS = "always"; |
||||
|
||||
public static final String CREATE_REGISTRY_AS_NEEDED = "as_needed"; |
||||
|
||||
private String name; |
||||
|
||||
private String instanceId; |
||||
|
||||
private String threadName; |
||||
|
||||
private String rmiRegistryHost = null; |
||||
|
||||
private int rmiRegistryPort = 1099; |
||||
|
||||
private int rmiServerPort = -1; |
||||
|
||||
private String rmiCreateRegistryStrategy = CREATE_REGISTRY_NEVER; |
||||
|
||||
private ThreadPool threadPool; |
||||
|
||||
private JobStore jobStore; |
||||
|
||||
private JobRunShellFactory jobRunShellFactory; |
||||
|
||||
private ArrayList schedulerPlugins = new ArrayList(10); |
||||
|
||||
private boolean makeSchedulerThreadDaemon = false; |
||||
|
||||
private boolean threadsInheritInitializersClassLoadContext = false; |
||||
|
||||
private String rmiBindName; |
||||
|
||||
private boolean jmxExport; |
||||
|
||||
private String jmxObjectName; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create an instance with no properties initialized. |
||||
* </p> |
||||
*/ |
||||
public QuartzSchedulerResources() { |
||||
// do nothing...
|
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name for the <code>{@link QuartzScheduler}</code>. |
||||
* </p> |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the name for the <code>{@link QuartzScheduler}</code>. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if name is null or empty. |
||||
*/ |
||||
public void setName(String name) { |
||||
if (name == null || name.trim().length() == 0) { |
||||
throw new IllegalArgumentException( |
||||
"Scheduler name cannot be empty."); |
||||
} |
||||
|
||||
this.name = name; |
||||
|
||||
if (threadName == null) { |
||||
// thread name not already set, use default thread name
|
||||
setThreadName(name + "_QuartzSchedulerThread"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the instance Id for the <code>{@link QuartzScheduler}</code>. |
||||
* </p> |
||||
*/ |
||||
public String getInstanceId() { |
||||
return instanceId; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the name for the <code>{@link QuartzScheduler}</code>. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if name is null or empty. |
||||
*/ |
||||
public void setInstanceId(String instanceId) { |
||||
if (instanceId == null || instanceId.trim().length() == 0) { |
||||
throw new IllegalArgumentException( |
||||
"Scheduler instanceId cannot be empty."); |
||||
} |
||||
|
||||
this.instanceId = instanceId; |
||||
} |
||||
|
||||
public static String getUniqueIdentifier(String schedName, |
||||
String schedInstId) { |
||||
return schedName + "_$_" + schedInstId; |
||||
} |
||||
|
||||
public String getUniqueIdentifier() { |
||||
return getUniqueIdentifier(name, instanceId); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the host name of the RMI Registry that the scheduler should export |
||||
* itself to. |
||||
* </p> |
||||
*/ |
||||
public String getRMIRegistryHost() { |
||||
return rmiRegistryHost; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the host name of the RMI Registry that the scheduler should export |
||||
* itself to. |
||||
* </p> |
||||
*/ |
||||
public void setRMIRegistryHost(String hostName) { |
||||
this.rmiRegistryHost = hostName; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the port number of the RMI Registry that the scheduler should export |
||||
* itself to. |
||||
* </p> |
||||
*/ |
||||
public int getRMIRegistryPort() { |
||||
return rmiRegistryPort; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the port number of the RMI Registry that the scheduler should export |
||||
* itself to. |
||||
* </p> |
||||
*/ |
||||
public void setRMIRegistryPort(int port) { |
||||
this.rmiRegistryPort = port; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* Get the port number the scheduler server will be bound to. |
||||
* </p> |
||||
*/ |
||||
public int getRMIServerPort() { |
||||
return rmiServerPort; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the port number the scheduler server will be bound to. |
||||
* </p> |
||||
*/ |
||||
public void setRMIServerPort(int port) { |
||||
this.rmiServerPort = port; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the setting of whether or not Quartz should create an RMI Registry, |
||||
* and if so, how. |
||||
* </p> |
||||
*/ |
||||
public String getRMICreateRegistryStrategy() { |
||||
return rmiCreateRegistryStrategy; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name for the <code>{@link QuartzSchedulerThread}</code>. |
||||
* </p> |
||||
*/ |
||||
public String getThreadName() { |
||||
return threadName; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the name for the <code>{@link QuartzSchedulerThread}</code>. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if name is null or empty. |
||||
*/ |
||||
public void setThreadName(String threadName) { |
||||
if (threadName == null || threadName.trim().length() == 0) { |
||||
throw new IllegalArgumentException( |
||||
"Scheduler thread name cannot be empty."); |
||||
} |
||||
|
||||
this.threadName = threadName; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set whether or not Quartz should create an RMI Registry, and if so, how. |
||||
* </p> |
||||
* |
||||
* @see #CREATE_REGISTRY_ALWAYS |
||||
* @see #CREATE_REGISTRY_AS_NEEDED |
||||
* @see #CREATE_REGISTRY_NEVER |
||||
*/ |
||||
public void setRMICreateRegistryStrategy(String rmiCreateRegistryStrategy) { |
||||
if (rmiCreateRegistryStrategy == null |
||||
|| rmiCreateRegistryStrategy.trim().length() == 0) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_NEVER; |
||||
} else if (rmiCreateRegistryStrategy.equalsIgnoreCase("true")) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_AS_NEEDED; |
||||
} else if (rmiCreateRegistryStrategy.equalsIgnoreCase("false")) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_NEVER; |
||||
} else if (rmiCreateRegistryStrategy.equalsIgnoreCase(CREATE_REGISTRY_ALWAYS)) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_ALWAYS; |
||||
} else if (rmiCreateRegistryStrategy.equalsIgnoreCase(CREATE_REGISTRY_AS_NEEDED)) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_AS_NEEDED; |
||||
} else if (rmiCreateRegistryStrategy.equalsIgnoreCase(CREATE_REGISTRY_NEVER)) { |
||||
rmiCreateRegistryStrategy = CREATE_REGISTRY_NEVER; |
||||
} else { |
||||
throw new IllegalArgumentException( |
||||
"Faild to set RMICreateRegistryStrategy - strategy unknown: '" |
||||
+ rmiCreateRegistryStrategy + "'"); |
||||
} |
||||
|
||||
this.rmiCreateRegistryStrategy = rmiCreateRegistryStrategy; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>{@link ThreadPool}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
*/ |
||||
public ThreadPool getThreadPool() { |
||||
return threadPool; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the <code>{@link ThreadPool}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if threadPool is null. |
||||
*/ |
||||
public void setThreadPool(ThreadPool threadPool) { |
||||
if (threadPool == null) { |
||||
throw new IllegalArgumentException("ThreadPool cannot be null."); |
||||
} |
||||
|
||||
this.threadPool = threadPool; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>{@link JobStore}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
*/ |
||||
public JobStore getJobStore() { |
||||
return jobStore; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the <code>{@link JobStore}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if jobStore is null. |
||||
*/ |
||||
public void setJobStore(JobStore jobStore) { |
||||
if (jobStore == null) { |
||||
throw new IllegalArgumentException("JobStore cannot be null."); |
||||
} |
||||
|
||||
this.jobStore = jobStore; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>{@link JobRunShellFactory}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
*/ |
||||
public JobRunShellFactory getJobRunShellFactory() { |
||||
return jobRunShellFactory; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the <code>{@link JobRunShellFactory}</code> for the <code>{@link QuartzScheduler}</code> |
||||
* to use. |
||||
* </p> |
||||
* |
||||
* @exception IllegalArgumentException |
||||
* if jobRunShellFactory is null. |
||||
*/ |
||||
public void setJobRunShellFactory(JobRunShellFactory jobRunShellFactory) { |
||||
if (jobRunShellFactory == null) { |
||||
throw new IllegalArgumentException( |
||||
"JobRunShellFactory cannot be null."); |
||||
} |
||||
|
||||
this.jobRunShellFactory = jobRunShellFactory; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Add the given <code>{@link com.fr.third.org.quartz.spi.SchedulerPlugin}</code> for the |
||||
* <code>{@link QuartzScheduler}</code> to use. This method expects the plugin's |
||||
* "initialize" method to be invoked externally (either before or after |
||||
* this method is called). |
||||
* </p> |
||||
*/ |
||||
public void addSchedulerPlugin(SchedulerPlugin plugin) { |
||||
schedulerPlugins.add(plugin); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the <code>List</code> of all |
||||
* <code>{@link com.fr.third.org.quartz.spi.SchedulerPlugin}</code>s for the |
||||
* <code>{@link QuartzScheduler}</code> to use. |
||||
* </p> |
||||
*/ |
||||
public List getSchedulerPlugins() { |
||||
return schedulerPlugins; |
||||
} |
||||
|
||||
/** |
||||
* Get whether to mark the Quartz scheduling thread as daemon. |
||||
* |
||||
* @see Thread#setDaemon(boolean) |
||||
*/ |
||||
public boolean getMakeSchedulerThreadDaemon() { |
||||
return makeSchedulerThreadDaemon; |
||||
} |
||||
|
||||
/** |
||||
* Set whether to mark the Quartz scheduling thread as daemon. |
||||
* |
||||
* @see Thread#setDaemon(boolean) |
||||
*/ |
||||
public void setMakeSchedulerThreadDaemon(boolean makeSchedulerThreadDaemon) { |
||||
this.makeSchedulerThreadDaemon = makeSchedulerThreadDaemon; |
||||
} |
||||
|
||||
/** |
||||
* Get whether to set the class load context of spawned threads to that |
||||
* of the initializing thread. |
||||
*/ |
||||
public boolean isThreadsInheritInitializersClassLoadContext() { |
||||
return threadsInheritInitializersClassLoadContext; |
||||
} |
||||
|
||||
/** |
||||
* Set whether to set the class load context of spawned threads to that |
||||
* of the initializing thread. |
||||
*/ |
||||
public void setThreadsInheritInitializersClassLoadContext( |
||||
boolean threadsInheritInitializersClassLoadContext) { |
||||
this.threadsInheritInitializersClassLoadContext = threadsInheritInitializersClassLoadContext; |
||||
} |
||||
|
||||
/** |
||||
* Get the name under which to bind the QuartzScheduler in RMI. Will |
||||
* return the value of the uniqueIdentifier property if explict RMI bind |
||||
* name was never set. |
||||
* |
||||
* @see #getUniqueIdentifier() |
||||
*/ |
||||
public String getRMIBindName() { |
||||
return (rmiBindName == null) ? getUniqueIdentifier() : rmiBindName; |
||||
} |
||||
|
||||
/** |
||||
* Set the name under which to bind the QuartzScheduler in RMI. If unset, |
||||
* defaults to the value of the uniqueIdentifier property. |
||||
* |
||||
* @see #getUniqueIdentifier() |
||||
*/ |
||||
public void setRMIBindName(String rmiBindName) { |
||||
this.rmiBindName = rmiBindName; |
||||
} |
||||
|
||||
/** |
||||
* Get whether the QuartzScheduler should be registered with the local |
||||
* MBeanServer. |
||||
*/ |
||||
public boolean getJMXExport() { |
||||
return jmxExport; |
||||
} |
||||
|
||||
/** |
||||
* Set whether the QuartzScheduler should be registered with the local |
||||
* MBeanServer. |
||||
*/ |
||||
public void setJMXExport(boolean jmxExport) { |
||||
this.jmxExport = jmxExport; |
||||
} |
||||
|
||||
/** |
||||
* Get the name under which the QuartzScheduler should be registered with |
||||
* the local MBeanServer. If unset, defaults to the value calculated by |
||||
* <code>generateJMXObjectName<code>. |
||||
* |
||||
* @see #generateJMXObjectName(String, String) |
||||
*/ |
||||
public String getJMXObjectName() { |
||||
return (jmxObjectName == null) ? generateJMXObjectName(name, instanceId) : jmxObjectName; |
||||
} |
||||
|
||||
/** |
||||
* Set the name under which the QuartzScheduler should be registered with |
||||
* the local MBeanServer. If unset, defaults to the value calculated by |
||||
* <code>generateJMXObjectName<code>. |
||||
* |
||||
* @see #generateJMXObjectName(String, String) |
||||
*/ |
||||
public void setJMXObjectName(String jmxObjectName) { |
||||
this.jmxObjectName = jmxObjectName; |
||||
} |
||||
|
||||
/** |
||||
* Create the name under which this scheduler should be registered in JMX. |
||||
* <p> |
||||
* The name is composed as: |
||||
* quartz:type=QuartzScheduler,name=<i>[schedName]</i>,instance=<i>[schedInstId]</i> |
||||
* </p> |
||||
*/ |
||||
public static String generateJMXObjectName(String schedName, String schedInstId) { |
||||
return "quartz:type=QuartzScheduler" + |
||||
",name=" + schedName + |
||||
",instance=" + schedInstId; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,560 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
import com.fr.third.org.quartz.spi.TriggerFiredBundle; |
||||
|
||||
import java.util.Random; |
||||
|
||||
/** |
||||
* <p> |
||||
* The thread responsible for performing the work of firing <code>{@link Trigger}</code> |
||||
* s that are registered with the <code>{@link QuartzScheduler}</code>. |
||||
* </p> |
||||
* |
||||
* @see QuartzScheduler |
||||
* @see com.fr.third.org.quartz.Job |
||||
* @see Trigger |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class QuartzSchedulerThread extends Thread { |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
private QuartzScheduler qs; |
||||
|
||||
private QuartzSchedulerResources qsRsrcs; |
||||
|
||||
private Object sigLock = new Object(); |
||||
|
||||
private boolean signaled; |
||||
private long signaledNextFireTime; |
||||
|
||||
private boolean paused; |
||||
|
||||
private boolean halted; |
||||
|
||||
private SchedulingContext ctxt = null; |
||||
|
||||
private Random random = new Random(System.currentTimeMillis()); |
||||
|
||||
// When the scheduler finds there is no current trigger to fire, how long
|
||||
// it should wait until checking again...
|
||||
private static long DEFAULT_IDLE_WAIT_TIME = 30L * 1000L; |
||||
|
||||
private long idleWaitTime = DEFAULT_IDLE_WAIT_TIME; |
||||
|
||||
private int idleWaitVariablness = 7 * 1000; |
||||
|
||||
private long dbFailureRetryInterval = 15L * 1000L; |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Construct a new <code>QuartzSchedulerThread</code> for the given |
||||
* <code>QuartzScheduler</code> as a non-daemon <code>Thread</code> |
||||
* with normal priority. |
||||
* </p> |
||||
*/ |
||||
QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs, |
||||
SchedulingContext ctxt) { |
||||
this(qs, qsRsrcs, ctxt, qsRsrcs.getMakeSchedulerThreadDaemon(), Thread.NORM_PRIORITY); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Construct a new <code>QuartzSchedulerThread</code> for the given |
||||
* <code>QuartzScheduler</code> as a <code>Thread</code> with the given |
||||
* attributes. |
||||
* </p> |
||||
*/ |
||||
QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs, |
||||
SchedulingContext ctxt, boolean setDaemon, int threadPrio) { |
||||
super(qs.getSchedulerThreadGroup(), qsRsrcs.getThreadName()); |
||||
this.qs = qs; |
||||
this.qsRsrcs = qsRsrcs; |
||||
this.ctxt = ctxt; |
||||
this.setDaemon(setDaemon); |
||||
if(qsRsrcs.isThreadsInheritInitializersClassLoadContext()) { |
||||
log.info("QuartzSchedulerThread Inheriting ContextClassLoader of thread: " + Thread.currentThread().getName()); |
||||
this.setContextClassLoader(Thread.currentThread().getContextClassLoader()); |
||||
} |
||||
|
||||
this.setPriority(threadPrio); |
||||
|
||||
// start the underlying thread, but put this object into the 'paused'
|
||||
// state
|
||||
// so processing doesn't start yet...
|
||||
paused = true; |
||||
halted = false; |
||||
this.start(); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
void setIdleWaitTime(long waitTime) { |
||||
idleWaitTime = waitTime; |
||||
idleWaitVariablness = (int) (waitTime * 0.2); |
||||
} |
||||
|
||||
private long getDbFailureRetryInterval() { |
||||
return dbFailureRetryInterval; |
||||
} |
||||
|
||||
public void setDbFailureRetryInterval(long dbFailureRetryInterval) { |
||||
this.dbFailureRetryInterval = dbFailureRetryInterval; |
||||
} |
||||
|
||||
private long getRandomizedIdleWaitTime() { |
||||
return idleWaitTime - random.nextInt(idleWaitVariablness); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Signals the main processing loop to pause at the next possible point. |
||||
* </p> |
||||
*/ |
||||
void togglePause(boolean pause) { |
||||
synchronized (sigLock) { |
||||
paused = pause; |
||||
|
||||
if (paused) { |
||||
signalSchedulingChange(0); |
||||
} else { |
||||
sigLock.notifyAll(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Signals the main processing loop to pause at the next possible point. |
||||
* </p> |
||||
*/ |
||||
void halt() { |
||||
synchronized (sigLock) { |
||||
halted = true; |
||||
|
||||
if (paused) { |
||||
sigLock.notifyAll(); |
||||
} else { |
||||
signalSchedulingChange(0); |
||||
} |
||||
} |
||||
} |
||||
|
||||
boolean isPaused() { |
||||
return paused; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Signals the main processing loop that a change in scheduling has been |
||||
* made - in order to interrupt any sleeping that may be occuring while |
||||
* waiting for the fire time to arrive. |
||||
* </p> |
||||
* |
||||
* @param newNextTime the time (in millis) when the newly scheduled trigger |
||||
* will fire. If this method is being called do to some other even (rather |
||||
* than scheduling a trigger), the caller should pass zero (0). |
||||
*/ |
||||
public void signalSchedulingChange(long candidateNewNextFireTime) { |
||||
synchronized(sigLock) { |
||||
signaled = true; |
||||
signaledNextFireTime = candidateNewNextFireTime; |
||||
sigLock.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
public void clearSignaledSchedulingChange() { |
||||
synchronized(sigLock) { |
||||
signaled = false; |
||||
signaledNextFireTime = 0; |
||||
} |
||||
} |
||||
|
||||
public boolean isScheduleChanged() { |
||||
synchronized(sigLock) { |
||||
return signaled; |
||||
} |
||||
} |
||||
|
||||
public long getSignaledNextFireTime() { |
||||
synchronized(sigLock) { |
||||
return signaledNextFireTime; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* The main processing loop of the <code>QuartzSchedulerThread</code>. |
||||
* </p> |
||||
*/ |
||||
public void run() { |
||||
boolean lastAcquireFailed = false; |
||||
|
||||
while (!halted) { |
||||
try { |
||||
// check if we're supposed to pause...
|
||||
synchronized (sigLock) { |
||||
while (paused && !halted) { |
||||
try { |
||||
// wait until togglePause(false) is called...
|
||||
sigLock.wait(1000L); |
||||
} catch (InterruptedException ignore) { |
||||
} |
||||
} |
||||
|
||||
if (halted) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
int availTreadCount = qsRsrcs.getThreadPool().blockForAvailableThreads(); |
||||
if(availTreadCount > 0) { // will always be true, due to semantics of blockForAvailableThreads...
|
||||
|
||||
Trigger trigger = null; |
||||
|
||||
long now = System.currentTimeMillis(); |
||||
|
||||
clearSignaledSchedulingChange(); |
||||
try { |
||||
trigger = qsRsrcs.getJobStore().acquireNextTrigger( |
||||
ctxt, now + idleWaitTime); |
||||
lastAcquireFailed = false; |
||||
} catch (JobPersistenceException jpe) { |
||||
if(!lastAcquireFailed) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while scanning for the next trigger to fire.", |
||||
jpe); |
||||
} |
||||
lastAcquireFailed = true; |
||||
} catch (RuntimeException e) { |
||||
if(!lastAcquireFailed) { |
||||
getLog().error("quartzSchedulerThreadLoop: RuntimeException " |
||||
+e.getMessage(), e); |
||||
} |
||||
lastAcquireFailed = true; |
||||
} |
||||
|
||||
if (trigger != null) { |
||||
|
||||
now = System.currentTimeMillis(); |
||||
long triggerTime = trigger.getNextFireTime().getTime(); |
||||
long timeUntilTrigger = triggerTime - now; |
||||
while(timeUntilTrigger > 0) { |
||||
synchronized(sigLock) { |
||||
try { |
||||
// we could have blocked a long while
|
||||
// on 'synchronize', so we must recompute
|
||||
now = System.currentTimeMillis(); |
||||
timeUntilTrigger = triggerTime - now; |
||||
if(timeUntilTrigger > 1) |
||||
sigLock.wait(timeUntilTrigger); |
||||
} catch (InterruptedException ignore) { |
||||
} |
||||
} |
||||
if (isScheduleChanged()) { |
||||
if(isCandidateNewTimeEarlierWithinReason(triggerTime)) { |
||||
// above call does a clearSignaledSchedulingChange()
|
||||
try { |
||||
qsRsrcs.getJobStore().releaseAcquiredTrigger( |
||||
ctxt, trigger); |
||||
} catch (JobPersistenceException jpe) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while releasing trigger '" |
||||
+ trigger.getFullName() + "'", |
||||
jpe); |
||||
// db connection must have failed... keep
|
||||
// retrying until it's up...
|
||||
releaseTriggerRetryLoop(trigger); |
||||
} catch (RuntimeException e) { |
||||
getLog().error( |
||||
"releaseTriggerRetryLoop: RuntimeException " |
||||
+e.getMessage(), e); |
||||
// db connection must have failed... keep
|
||||
// retrying until it's up...
|
||||
releaseTriggerRetryLoop(trigger); |
||||
} |
||||
trigger = null; |
||||
break; |
||||
} |
||||
} |
||||
now = System.currentTimeMillis(); |
||||
timeUntilTrigger = triggerTime - now; |
||||
} |
||||
if(trigger == null) |
||||
continue; |
||||
|
||||
// set trigger to 'executing'
|
||||
TriggerFiredBundle bndle = null; |
||||
|
||||
boolean goAhead = true; |
||||
synchronized(sigLock) { |
||||
goAhead = !halted; |
||||
} |
||||
if(goAhead) { |
||||
try { |
||||
bndle = qsRsrcs.getJobStore().triggerFired(ctxt, |
||||
trigger); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while firing trigger '" |
||||
+ trigger.getFullName() + "'", se); |
||||
} catch (RuntimeException e) { |
||||
getLog().error( |
||||
"RuntimeException while firing trigger " + |
||||
trigger.getFullName(), e); |
||||
// db connection must have failed... keep
|
||||
// retrying until it's up...
|
||||
releaseTriggerRetryLoop(trigger); |
||||
} |
||||
} |
||||
|
||||
// it's possible to get 'null' if the trigger was paused,
|
||||
// blocked, or other similar occurrences that prevent it being
|
||||
// fired at this time... or if the scheduler was shutdown (halted)
|
||||
if (bndle == null) { |
||||
try { |
||||
qsRsrcs.getJobStore().releaseAcquiredTrigger(ctxt, |
||||
trigger); |
||||
} catch (SchedulerException se) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while releasing trigger '" |
||||
+ trigger.getFullName() + "'", se); |
||||
// db connection must have failed... keep retrying
|
||||
// until it's up...
|
||||
releaseTriggerRetryLoop(trigger); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
// TODO: improvements:
|
||||
//
|
||||
// 2- make sure we can get a job runshell before firing trigger, or
|
||||
// don't let that throw an exception (right now it never does,
|
||||
// but the signature says it can).
|
||||
// 3- acquire more triggers at a time (based on num threads available?)
|
||||
|
||||
|
||||
JobRunShell shell = null; |
||||
try { |
||||
shell = qsRsrcs.getJobRunShellFactory().borrowJobRunShell(); |
||||
shell.initialize(qs, bndle); |
||||
} catch (SchedulerException se) { |
||||
try { |
||||
qsRsrcs.getJobStore().triggeredJobComplete(ctxt, |
||||
trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR); |
||||
} catch (SchedulerException se2) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while placing job's triggers in error state '" |
||||
+ trigger.getFullName() + "'", se2); |
||||
// db connection must have failed... keep retrying
|
||||
// until it's up...
|
||||
errorTriggerRetryLoop(bndle); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (qsRsrcs.getThreadPool().runInThread(shell) == false) { |
||||
try { |
||||
// this case should never happen, as it is indicative of the
|
||||
// scheduler being shutdown or a bug in the thread pool or
|
||||
// a thread pool being used concurrently - which the docs
|
||||
// say not to do...
|
||||
getLog().error("ThreadPool.runInThread() return false!"); |
||||
qsRsrcs.getJobStore().triggeredJobComplete(ctxt, |
||||
trigger, bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR); |
||||
} catch (SchedulerException se2) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while placing job's triggers in error state '" |
||||
+ trigger.getFullName() + "'", se2); |
||||
// db connection must have failed... keep retrying
|
||||
// until it's up...
|
||||
releaseTriggerRetryLoop(trigger); |
||||
} |
||||
} |
||||
|
||||
continue; |
||||
} |
||||
} else { // if(availTreadCount > 0)
|
||||
continue; // should never happen, if threadPool.blockForAvailableThreads() follows contract
|
||||
} |
||||
|
||||
long now = System.currentTimeMillis(); |
||||
long waitTime = now + getRandomizedIdleWaitTime(); |
||||
long timeUntilContinue = waitTime - now; |
||||
synchronized(sigLock) { |
||||
try { |
||||
sigLock.wait(timeUntilContinue); |
||||
} catch (InterruptedException ignore) { |
||||
} |
||||
} |
||||
|
||||
} catch(RuntimeException re) { |
||||
getLog().error("Runtime error occured in main trigger firing loop.", re); |
||||
} |
||||
} // loop...
|
||||
|
||||
// drop references to scheduler stuff to aid garbage collection...
|
||||
qs = null; |
||||
qsRsrcs = null; |
||||
} |
||||
|
||||
private boolean isCandidateNewTimeEarlierWithinReason(long oldTime) { |
||||
|
||||
// So here's the deal: We know due to being signaled that 'the schedule'
|
||||
// has changed. We may know (if getSignaledNextFireTime() != 0) the
|
||||
// new earliest fire time. We may not (in which case we will assume
|
||||
// that the new time is earlier than the trigger we have acquired).
|
||||
// In either case, we only want to abandon our acquired trigger and
|
||||
// go looking for a new one if "it's worth it". It's only worth it if
|
||||
// the time cost incurred to abandon the trigger and acquire a new one
|
||||
// is less than the time until the currently acquired trigger will fire,
|
||||
// otherwise we're just "thrashing" the job store (e.g. database).
|
||||
//
|
||||
// So the question becomes when is it "worth it"? This will depend on
|
||||
// the job store implementation (and of course the particular database
|
||||
// or whatever behind it). Ideally we would depend on the job store
|
||||
// implementation to tell us the amount of time in which it "thinks"
|
||||
// it can abandon the acquired trigger and acquire a new one. However
|
||||
// we have no current facility for having it tell us that, so we make
|
||||
// a somewhat educated but arbitrary guess ;-).
|
||||
|
||||
synchronized(sigLock) { |
||||
|
||||
boolean earlier = false; |
||||
|
||||
if(getSignaledNextFireTime() == 0) |
||||
earlier = true; |
||||
else if(getSignaledNextFireTime() < oldTime ) |
||||
earlier = true; |
||||
|
||||
if(earlier) { |
||||
// so the new time is considered earlier, but is it enough earlier?
|
||||
// le
|
||||
long diff = oldTime - System.currentTimeMillis(); |
||||
if(diff < (qsRsrcs.getJobStore().supportsPersistence() ? 80L : 7L)) |
||||
earlier = false; |
||||
} |
||||
|
||||
clearSignaledSchedulingChange(); |
||||
|
||||
return earlier; |
||||
} |
||||
} |
||||
|
||||
public void errorTriggerRetryLoop(TriggerFiredBundle bndle) { |
||||
int retryCount = 0; |
||||
try { |
||||
while (!halted) { |
||||
try { |
||||
Thread.sleep(getDbFailureRetryInterval()); // retry every N
|
||||
// seconds (the db
|
||||
// connection must
|
||||
// be failed)
|
||||
retryCount++; |
||||
qsRsrcs.getJobStore().triggeredJobComplete(ctxt, |
||||
bndle.getTrigger(), bndle.getJobDetail(), Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_ERROR); |
||||
retryCount = 0; |
||||
break; |
||||
} catch (JobPersistenceException jpe) { |
||||
if(retryCount % 4 == 0) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while releasing trigger '" |
||||
+ bndle.getTrigger().getFullName() + "'", jpe); |
||||
} |
||||
} catch (RuntimeException e) { |
||||
getLog().error("releaseTriggerRetryLoop: RuntimeException "+e.getMessage(), e); |
||||
} catch (InterruptedException e) { |
||||
getLog().error("releaseTriggerRetryLoop: InterruptedException "+e.getMessage(), e); |
||||
} |
||||
} |
||||
} finally { |
||||
if(retryCount == 0) { |
||||
getLog().info("releaseTriggerRetryLoop: connection restored."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void releaseTriggerRetryLoop(Trigger trigger) { |
||||
int retryCount = 0; |
||||
try { |
||||
while (!halted) { |
||||
try { |
||||
Thread.sleep(getDbFailureRetryInterval()); // retry every N
|
||||
// seconds (the db
|
||||
// connection must
|
||||
// be failed)
|
||||
retryCount++; |
||||
qsRsrcs.getJobStore().releaseAcquiredTrigger(ctxt, trigger); |
||||
retryCount = 0; |
||||
break; |
||||
} catch (JobPersistenceException jpe) { |
||||
if(retryCount % 4 == 0) { |
||||
qs.notifySchedulerListenersError( |
||||
"An error occured while releasing trigger '" |
||||
+ trigger.getFullName() + "'", jpe); |
||||
} |
||||
} catch (RuntimeException e) { |
||||
getLog().error("releaseTriggerRetryLoop: RuntimeException "+e.getMessage(), e); |
||||
} catch (InterruptedException e) { |
||||
getLog().error("releaseTriggerRetryLoop: InterruptedException "+e.getMessage(), e); |
||||
} |
||||
} |
||||
} finally { |
||||
if(retryCount == 0) { |
||||
getLog().info("releaseTriggerRetryLoop: connection restored."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
} // end of QuartzSchedulerThread
|
@ -0,0 +1,235 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import java.rmi.Remote; |
||||
import java.rmi.RemoteException; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
import com.fr.third.org.quartz.JobDataMap; |
||||
import com.fr.third.org.quartz.JobDetail; |
||||
import com.fr.third.org.quartz.JobListener; |
||||
import com.fr.third.org.quartz.SchedulerContext; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.SchedulerListener; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
import com.fr.third.org.quartz.TriggerListener; |
||||
import com.fr.third.org.quartz.UnableToInterruptJobException; |
||||
|
||||
/** |
||||
* @author James House |
||||
*/ |
||||
public interface RemotableQuartzScheduler extends Remote { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
String getSchedulerName() throws RemoteException; |
||||
|
||||
String getSchedulerInstanceId() throws RemoteException; |
||||
|
||||
SchedulerContext getSchedulerContext() throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
void start() throws SchedulerException, RemoteException; |
||||
|
||||
void startDelayed(int seconds) throws SchedulerException, RemoteException; |
||||
|
||||
void standby() throws RemoteException; |
||||
|
||||
boolean isInStandbyMode() throws RemoteException; |
||||
|
||||
void shutdown() throws RemoteException; |
||||
|
||||
void shutdown(boolean waitForJobsToComplete) throws RemoteException; |
||||
|
||||
boolean isShutdown() throws RemoteException; |
||||
|
||||
Date runningSince() throws RemoteException; |
||||
|
||||
String getVersion() throws RemoteException; |
||||
|
||||
int numJobsExecuted() throws RemoteException; |
||||
|
||||
Class getJobStoreClass() throws RemoteException; |
||||
|
||||
boolean supportsPersistence() throws RemoteException; |
||||
|
||||
Class getThreadPoolClass() throws RemoteException; |
||||
|
||||
int getThreadPoolSize() throws RemoteException; |
||||
|
||||
List getCurrentlyExecutingJobs() throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
Date scheduleJob(SchedulingContext ctxt, JobDetail jobDetail, |
||||
Trigger trigger) throws SchedulerException, RemoteException; |
||||
|
||||
Date scheduleJob(SchedulingContext ctxt, Trigger trigger) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void addJob(SchedulingContext ctxt, JobDetail jobDetail, |
||||
boolean replace) throws SchedulerException, RemoteException; |
||||
|
||||
boolean deleteJob(SchedulingContext ctxt, String jobName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
boolean unscheduleJob(SchedulingContext ctxt, String triggerName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
Date rescheduleJob(SchedulingContext ctxt, String triggerName, |
||||
String groupName, Trigger newTrigger) throws SchedulerException, RemoteException; |
||||
|
||||
|
||||
void triggerJob(SchedulingContext ctxt, String jobName, |
||||
String groupName, JobDataMap data) throws SchedulerException, RemoteException; |
||||
|
||||
void triggerJobWithVolatileTrigger(SchedulingContext ctxt, |
||||
String jobName, String groupName, JobDataMap data) throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
void pauseTrigger(SchedulingContext ctxt, String triggerName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
void pauseTriggerGroup(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void pauseJob(SchedulingContext ctxt, String jobName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
void pauseJobGroup(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void resumeTrigger(SchedulingContext ctxt, String triggerName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
void resumeTriggerGroup(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
Set getPausedTriggerGroups(SchedulingContext ctxt) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void resumeJob(SchedulingContext ctxt, String jobName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
void resumeJobGroup(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void pauseAll(SchedulingContext ctxt) throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
void resumeAll(SchedulingContext ctxt) throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
String[] getJobGroupNames(SchedulingContext ctxt) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
String[] getJobNames(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
Trigger[] getTriggersOfJob(SchedulingContext ctxt, String jobName, |
||||
String groupName) throws SchedulerException, RemoteException; |
||||
|
||||
String[] getTriggerGroupNames(SchedulingContext ctxt) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
String[] getTriggerNames(SchedulingContext ctxt, String groupName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
JobDetail getJobDetail(SchedulingContext ctxt, String jobName, |
||||
String jobGroup) throws SchedulerException, RemoteException; |
||||
|
||||
Trigger getTrigger(SchedulingContext ctxt, String triggerName, |
||||
String triggerGroup) throws SchedulerException, RemoteException; |
||||
|
||||
int getTriggerState(SchedulingContext ctxt, String triggerName, |
||||
String triggerGroup) throws SchedulerException, RemoteException; |
||||
|
||||
void addCalendar(SchedulingContext ctxt, String calName, |
||||
Calendar calendar, boolean replace, boolean updateTriggers) throws SchedulerException, |
||||
RemoteException; |
||||
|
||||
boolean deleteCalendar(SchedulingContext ctxt, String calName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
Calendar getCalendar(SchedulingContext ctxt, String calName) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
String[] getCalendarNames(SchedulingContext ctxt) |
||||
throws SchedulerException, RemoteException; |
||||
|
||||
void addGlobalJobListener(JobListener jobListener) |
||||
throws RemoteException; |
||||
|
||||
void addJobListener(JobListener jobListener) throws RemoteException; |
||||
|
||||
boolean removeGlobalJobListener(String name) throws RemoteException; |
||||
|
||||
boolean removeJobListener(String name) throws RemoteException; |
||||
|
||||
List getGlobalJobListeners() throws RemoteException; |
||||
|
||||
Set getJobListenerNames() throws RemoteException; |
||||
|
||||
JobListener getGlobalJobListener(String name) throws RemoteException; |
||||
|
||||
JobListener getJobListener(String name) throws RemoteException; |
||||
|
||||
void addGlobalTriggerListener(TriggerListener triggerListener) |
||||
throws RemoteException; |
||||
|
||||
void addTriggerListener(TriggerListener triggerListener) |
||||
throws RemoteException; |
||||
|
||||
boolean removeGlobalTriggerListener(String name) |
||||
throws RemoteException; |
||||
|
||||
boolean removeTriggerListener(String name) throws RemoteException; |
||||
|
||||
List getGlobalTriggerListeners() throws RemoteException; |
||||
|
||||
Set getTriggerListenerNames() throws RemoteException; |
||||
|
||||
TriggerListener getGlobalTriggerListener(String name) |
||||
throws RemoteException; |
||||
|
||||
TriggerListener getTriggerListener(String name) |
||||
throws RemoteException; |
||||
|
||||
void addSchedulerListener(SchedulerListener schedulerListener) |
||||
throws RemoteException; |
||||
|
||||
boolean removeSchedulerListener(SchedulerListener schedulerListener) |
||||
throws RemoteException; |
||||
|
||||
List getSchedulerListeners() throws RemoteException; |
||||
|
||||
boolean interrupt(SchedulingContext ctxt, String jobName, String groupName) throws UnableToInterruptJobException,RemoteException ; |
||||
} |
@ -0,0 +1,93 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
import com.fr.third.org.quartz.spi.SchedulerSignaler; |
||||
|
||||
/** |
||||
* An interface to be used by <code>JobStore</code> instances in order to |
||||
* communicate signals back to the <code>QuartzScheduler</code>. |
||||
* |
||||
* @author jhouse |
||||
*/ |
||||
public class SchedulerSignalerImpl implements SchedulerSignaler { |
||||
|
||||
Log log = LogFactory.getLog(SchedulerSignalerImpl.class); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected QuartzScheduler sched; |
||||
protected QuartzSchedulerThread schedThread; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public SchedulerSignalerImpl(QuartzScheduler sched, QuartzSchedulerThread schedThread) { |
||||
this.sched = sched; |
||||
this.schedThread = schedThread; |
||||
|
||||
log.info("Initialized Scheduler Signaller of type: " + getClass()); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public void notifyTriggerListenersMisfired(Trigger trigger) { |
||||
try { |
||||
sched.notifyTriggerListenersMisfired(trigger); |
||||
} catch (SchedulerException se) { |
||||
sched.getLog().error( |
||||
"Error notifying listeners of trigger misfire.", se); |
||||
sched.notifySchedulerListenersError( |
||||
"Error notifying listeners of trigger misfire.", se); |
||||
} |
||||
} |
||||
|
||||
public void notifySchedulerListenersFinalized(Trigger trigger) { |
||||
sched.notifySchedulerListenersFinalized(trigger); |
||||
} |
||||
|
||||
public void signalSchedulingChange(long candidateNewNextFireTime) { |
||||
schedThread.signalSchedulingChange(candidateNewNextFireTime); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,87 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.core; |
||||
|
||||
/** |
||||
* <p> |
||||
* An object used to pass information about the 'client' to the <code>QuartzScheduler</code>. |
||||
* </p> |
||||
* |
||||
* @see QuartzScheduler |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulingContext implements java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private String instanceId; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Construct a SchedulingContext with default values. |
||||
* </p> |
||||
*/ |
||||
public SchedulingContext() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* get the instanceId in the cluster. |
||||
* </p> |
||||
*/ |
||||
public String getInstanceId() { |
||||
return this.instanceId; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the instanceId. |
||||
* </p> |
||||
*/ |
||||
public void setInstanceId(String instanceId) { |
||||
this.instanceId = instanceId; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,234 @@
|
||||
<?xml version="1.0"?> |
||||
<!DOCTYPE mbeans-descriptors PUBLIC "-//Apache Software Foundation//DTD Model MBeans Configuration File" |
||||
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd"> |
||||
<mbeans-descriptors> |
||||
<mbean name="QuartzScheduler" description="A Quartz Scheduler." domain="quartz" type="com.fr.third.org.quartz.core.QuartzScheduler"> |
||||
|
||||
<!-- ATTRIBUTES --> |
||||
<attribute name="schedulerName" description="The name of the scheduler." type="java.lang.String" writeable="false"/> |
||||
<attribute name="schedulerInstanceId" description="The instance Id of the scheduler." type="java.lang.String" writeable="false"/> |
||||
<attribute name="schedulerContext" description="The SchedulerContext of the scheduler." type="com.fr.third.org.quartz.SchedulerContext" writeable="false"/> |
||||
<attribute name="inStandbyMode" description="Whether the scheduler is currently in standby (paused)." type="boolean" writeable="false" is="true"/> |
||||
<attribute name="shutdown" description="Whether the scheduler has been shutdown." type="boolean" writeable="false" is="true"/> |
||||
<attribute name="jobFactory" description="The JobFactory that will be responsible for producing instances of Job classes." type="com.fr.third.org.quartz.spi.JobFactory" readable="false" writeable="true"/> |
||||
<attribute name="version" description="Quartz version." type="java.lang.String" writeable="false"/> |
||||
<attribute name="jobStoreClass" description="Class of this scheduler's JobStore." type="java.lang.Class" writeable="false"/> |
||||
<attribute name="threadPoolClass" description="Class of this scheduler's ThreadPool." type="java.lang.Class" writeable="false"/> |
||||
<attribute name="threadPoolSize" description="Number of threads in this scheduler's ThreadPool." type="int" writeable="false"/> |
||||
|
||||
<!-- OPERATIONS--> |
||||
<operation name="start" description="Starts the scheduler's threads that fire Triggers." impact="ACTION" returnType="void"/> |
||||
<operation name="standby" description="Temporarily halts the scheduler's firing of Triggers." impact="ACTION" returnType="void"/> |
||||
<operation name="shutdown" description="Halts the scheduler's firing of Triggers, and cleans up all resources associated with the scheduler." impact="ACTION" returnType="void"/> |
||||
<operation name="shutdown" description="Halts the scheduler's firing of Triggers, and cleans up all resources associated with the scheduler." impact="ACTION" returnType="void"> |
||||
<parameter name="waitForJobsToComplete" description="If true the scheduler will not allow this method to return until all currently executing jobs have completed." type="boolean"/> |
||||
</operation> |
||||
|
||||
<operation name="runningSince" description="Get Date scheduler was first started." impact="INFO" returnType="java.util.Date"/> |
||||
<operation name="numJobsExecuted" description="Get total number of jobs executed by this scheduler." impact="INFO" returnType="int"/> |
||||
<operation name="supportsPersistence" description="Get whether this scheduler's JobStore supports persistence." impact="INFO" returnType="boolean"/> |
||||
<operation name="getCurrentlyExecutingJobs" description="Get a list of JobExecutionContext objects that represent all currently executing Jobs in this scheduler instance." impact="INFO" returnType="java.util.List"/> |
||||
|
||||
<operation name="scheduleJob" description="Add the given JobDetail to the Scheduler, and associate the given Trigger with it." impact="ACTION" returnType="java.util.Date"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobDetail" type="com.fr.third.org.quartz.JobDetail" description="The JobDetail to schedule."/> |
||||
<parameter name="trigger" type="com.fr.third.org.quartz.Trigger" description="The Trigger to schedule."/> |
||||
</operation> |
||||
<operation name="scheduleJob" description="Schedule the given Trigger with the Job identified by the Trigger's settings." impact="ACTION" returnType="java.util.Date"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="trigger" type="com.fr.third.org.quartz.Trigger" description="The Trigger to schedule."/> |
||||
</operation> |
||||
<operation name="unscheduleJob" description="Remove the indicated Triggerfrom the scheduler." impact="ACTION" returnType="boolean"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the Trigger to unschedule."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Trigger to unschedule."/> |
||||
</operation> |
||||
<operation name="rescheduleJob" description="Remove (delete) the Trigger with the given name, and store the new given one - which must be associated with the same job (the new trigger must have the job name and group specified) - however, the new trigger need not have the same name as the old trigger." impact="ACTION" returnType="java.util.Date"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the Trigger to be replaced."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Trigger to be replaced."/> |
||||
<parameter name="newTrigger" type="com.fr.third.org.quartz.Trigger" description="The new Trigger to be stored."/> |
||||
</operation> |
||||
|
||||
<operation name="addJob" description="Add the given Job to the Scheduler - with no associated Trigger." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobDetail" type="com.fr.third.org.quartz.JobDetail" description="The JobDetail to add."/> |
||||
<parameter name="replace" type="boolean" description="Whether or not to replace an existing Job with the given one."/> |
||||
</operation> |
||||
<operation name="deleteJob" description="Delete the identified Job from the Scheduler - and any associated Triggers." impact="ACTION" returnType="boolean"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the Job to delete."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Job to delete."/> |
||||
</operation> |
||||
|
||||
<operation name="triggerJob" description="Trigger the identified JobDetail (execute it now) - the generated trigger will be non-volatile." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the Job to trigger."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Job to trigger."/> |
||||
<parameter name="jobDataMap" type="com.fr.third.org.quartz.JobDataMap" description="The (possibly null) JobDataMap to be associated with the trigger that fires the job immediately."/> |
||||
</operation> |
||||
<operation name="triggerJobWithVolatileTrigger" description="Trigger the identified JobDetail (execute it now) - the generated trigger will be volatile." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the Job to trigger."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Job to trigger."/> |
||||
<parameter name="jobDataMap" type="com.fr.third.org.quartz.JobDataMap" description="The (possibly null) JobDataMap to be associated with the trigger that fires the job immediately."/> |
||||
</operation> |
||||
|
||||
|
||||
<operation name="interrupt" description="Request the interruption, within this scheduler instance, of all currently executing instances of the identified Job, which must be an implementor of the InterruptableJob interface." impact="ACTION" returnType="boolean"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the trigger to interrupt."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The name of the trigger group to interrupt."/> |
||||
</operation> |
||||
|
||||
<operation name="pauseJob" description="Pause the JobDetail with the given name - by pausing all of its current Triggers." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the Job to pause."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Job to pause."/> |
||||
</operation> |
||||
<operation name="pauseJobGroup" description="Pause all of the JobDetails in the given group - by pausing all of theirTriggers." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Jobs to pause."/> |
||||
</operation> |
||||
<operation name="pauseTrigger" description="Pause the Trigger with the given name." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the Trigger to pause."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Trigger to pause."/> |
||||
</operation> |
||||
<operation name="pauseTriggerGroup" description="Pause all of the Triggers in the given group." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Triggers to pause."/> |
||||
</operation> |
||||
<operation name="resumeJob" description="Resume (un-pause) the JobDetail with the given name." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the Job to resume."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Job to resume."/> |
||||
</operation> |
||||
<operation name="resumeJobGroup" description="Resume (un-pause) all of the JobDetails in the given group." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The group name of the Jobs to resume."/> |
||||
</operation> |
||||
<operation name="resumeTrigger" description="Resume (un-pause) the Trigger with the given name." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the Trigger to resume."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Trigger to resume."/> |
||||
</operation> |
||||
<operation name="resumeTriggerGroup" description="Resume (un-pause) all of the Triggers in the given group." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The group name of the Triggers to resume."/> |
||||
</operation> |
||||
<operation name="pauseAll" description="Pause all triggers - similar to calling pauseTriggerGroup(group) on every group, however, after using this method resumeAll() must be called to clear the scheduler's state of 'remembering' that all new triggers will be paused as they are added." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
<operation name="resumeAll" description="Resume (un-pause) all triggers - similar to calling resumeTriggerGroup(group) on every group." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
<operation name="getPausedTriggerGroups" description="Get the names of all Trigger groups that are paused." impact="INFO" returnType="java.util.Set"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
|
||||
<operation name="getJobGroupNames" description="Get the names of all known JobDetail groups." impact="INFO" returnType="[Ljava.lang.String;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
<operation name="getJobNames" description="Get the names of all the JobDetails in the given group." impact="INFO" returnType="[Ljava.lang.String;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The job group name."/> |
||||
</operation> |
||||
<operation name="getTriggersOfJob" description="Get all Triggers that are associated with the identified JobDetail." impact="INFO" returnType="[Lcom.fr.third.org.quartz.Trigger;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the job."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The name of the job group."/> |
||||
</operation> |
||||
<operation name="getTriggerGroupNames" description="Get the names of all known Trigger groups." impact="INFO" returnType="[Ljava.lang.String;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
<operation name="getTriggerNames" description="Get the names of all the Triggers in the given group." impact="INFO" returnType="[Ljava.lang.String;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The trigger group name."/> |
||||
</operation> |
||||
<operation name="getJobDetail" description="Get the JobDetail for the Job instance with the given name and group." impact="INFO" returnType="[Lcom.fr.third.org.quartz.JobDetail;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="jobName" type="java.lang.String" description="The name of the job."/> |
||||
<parameter name="jobGroupName" type="java.lang.String" description="The name of the job group."/> |
||||
</operation> |
||||
<operation name="getTrigger" description="Get the Trigger instance with the given name and group." impact="INFO" returnType="[Lcom.fr.third.org.quartz.Trigger;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the trigger."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The name of the trigger group."/> |
||||
</operation> |
||||
<operation name="getTriggerState" description="Get the current state of the identified Trigger." impact="INFO" returnType="int"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="triggerName" type="java.lang.String" description="The name of the trigger."/> |
||||
<parameter name="triggerGroupName" type="java.lang.String" description="The name of the trigger group."/> |
||||
</operation> |
||||
|
||||
<operation name="addCalendar" description="Add (register) the given Calendar to the scheduler." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="calendarName" type="java.lang.String" description="Name of the calendar to add."/> |
||||
<parameter name="calendar" type="com.fr.third.org.quartz.Calendar" description="The Calendar instance to add."/> |
||||
<parameter name="replace" type="boolean" description="Whether to allow replacing an existing Calendar instance."/> |
||||
<parameter name="updateTriggers" type="boolean" description="Whether or not to update existing triggers that referenced the already existing calendar so that they are 'correct' based on the new trigger."/> |
||||
</operation> |
||||
<operation name="deleteCalendar" description="Delete the identified Calendar from the scheduler." impact="ACTION" returnType="boolean"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="calendarName" type="java.lang.String" description="Name of the Calendar to delete."/> |
||||
</operation> |
||||
<operation name="getCalendar" description="Get the Calendar instance with the given name." impact="INFO" returnType="com.fr.third.org.quartz.Calendar"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
<parameter name="calendarName" type="java.lang.String" description="Name of the Calendar to get."/> |
||||
</operation> |
||||
<operation name="getCalendarNames" description="Get the names of all registered Calendars." impact="INFO" returnType="[Ljava.lang.String;"> |
||||
<parameter name="schedulingContext" type="com.fr.third.org.quartz.core.SchedulingContext" description="The scheduling context."/> |
||||
</operation> |
||||
|
||||
<operation name="addGlobalJobListener" description="Add the given JobListener to the scheduler's global list." impact="ACTION" returnType="void"> |
||||
<parameter name="jobListener" type="com.fr.third.org.quartz.JobListener" description="Job listener to add."/> |
||||
</operation> |
||||
<operation name="addJobListener" description="Add the given JobListener to the scheduler's list, of registered JobListeners." impact="ACTION" returnType="void"> |
||||
<parameter name="jobListener" type="com.fr.third.org.quartz.JobListener" description="Job listener to add."/> |
||||
</operation> |
||||
<operation name="removeGlobalJobListener" description="Remove the identifed JobListener from the scheduler's list of global listeners." impact="ACTION" returnType="boolean"> |
||||
<parameter name="jobListenerName" type="java.lang.String" description="Name of the global JobListener to remove."/> |
||||
</operation> |
||||
<operation name="removeJobListener" description="Remove the identifed JobListener from the scheduler's list of registered listeners." impact="ACTION" returnType="boolean"> |
||||
<parameter name="jobListenerName" type="java.lang.String" description="Name of the JobListener to remove."/> |
||||
</operation> |
||||
<operation name="getGlobalJobListeners" description="Get a List containing all of the JobListeners in the scheduler's global list." impact="INFO" returnType="java.util.List"/> |
||||
<operation name="getJobListenerNames" description="Get a Set containing the names of all the non-global JobListeners registered with the scheduler." impact="INFO" returnType="java.util.Set"/> |
||||
<operation name="getGlobalJobListener" description="Get the global JobListener that has the given name." impact="INFO" returnType="com.fr.third.org.quartz.JobListener"> |
||||
<parameter name="jobListenerName" type="java.lang.String" description="Name of the global JobListener to get."/> |
||||
</operation> |
||||
<operation name="getJobListener" description="Get the non-global JobListener that has the given name." impact="INFO" returnType="com.fr.third.org.quartz.JobListener"> |
||||
<parameter name="jobListenerName" type="java.lang.String" description="Name of the JobListener to get."/> |
||||
</operation> |
||||
|
||||
<operation name="addGlobalTriggerListener" description="Add the given TriggerListener to the scheduler's global list." impact="ACTION" returnType="void"> |
||||
<parameter name="triggerListener" type="com.fr.third.org.quartz.TriggerListener" description="Trigger listener to add."/> |
||||
</operation> |
||||
<operation name="addTriggerListener" description="Add the given TriggerListener to the scheduler's list, of registered TriggerListeners." impact="ACTION" returnType="void"> |
||||
<parameter name="triggerListener" type="com.fr.third.org.quartz.TriggerListener" description="Trigger listener to add."/> |
||||
</operation> |
||||
<operation name="removeGlobalTriggerListener" description="Remove the identifed TriggerListener from the scheduler's list of global listeners." impact="ACTION" returnType="boolean"> |
||||
<parameter name="triggerListenerName" type="java.lang.String" description="Name of the global TriggerListener to remove."/> |
||||
</operation> |
||||
<operation name="removeTriggerListener" description="Remove the identifed TriggerListener from the scheduler's list of registered listeners." impact="ACTION" returnType="boolean"> |
||||
<parameter name="triggerListenerName" type="java.lang.String" description="Name of the TriggerListener to remove."/> |
||||
</operation> |
||||
<operation name="getGlobalTriggerListeners" description="Get a List containing all of the TriggerListeners in the scheduler's global list." impact="INFO" returnType="java.util.List"/> |
||||
<operation name="getTriggerListenerNames" description="Get a Set containing the names of all the non-global TriggerListeners registered with the scheduler." impact="INFO" returnType="java.util.Set"/> |
||||
<operation name="getGlobalTriggerListener" description="Get the global TriggerListener that has the given name." impact="INFO" returnType="com.fr.third.org.quartz.TriggerListener"> |
||||
<parameter name="triggerListenerName" type="java.lang.String" description="Name of the global TriggerListener to get."/> |
||||
</operation> |
||||
<operation name="getTriggerListener" description="Get the non-global TriggerListener that has the given name." impact="INFO" returnType="com.fr.third.org.quartz.TriggerListener"> |
||||
<parameter name="triggerListenerName" type="java.lang.String" description="Name of the TriggerListener to get."/> |
||||
</operation> |
||||
|
||||
<operation name="addSchedulerListener" description="Register the given SchedulerListener with the scheduler." impact="ACTION" returnType="void"> |
||||
<parameter name="schedulerListener" type="com.fr.third.org.quartz.SchedulerListener" description="Scheduler listener to add."/> |
||||
</operation> |
||||
<operation name="removeSchedulerListener" description="Remove the given SchedulerListener from the scheduler." impact="ACTION" returnType="boolean"> |
||||
<parameter name="schedulerListener" type="com.fr.third.org.quartz.SchedulerListener" description="Scheduler listener to remove."/> |
||||
</operation> |
||||
<operation name="getSchedulerListeners" description="Get a List containing all of the SchedulerListeners registered with the scheduler." impact="INFO" returnType="java.util.List"/> |
||||
</mbean> |
||||
</mbeans-descriptors> |
@ -0,0 +1,15 @@
|
||||
<html> |
||||
<head> |
||||
<title>Package com.fr.third.org.quartz.core</title> |
||||
</head> |
||||
<body> |
||||
<p>Contains the core classes and interfaces for the <b>Quartz</b> job scheduler.</p> |
||||
|
||||
<br> |
||||
<br> |
||||
<hr> |
||||
See the <a href="http://www.opensymphony.com/quartz">Quartz</a> project |
||||
at <a href="http://www.opensymphony.com">Open Symphony</a> for more information. |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,166 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.ee.jta; |
||||
|
||||
import javax.transaction.Status; |
||||
import javax.transaction.SystemException; |
||||
import javax.transaction.UserTransaction; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.core.JobRunShell; |
||||
import com.fr.third.org.quartz.core.JobRunShellFactory; |
||||
import com.fr.third.org.quartz.core.SchedulingContext; |
||||
|
||||
/** |
||||
* <p> |
||||
* An extension of <code>{@link com.fr.third.org.quartz.core.JobRunShell}</code> that |
||||
* begins an XA transaction before executing the Job, and commits (or |
||||
* rolls-back) the transaction after execution completes. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.core.JobRunShell |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JTAJobRunShell extends JobRunShell { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private UserTransaction ut; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Create a JTAJobRunShell instance with the given settings. |
||||
* </p> |
||||
*/ |
||||
public JTAJobRunShell(JobRunShellFactory jobRunShellFactory, |
||||
Scheduler scheduler, SchedulingContext schdCtxt) { |
||||
super(jobRunShellFactory, scheduler, schdCtxt); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected void begin() throws SchedulerException { |
||||
// Don't get a new UserTransaction w/o making sure we cleaned up the old
|
||||
// one. This is necessary because there are paths through JobRunShell.run()
|
||||
// where begin() can be called multiple times w/o complete being called in
|
||||
// between.
|
||||
cleanupUserTransaction(); |
||||
|
||||
boolean beganSuccessfully = false; |
||||
try { |
||||
getLog().debug("Looking up UserTransaction."); |
||||
ut = UserTransactionHelper.lookupUserTransaction(); |
||||
|
||||
getLog().debug("Beginning UserTransaction."); |
||||
ut.begin(); |
||||
|
||||
beganSuccessfully = true; |
||||
} catch (SchedulerException se) { |
||||
throw se; |
||||
} catch (Exception nse) { |
||||
|
||||
throw new SchedulerException( |
||||
"JTAJobRunShell could not start UserTransaction.", nse); |
||||
} finally { |
||||
if (beganSuccessfully == false) { |
||||
cleanupUserTransaction(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void complete(boolean successfulExecution) |
||||
throws SchedulerException { |
||||
if (ut == null) { |
||||
return; |
||||
} |
||||
|
||||
try { |
||||
try { |
||||
if (ut.getStatus() == Status.STATUS_MARKED_ROLLBACK) { |
||||
getLog().debug("UserTransaction marked for rollback only."); |
||||
successfulExecution = false; |
||||
} |
||||
} catch (SystemException e) { |
||||
throw new SchedulerException( |
||||
"JTAJobRunShell could not read UserTransaction status.", e); |
||||
} |
||||
|
||||
if (successfulExecution) { |
||||
try { |
||||
getLog().debug("Committing UserTransaction."); |
||||
ut.commit(); |
||||
} catch (Exception nse) { |
||||
throw new SchedulerException( |
||||
"JTAJobRunShell could not commit UserTransaction.", nse); |
||||
} |
||||
} else { |
||||
try { |
||||
getLog().debug("Rolling-back UserTransaction."); |
||||
ut.rollback(); |
||||
} catch (Exception nse) { |
||||
throw new SchedulerException( |
||||
"JTAJobRunShell could not rollback UserTransaction.", |
||||
nse); |
||||
} |
||||
} |
||||
} finally { |
||||
cleanupUserTransaction(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Override passivate() to ensure we always cleanup the UserTransaction. |
||||
*/ |
||||
public void passivate() { |
||||
cleanupUserTransaction(); |
||||
super.passivate(); |
||||
} |
||||
|
||||
private void cleanupUserTransaction() { |
||||
if (ut != null) { |
||||
UserTransactionHelper.returnUserTransaction(ut); |
||||
ut = null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,114 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.ee.jta; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerConfigException; |
||||
import com.fr.third.org.quartz.core.JobRunShell; |
||||
import com.fr.third.org.quartz.core.JobRunShellFactory; |
||||
import com.fr.third.org.quartz.core.SchedulingContext; |
||||
|
||||
/** |
||||
* <p> |
||||
* Responsible for creating the instances of <code>{@link com.fr.third.org.quartz.ee.jta.JTAJobRunShell}</code> |
||||
* to be used within the <class>{@link com.fr.third.org.quartz.core.QuartzScheduler} |
||||
* </code> instance. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This implementation does not re-use any objects, it simply makes a new |
||||
* JTAJobRunShell each time <code>borrowJobRunShell()</code> is called. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class JTAJobRunShellFactory implements JobRunShellFactory { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Scheduler scheduler; |
||||
|
||||
private SchedulingContext schedCtxt; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public JTAJobRunShellFactory() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Initialize the factory, providing a handle to the <code>Scheduler</code> |
||||
* that should be made available within the <code>JobRunShell</code> and |
||||
* the <code>JobExecutionContext</code> s within it, and a handle to the |
||||
* <code>SchedulingContext</code> that the shell will use in its own |
||||
* operations with the <code>JobStore</code>. |
||||
* </p> |
||||
*/ |
||||
public void initialize(Scheduler scheduler, SchedulingContext schedCtxt) |
||||
throws SchedulerConfigException { |
||||
this.scheduler = scheduler; |
||||
this.schedCtxt = schedCtxt; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <class>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread} |
||||
* </code> to obtain instances of <code> |
||||
* {@link com.fr.third.org.quartz.core.JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
public JobRunShell borrowJobRunShell() { |
||||
return new JTAJobRunShell(this, scheduler, schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <class>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread} |
||||
* </code> to return instances of <code> |
||||
* {@link com.fr.third.org.quartz.core.JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
public void returnJobRunShell(JobRunShell jobRunShell) { |
||||
jobRunShell.passivate(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,225 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.ee.jta; |
||||
|
||||
import javax.naming.InitialContext; |
||||
import javax.transaction.HeuristicMixedException; |
||||
import javax.transaction.HeuristicRollbackException; |
||||
import javax.transaction.NotSupportedException; |
||||
import javax.transaction.RollbackException; |
||||
import javax.transaction.SystemException; |
||||
import javax.transaction.TransactionManager; |
||||
import javax.transaction.UserTransaction; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* A helper for obtaining a handle to a UserTransaction... |
||||
* </p> |
||||
* <p> |
||||
* To ensure proper cleanup of the InitalContext used to create/lookup |
||||
* the UserTransaction, be sure to always call returnUserTransaction() when |
||||
* you are done with the UserTransaction. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class UserTransactionHelper { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final String DEFAULT_USER_TX_LOCATION = "java:comp/UserTransaction"; |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private static String userTxURL = DEFAULT_USER_TX_LOCATION; |
||||
|
||||
private static Log log = LogFactory.getLog(UserTransactionHelper.class); |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Do not allow the creation of an all static utility class. |
||||
*/ |
||||
private UserTransactionHelper() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static String getUserTxLocation() { |
||||
return userTxURL; |
||||
} |
||||
|
||||
/** |
||||
* Set the JNDI URL at which the Application Server's UserTransaction can |
||||
* be found. If not set, the default value is "java:comp/UserTransaction" - |
||||
* which works for nearly all application servers. |
||||
*/ |
||||
public static void setUserTxLocation(String userTxURL) { |
||||
if (userTxURL != null) { |
||||
UserTransactionHelper.userTxURL = userTxURL; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create/Lookup a UserTransaction in the InitialContext via the |
||||
* name set in setUserTxLocation(). |
||||
*/ |
||||
public static UserTransaction lookupUserTransaction() throws SchedulerException { |
||||
return new UserTransactionWithContext(); |
||||
} |
||||
|
||||
/** |
||||
* Return a UserTransaction that was retrieved via getUserTransaction(). |
||||
* This will make sure that the InitalContext used to lookup/create the |
||||
* UserTransaction is properly cleaned up. |
||||
*/ |
||||
public static void returnUserTransaction(UserTransaction userTransaction) { |
||||
if ((userTransaction != null) && |
||||
(userTransaction instanceof UserTransactionWithContext)) { |
||||
UserTransactionWithContext userTransactionWithContext = |
||||
(UserTransactionWithContext)userTransaction; |
||||
|
||||
userTransactionWithContext.closeContext(); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* This class wraps a UserTransaction with the InitialContext that was used |
||||
* to look it up, so that when the UserTransaction is returned to the |
||||
* UserTransactionHelper the InitialContext can be closed. |
||||
*/ |
||||
private static class UserTransactionWithContext implements UserTransaction { |
||||
InitialContext context; |
||||
UserTransaction userTransaction; |
||||
|
||||
public UserTransactionWithContext() throws SchedulerException { |
||||
try { |
||||
context = new InitialContext(); |
||||
} catch (Throwable t) { |
||||
throw new SchedulerException( |
||||
"UserTransactionHelper failed to create InitialContext to lookup/create UserTransaction.", t); |
||||
} |
||||
|
||||
try { |
||||
userTransaction = (UserTransaction)context.lookup(userTxURL); |
||||
} catch (Throwable t) { |
||||
closeContext(); |
||||
throw new SchedulerException( |
||||
"UserTransactionHelper could not lookup/create UserTransaction.", |
||||
t); |
||||
} |
||||
|
||||
if (userTransaction == null) { |
||||
closeContext(); |
||||
throw new SchedulerException( |
||||
"UserTransactionHelper could not lookup/create UserTransaction from the InitialContext."); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Close the InitialContext that was used to lookup/create the |
||||
* underlying UserTransaction. |
||||
*/ |
||||
public void closeContext() { |
||||
try { |
||||
if (context != null) { |
||||
context.close(); |
||||
} |
||||
} catch (Throwable t) { |
||||
getLog().warn("Failed to close InitialContext used to get a UserTransaction.", t); |
||||
} |
||||
context = null; |
||||
} |
||||
|
||||
/** |
||||
* When we are being garbage collected, make sure we were properly |
||||
* returned to the UserTransactionHelper. |
||||
*/ |
||||
protected void finalize() throws Throwable { |
||||
try { |
||||
if (context != null) { |
||||
getLog().warn("UserTransaction was never returned to the UserTransactionHelper."); |
||||
closeContext(); |
||||
} |
||||
} finally { |
||||
super.finalize(); |
||||
} |
||||
} |
||||
|
||||
private static Log getLog() { |
||||
return LogFactory.getLog(UserTransactionWithContext.class); |
||||
} |
||||
|
||||
// Wrapper methods that just delegate to the underlying UserTransaction
|
||||
|
||||
public void begin() throws NotSupportedException, SystemException { |
||||
userTransaction.begin(); |
||||
} |
||||
|
||||
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { |
||||
userTransaction.commit(); |
||||
} |
||||
|
||||
public void rollback() throws IllegalStateException, SecurityException, SystemException { |
||||
userTransaction.rollback(); |
||||
} |
||||
|
||||
public void setRollbackOnly() throws IllegalStateException, SystemException { |
||||
userTransaction.setRollbackOnly(); |
||||
} |
||||
|
||||
public int getStatus() throws SystemException { |
||||
return userTransaction.getStatus(); |
||||
} |
||||
|
||||
public void setTransactionTimeout(int seconds) throws SystemException { |
||||
userTransaction.setTransactionTimeout(seconds); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,54 @@
|
||||
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.helpers; |
||||
|
||||
import com.fr.third.org.quartz.core.QuartzScheduler; |
||||
|
||||
/** |
||||
* <p> |
||||
* Prints the version of Quartz on stdout. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class VersionPrinter { |
||||
|
||||
/** |
||||
* Private constructor because this is a pure utility class. |
||||
*/ |
||||
private VersionPrinter() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println("Quartz version: " + QuartzScheduler.getVersionMajor() |
||||
+ "." + QuartzScheduler.getVersionMinor() + "." |
||||
+ QuartzScheduler.getVersionIteration()); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
<html> |
||||
<head> |
||||
<title>Package com.fr.third.org.quartz.helpers</title> |
||||
</head> |
||||
<body> |
||||
<p>Contains helper classes to make working with Quartz easier.</p> |
||||
|
||||
<br> |
||||
<br> |
||||
<hr> |
||||
See the <a href="http://www.opensymphony.com/quartz">Quartz</a> project |
||||
at <a href="http://www.opensymphony.com">Open Symphony</a> for more information. |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,482 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.SchedulerFactory; |
||||
import com.fr.third.org.quartz.core.JobRunShellFactory; |
||||
import com.fr.third.org.quartz.core.QuartzScheduler; |
||||
import com.fr.third.org.quartz.core.QuartzSchedulerResources; |
||||
import com.fr.third.org.quartz.core.SchedulingContext; |
||||
import com.fr.third.org.quartz.simpl.CascadingClassLoadHelper; |
||||
import com.fr.third.org.quartz.simpl.RAMJobStore; |
||||
import com.fr.third.org.quartz.simpl.SimpleThreadPool; |
||||
import com.fr.third.org.quartz.spi.ClassLoadHelper; |
||||
import com.fr.third.org.quartz.spi.JobStore; |
||||
import com.fr.third.org.quartz.spi.SchedulerPlugin; |
||||
import com.fr.third.org.quartz.spi.ThreadPool; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* <p> |
||||
* A singleton implementation of <code>{@link com.fr.third.org.quartz.SchedulerFactory}</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Here are some examples of using this class: |
||||
* </p> |
||||
* <p> |
||||
* To create a scheduler that does not write anything to the database (is not |
||||
* persistent), you can call <code>createVolatileScheduler</code>: |
||||
* |
||||
* <pre> |
||||
* DirectSchedulerFactory.getInstance().createVolatileScheduler(10); // 10 threads * // don't forget to start the scheduler: DirectSchedulerFactory.getInstance().getScheduler().start();
|
||||
* </pre> |
||||
* |
||||
* |
||||
* <p> |
||||
* Several create methods are provided for convenience. All create methods |
||||
* eventually end up calling the create method with all the parameters: |
||||
* </p> |
||||
* |
||||
* <pre> |
||||
* public void createScheduler(String schedulerName, String schedulerInstanceId, ThreadPool threadPool, JobStore jobStore, String rmiRegistryHost, int rmiRegistryPort) |
||||
* </pre> |
||||
* |
||||
* |
||||
* <p> |
||||
* Here is an example of using this method: |
||||
* </p> |
||||
* * |
||||
* * <pre>// create the thread pool SimpleThreadPool threadPool = new SimpleThreadPool(maxThreads, Thread.NORM_PRIORITY); threadPool.initialize(); * // create the job store JobStore jobStore = new RAMJobStore(); jobStore.initialize();
|
||||
* |
||||
* DirectSchedulerFactory.getInstance().createScheduler("My Quartz Scheduler", "My Instance", threadPool, jobStore, "localhost", 1099); * // don't forget to start the scheduler: DirectSchedulerFactory.getInstance().getScheduler("My Quartz Scheduler", "My Instance").start();
|
||||
* </pre> |
||||
* |
||||
* |
||||
* <p> |
||||
* You can also use a JDBCJobStore instead of the RAMJobStore: |
||||
* </p> |
||||
* |
||||
* <pre> |
||||
* DBConnectionManager.getInstance().addConnectionProvider("someDatasource", new JNDIConnectionProvider("someDatasourceJNDIName")); |
||||
* |
||||
* JDBCJobStore jdbcJobStore = new JDBCJobStore(); jdbcJobStore.setDataSource("someDatasource"); jdbcJobStore.setPostgresStyleBlobs(true); jdbcJobStore.setTablePrefix("QRTZ_"); jdbcJobStore.setInstanceId("My Instance"); jdbcJobStore.initialize(); |
||||
* </pre> |
||||
* |
||||
* @author Mohammad Rezaei |
||||
* @author James House |
||||
* |
||||
* @see JobStore |
||||
* @see ThreadPool |
||||
*/ |
||||
public class DirectSchedulerFactory implements SchedulerFactory { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
public static final String DEFAULT_INSTANCE_ID = "SIMPLE_NON_CLUSTERED"; |
||||
|
||||
public static final String DEFAULT_SCHEDULER_NAME = "SimpleQuartzScheduler"; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private boolean initialized = false; |
||||
|
||||
private static DirectSchedulerFactory instance = new DirectSchedulerFactory(); |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
/** |
||||
* Constructor |
||||
*/ |
||||
protected DirectSchedulerFactory() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static DirectSchedulerFactory getInstance() { |
||||
return instance; |
||||
} |
||||
|
||||
/** |
||||
* Creates an in memory job store (<code>{@link RAMJobStore}</code>) |
||||
* The thread priority is set to Thread.NORM_PRIORITY |
||||
* |
||||
* @param maxThreads |
||||
* The number of threads in the thread pool |
||||
* @throws SchedulerException |
||||
* if initialization failed. |
||||
*/ |
||||
public void createVolatileScheduler(int maxThreads) |
||||
throws SchedulerException { |
||||
SimpleThreadPool threadPool = new SimpleThreadPool(maxThreads, |
||||
Thread.NORM_PRIORITY); |
||||
threadPool.initialize(); |
||||
JobStore jobStore = new RAMJobStore(); |
||||
this.createScheduler(threadPool, jobStore); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @deprecated see correctly spelled method. |
||||
* @see #createVolatileScheduler(int) |
||||
*/ |
||||
public void createVolatileSchduler(int maxThreads) |
||||
throws SchedulerException { |
||||
createVolatileScheduler(maxThreads); |
||||
} |
||||
|
||||
/** |
||||
* Creates a proxy to a remote scheduler. This scheduler can be retrieved |
||||
* via {@link DirectSchedulerFactory#getScheduler()} |
||||
* |
||||
* @param rmiHost |
||||
* The hostname for remote scheduler |
||||
* @param rmiPort |
||||
* Port for the remote scheduler. The default RMI port is 1099. |
||||
* @throws SchedulerException |
||||
* if the remote scheduler could not be reached. |
||||
*/ |
||||
public void createRemoteScheduler(String rmiHost, int rmiPort) |
||||
throws SchedulerException { |
||||
createRemoteScheduler(DEFAULT_SCHEDULER_NAME, DEFAULT_INSTANCE_ID, |
||||
rmiHost, rmiPort); |
||||
initialized = true; |
||||
} |
||||
|
||||
/** |
||||
* Same as |
||||
* {@link DirectSchedulerFactory#createRemoteScheduler(String rmiHost, int rmiPort)}, |
||||
* with the addition of specifying the scheduler name and instance ID. This |
||||
* scheduler can only be retrieved via |
||||
* {@link DirectSchedulerFactory#getScheduler(String)} |
||||
* |
||||
* @param schedulerName |
||||
* The name for the scheduler. |
||||
* @param schedulerInstanceId |
||||
* The instance ID for the scheduler. |
||||
* @param rmiHost |
||||
* The hostname for remote scheduler |
||||
* @param rmiPort |
||||
* Port for the remote scheduler. The default RMI port is 1099. |
||||
* @throws SchedulerException |
||||
* if the remote scheduler could not be reached. |
||||
*/ |
||||
public void createRemoteScheduler(String schedulerName, |
||||
String schedulerInstanceId, String rmiHost, int rmiPort) |
||||
throws SchedulerException { |
||||
createRemoteScheduler(schedulerName, |
||||
schedulerInstanceId, null, rmiHost, rmiPort); |
||||
} |
||||
|
||||
/** |
||||
* Same as |
||||
* {@link DirectSchedulerFactory#createRemoteScheduler(String rmiHost, int rmiPort)}, |
||||
* with the addition of specifying the scheduler name, instance ID, and rmi |
||||
* bind name. This scheduler can only be retrieved via |
||||
* {@link DirectSchedulerFactory#getScheduler(String)} |
||||
* |
||||
* @param schedulerName |
||||
* The name for the scheduler. |
||||
* @param schedulerInstanceId |
||||
* The instance ID for the scheduler. |
||||
* @param rmiBindName |
||||
* The name of the remote scheduler in the RMI repository. If null |
||||
* defaults to the generated unique identifier. |
||||
* @param rmiHost |
||||
* The hostname for remote scheduler |
||||
* @param rmiPort |
||||
* Port for the remote scheduler. The default RMI port is 1099. |
||||
* @throws SchedulerException |
||||
* if the remote scheduler could not be reached. |
||||
*/ |
||||
public void createRemoteScheduler(String schedulerName, |
||||
String schedulerInstanceId, String rmiBindName, String rmiHost, int rmiPort) |
||||
throws SchedulerException { |
||||
SchedulingContext schedCtxt = new SchedulingContext(); |
||||
schedCtxt.setInstanceId(schedulerInstanceId); |
||||
|
||||
String uid = (rmiBindName != null) ? rmiBindName : |
||||
QuartzSchedulerResources.getUniqueIdentifier( |
||||
schedulerName, schedulerInstanceId); |
||||
|
||||
RemoteScheduler remoteScheduler = new RemoteScheduler(schedCtxt, uid, |
||||
rmiHost, rmiPort); |
||||
|
||||
SchedulerRepository schedRep = SchedulerRepository.getInstance(); |
||||
schedRep.bind(remoteScheduler); |
||||
} |
||||
|
||||
/** |
||||
* Creates a scheduler using the specified thread pool and job store. This |
||||
* scheduler can be retrieved via |
||||
* {@link DirectSchedulerFactory#getScheduler()} |
||||
* |
||||
* @param threadPool |
||||
* The thread pool for executing jobs |
||||
* @param jobStore |
||||
* The type of job store |
||||
* @throws SchedulerException |
||||
* if initialization failed |
||||
*/ |
||||
public void createScheduler(ThreadPool threadPool, JobStore jobStore) |
||||
throws SchedulerException { |
||||
createScheduler(DEFAULT_SCHEDULER_NAME, DEFAULT_INSTANCE_ID, |
||||
threadPool, jobStore); |
||||
initialized = true; |
||||
} |
||||
|
||||
/** |
||||
* Same as |
||||
* {@link DirectSchedulerFactory#createScheduler(ThreadPool threadPool, JobStore jobStore)}, |
||||
* with the addition of specifying the scheduler name and instance ID. This |
||||
* scheduler can only be retrieved via |
||||
* {@link DirectSchedulerFactory#getScheduler(String)} |
||||
* |
||||
* @param schedulerName |
||||
* The name for the scheduler. |
||||
* @param schedulerInstanceId |
||||
* The instance ID for the scheduler. |
||||
* @param threadPool |
||||
* The thread pool for executing jobs |
||||
* @param jobStore |
||||
* The type of job store |
||||
* @throws SchedulerException |
||||
* if initialization failed |
||||
*/ |
||||
public void createScheduler(String schedulerName, |
||||
String schedulerInstanceId, ThreadPool threadPool, JobStore jobStore) |
||||
throws SchedulerException { |
||||
createScheduler(schedulerName, schedulerInstanceId, threadPool, |
||||
jobStore, null, 0, -1, -1); |
||||
} |
||||
|
||||
/** |
||||
* Creates a scheduler using the specified thread pool and job store and |
||||
* binds it to RMI. |
||||
* |
||||
* @param schedulerName |
||||
* The name for the scheduler. |
||||
* @param schedulerInstanceId |
||||
* The instance ID for the scheduler. |
||||
* @param threadPool |
||||
* The thread pool for executing jobs |
||||
* @param jobStore |
||||
* The type of job store |
||||
* @param rmiRegistryHost |
||||
* The hostname to register this scheduler with for RMI. Can use |
||||
* "null" if no RMI is required. |
||||
* @param rmiRegistryPort |
||||
* The port for RMI. Typically 1099. |
||||
* @param idleWaitTime |
||||
* The idle wait time in milliseconds. You can specify "-1" for |
||||
* the default value, which is currently 30000 ms. |
||||
* @throws SchedulerException |
||||
* if initialization failed |
||||
*/ |
||||
public void createScheduler(String schedulerName, |
||||
String schedulerInstanceId, ThreadPool threadPool, |
||||
JobStore jobStore, String rmiRegistryHost, int rmiRegistryPort, |
||||
long idleWaitTime, long dbFailureRetryInterval) |
||||
throws SchedulerException { |
||||
createScheduler(schedulerName, |
||||
schedulerInstanceId, threadPool, |
||||
jobStore, null, // plugins
|
||||
rmiRegistryHost, rmiRegistryPort, |
||||
idleWaitTime, dbFailureRetryInterval); |
||||
} |
||||
|
||||
/** |
||||
* Creates a scheduler using the specified thread pool, job store, and |
||||
* plugins, and binds it to RMI. |
||||
* |
||||
* @param schedulerName |
||||
* The name for the scheduler. |
||||
* @param schedulerInstanceId |
||||
* The instance ID for the scheduler. |
||||
* @param threadPool |
||||
* The thread pool for executing jobs |
||||
* @param jobStore |
||||
* The type of job store |
||||
* @param schedulerPluginMap |
||||
* Map from a <code>String</code> plugin names to |
||||
* <code>{@link com.fr.third.org.quartz.spi.SchedulerPlugin}</code>s. Can use |
||||
* "null" if no plugins are required. |
||||
* @param rmiRegistryHost |
||||
* The hostname to register this scheduler with for RMI. Can use |
||||
* "null" if no RMI is required. |
||||
* @param rmiRegistryPort |
||||
* The port for RMI. Typically 1099. |
||||
* @param idleWaitTime |
||||
* The idle wait time in milliseconds. You can specify "-1" for |
||||
* the default value, which is currently 30000 ms. |
||||
* @throws SchedulerException |
||||
* if initialization failed |
||||
*/ |
||||
public void createScheduler(String schedulerName, |
||||
String schedulerInstanceId, ThreadPool threadPool, |
||||
JobStore jobStore, Map schedulerPluginMap, |
||||
String rmiRegistryHost, int rmiRegistryPort, |
||||
long idleWaitTime, long dbFailureRetryInterval) |
||||
throws SchedulerException { |
||||
// Currently only one run-shell factory is available...
|
||||
JobRunShellFactory jrsf = new StdJobRunShellFactory(); |
||||
|
||||
// Fire everything up
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
SchedulingContext schedCtxt = new SchedulingContext(); |
||||
schedCtxt.setInstanceId(schedulerInstanceId); |
||||
|
||||
QuartzSchedulerResources qrs = new QuartzSchedulerResources(); |
||||
|
||||
qrs.setName(schedulerName); |
||||
qrs.setInstanceId(schedulerInstanceId); |
||||
qrs.setJobRunShellFactory(jrsf); |
||||
qrs.setThreadPool(threadPool); |
||||
qrs.setJobStore(jobStore); |
||||
qrs.setRMIRegistryHost(rmiRegistryHost); |
||||
qrs.setRMIRegistryPort(rmiRegistryPort); |
||||
|
||||
// add plugins
|
||||
if (schedulerPluginMap != null) { |
||||
for (Iterator pluginIter = schedulerPluginMap.values().iterator(); pluginIter.hasNext();) { |
||||
qrs.addSchedulerPlugin((SchedulerPlugin)pluginIter.next()); |
||||
} |
||||
} |
||||
|
||||
QuartzScheduler qs = new QuartzScheduler(qrs, schedCtxt, idleWaitTime, |
||||
dbFailureRetryInterval); |
||||
|
||||
ClassLoadHelper cch = new CascadingClassLoadHelper(); |
||||
cch.initialize(); |
||||
|
||||
jobStore.initialize(cch, qs.getSchedulerSignaler()); |
||||
|
||||
Scheduler scheduler = new StdScheduler(qs, schedCtxt); |
||||
|
||||
// Initialize plugins now that we have a Scheduler instance.
|
||||
if (schedulerPluginMap != null) { |
||||
for (Iterator pluginEntryIter = schedulerPluginMap.entrySet().iterator(); pluginEntryIter.hasNext();) { |
||||
Map.Entry pluginEntry = (Map.Entry)pluginEntryIter.next(); |
||||
|
||||
((SchedulerPlugin)pluginEntry.getValue()).initialize( |
||||
(String)pluginEntry.getKey(), scheduler); |
||||
} |
||||
} |
||||
|
||||
jrsf.initialize(scheduler, schedCtxt); |
||||
|
||||
getLog().info("Quartz scheduler '" + scheduler.getSchedulerName()); |
||||
|
||||
getLog().info("Quartz scheduler version: " + qs.getVersion()); |
||||
|
||||
SchedulerRepository schedRep = SchedulerRepository.getInstance(); |
||||
|
||||
qs.addNoGCObject(schedRep); // prevents the repository from being
|
||||
// garbage collected
|
||||
|
||||
schedRep.bind(scheduler); |
||||
} |
||||
|
||||
/* |
||||
* public void registerSchedulerForRmi(String schedulerName, String |
||||
* schedulerId, String registryHost, int registryPort) throws |
||||
* SchedulerException, RemoteException { QuartzScheduler scheduler = |
||||
* (QuartzScheduler) this.getScheduler(); scheduler.bind(registryHost, |
||||
* registryPort); } |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a handle to the Scheduler produced by this factory. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* you must call createRemoteScheduler or createScheduler methods before |
||||
* calling getScheduler() |
||||
* </p> |
||||
*/ |
||||
public Scheduler getScheduler() throws SchedulerException { |
||||
if (!initialized) { |
||||
throw new SchedulerException( |
||||
"you must call createRemoteScheduler or createScheduler methods before calling getScheduler()"); |
||||
} |
||||
|
||||
return getScheduler(DEFAULT_SCHEDULER_NAME); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a handle to the Scheduler with the given name, if it exists. |
||||
* </p> |
||||
*/ |
||||
public Scheduler getScheduler(String schedName) throws SchedulerException { |
||||
SchedulerRepository schedRep = SchedulerRepository.getInstance(); |
||||
|
||||
return schedRep.lookup(schedName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a handle to all known Schedulers (made by any |
||||
* StdSchedulerFactory instance.). |
||||
* </p> |
||||
*/ |
||||
public Collection getAllSchedulers() throws SchedulerException { |
||||
return SchedulerRepository.getInstance().lookupAll(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,197 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.InputStreamReader; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.SchedulerFactory; |
||||
import com.fr.third.org.quartz.listeners.SchedulerListenerSupport; |
||||
|
||||
/** |
||||
* <p> |
||||
* Instantiates an instance of Quartz Scheduler as a stand-alone program, if |
||||
* the scheduler is configured for RMI it will be made available. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The main() method of this class currently accepts 0 or 1 arguemtns, if there |
||||
* is an argument, and its value is <code>"console"</code>, then the program |
||||
* will print a short message on the console (std-out) and wait for the user to |
||||
* type "exit" - at which time the scheduler will be shutdown. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Future versions of this server should allow additional configuration for |
||||
* responding to scheduler events by allowing the user to specify <code>{@link com.fr.third.org.quartz.JobListener}</code>, |
||||
* <code>{@link com.fr.third.org.quartz.TriggerListener}</code> and <code>{@link com.fr.third.org.quartz.SchedulerListener}</code> |
||||
* classes. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Please read the Quartz FAQ entries about RMI before asking questions in the |
||||
* forums or mail-lists. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class QuartzServer extends SchedulerListenerSupport { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Scheduler sched = null; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
QuartzServer() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public void serve(SchedulerFactory schedFact, boolean console) |
||||
throws Exception { |
||||
sched = schedFact.getScheduler(); |
||||
|
||||
sched.start(); |
||||
|
||||
try { |
||||
Thread.sleep(3000l); |
||||
} catch (Exception ignore) { |
||||
} |
||||
|
||||
System.out.println("\n*** The scheduler successfully started."); |
||||
|
||||
if (console) { |
||||
System.out.println("\n"); |
||||
System.out |
||||
.println("The scheduler will now run until you type \"exit\""); |
||||
System.out |
||||
.println(" If it was configured to export itself via RMI,"); |
||||
System.out.println(" then other process may now use it."); |
||||
|
||||
BufferedReader rdr = new BufferedReader(new InputStreamReader( |
||||
System.in)); |
||||
|
||||
while (true) { |
||||
System.out.print("Type 'exit' to shutdown the server: "); |
||||
if ("exit".equals(rdr.readLine())) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
System.out.println("\n...Shutting down server..."); |
||||
|
||||
sched.shutdown(true); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* SchedulerListener Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> when a serious error has |
||||
* occured within the scheduler - such as repeated failures in the <code>JobStore</code>, |
||||
* or the inability to instantiate a <code>Job</code> instance when its |
||||
* <code>Trigger</code> has fired. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The <code>getErrorCode()</code> method of the given SchedulerException |
||||
* can be used to determine more specific information about the type of |
||||
* error that was encountered. |
||||
* </p> |
||||
*/ |
||||
public void schedulerError(String msg, SchedulerException cause) { |
||||
System.err.println("*** " + msg); |
||||
cause.printStackTrace(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <code>{@link Scheduler}</code> to inform the listener |
||||
* that it has shutdown. |
||||
* </p> |
||||
*/ |
||||
public void schedulerShutdown() { |
||||
System.out.println("\n*** The scheduler is now shutdown."); |
||||
sched = null; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Main Method. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static void main(String[] args) throws Exception { |
||||
|
||||
// //Configure Log4J
|
||||
// org.apache.log4j.PropertyConfigurator.configure(
|
||||
// System.getProperty("log4jConfigFile", "log4j.properties"));
|
||||
|
||||
if (System.getSecurityManager() == null) { |
||||
System.setSecurityManager(new java.rmi.RMISecurityManager()); |
||||
} |
||||
|
||||
try { |
||||
QuartzServer server = new QuartzServer(); |
||||
if (args.length == 0) { |
||||
server.serve( |
||||
new com.fr.third.org.quartz.impl.StdSchedulerFactory(), false); |
||||
} else if (args.length == 1 && args[0].equalsIgnoreCase("console")) { |
||||
server.serve(new com.fr.third.org.quartz.impl.StdSchedulerFactory(), true); |
||||
} else { |
||||
System.err.println("\nUsage: QuartzServer [console]"); |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,104 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Holds references to Scheduler instances - ensuring uniqueness, and |
||||
* preventing garbage collection, and allowing 'global' lookups - all within a |
||||
* ClassLoader space. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerRepository { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private HashMap schedulers; |
||||
|
||||
private static SchedulerRepository inst; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private SchedulerRepository() { |
||||
schedulers = new HashMap(); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static synchronized SchedulerRepository getInstance() { |
||||
if (inst == null) { |
||||
inst = new SchedulerRepository(); |
||||
} |
||||
|
||||
return inst; |
||||
} |
||||
|
||||
public synchronized void bind(Scheduler sched) throws SchedulerException { |
||||
|
||||
if ((Scheduler) schedulers.get(sched.getSchedulerName()) != null) { |
||||
throw new SchedulerException("Scheduler with name '" |
||||
+ sched.getSchedulerName() + "' already exists.", |
||||
SchedulerException.ERR_BAD_CONFIGURATION); |
||||
} |
||||
|
||||
schedulers.put(sched.getSchedulerName(), sched); |
||||
} |
||||
|
||||
public synchronized boolean remove(String schedName) { |
||||
return (schedulers.remove(schedName) != null); |
||||
} |
||||
|
||||
public synchronized Scheduler lookup(String schedName) { |
||||
return (Scheduler) schedulers.get(schedName); |
||||
} |
||||
|
||||
public synchronized Collection lookupAll() { |
||||
return java.util.Collections |
||||
.unmodifiableCollection(schedulers.values()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,100 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl; |
||||
|
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.core.JobRunShell; |
||||
import com.fr.third.org.quartz.core.JobRunShellFactory; |
||||
import com.fr.third.org.quartz.core.SchedulingContext; |
||||
|
||||
/** |
||||
* <p> |
||||
* Responsible for creating the instances of <code>{@link com.fr.third.org.quartz.core.JobRunShell}</code> |
||||
* to be used within the <class>{@link com.fr.third.org.quartz.core.QuartzScheduler} |
||||
* </code> instance. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* This implementation does not re-use any objects, it simply makes a new |
||||
* JobRunShell each time <code>borrowJobRunShell()</code> is called. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class StdJobRunShellFactory implements JobRunShellFactory { |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private Scheduler scheduler; |
||||
|
||||
private SchedulingContext schedCtxt; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Initialize the factory, providing a handle to the <code>Scheduler</code> |
||||
* that should be made available within the <code>JobRunShell</code> and |
||||
* the <code>JobExecutionCOntext</code> s within it, and a handle to the |
||||
* <code>SchedulingContext</code> that the shell will use in its own |
||||
* operations with the <code>JobStore</code>. |
||||
* </p> |
||||
*/ |
||||
public void initialize(Scheduler scheduler, SchedulingContext schedCtxt) { |
||||
this.scheduler = scheduler; |
||||
this.schedCtxt = schedCtxt; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <class>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread} |
||||
* </code> to obtain instances of <code> |
||||
* {@link com.fr.third.org.quartz.core.JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
public JobRunShell borrowJobRunShell() throws SchedulerException { |
||||
return new JobRunShell(this, scheduler, schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Called by the <class>{@link com.fr.third.org.quartz.core.QuartzSchedulerThread} |
||||
* </code> to return instances of <code> |
||||
* {@link com.fr.third.org.quartz.core.JobRunShell}</code>. |
||||
* </p> |
||||
*/ |
||||
public void returnJobRunShell(JobRunShell jobRunShell) { |
||||
jobRunShell.passivate(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,844 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
import com.fr.third.org.quartz.JobDataMap; |
||||
import com.fr.third.org.quartz.JobDetail; |
||||
import com.fr.third.org.quartz.JobListener; |
||||
import com.fr.third.org.quartz.Scheduler; |
||||
import com.fr.third.org.quartz.SchedulerContext; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.SchedulerListener; |
||||
import com.fr.third.org.quartz.SchedulerMetaData; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
import com.fr.third.org.quartz.TriggerListener; |
||||
import com.fr.third.org.quartz.UnableToInterruptJobException; |
||||
import com.fr.third.org.quartz.core.QuartzScheduler; |
||||
import com.fr.third.org.quartz.core.SchedulingContext; |
||||
import com.fr.third.org.quartz.spi.JobFactory; |
||||
|
||||
/** |
||||
* <p> |
||||
* An implementation of the <code>Scheduler</code> interface that directly |
||||
* proxies all method calls to the equivalent call on a given <code>QuartzScheduler</code> |
||||
* instance. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Scheduler |
||||
* @see com.fr.third.org.quartz.core.QuartzScheduler |
||||
* @see com.fr.third.org.quartz.core.SchedulingContext |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class StdScheduler implements Scheduler { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private QuartzScheduler sched; |
||||
|
||||
private SchedulingContext schedCtxt; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Construct a <code>StdScheduler</code> instance to proxy the given |
||||
* <code>QuartzScheduler</code> instance, and with the given <code>SchedulingContext</code>. |
||||
* </p> |
||||
*/ |
||||
public StdScheduler(QuartzScheduler sched, SchedulingContext schedCtxt) { |
||||
this.sched = sched; |
||||
this.schedCtxt = schedCtxt; |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the name of the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public String getSchedulerName() { |
||||
return sched.getSchedulerName(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the instance Id of the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public String getSchedulerInstanceId() { |
||||
return sched.getSchedulerInstanceId(); |
||||
} |
||||
|
||||
public SchedulerMetaData getMetaData() { |
||||
return new SchedulerMetaData(getSchedulerName(), |
||||
getSchedulerInstanceId(), getClass(), false, isStarted(), |
||||
isInStandbyMode(), isShutdown(), sched.runningSince(), |
||||
sched.numJobsExecuted(), sched.getJobStoreClass(), |
||||
sched.supportsPersistence(), sched.getThreadPoolClass(), |
||||
sched.getThreadPoolSize(), sched.getVersion()); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns the <code>SchedulerContext</code> of the <code>Scheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public SchedulerContext getContext() throws SchedulerException { |
||||
return sched.getSchedulerContext(); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Schedululer State Management Methods
|
||||
///
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void start() throws SchedulerException { |
||||
sched.start(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void startDelayed(int seconds) throws SchedulerException { |
||||
sched.startDelayed(seconds); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
* |
||||
* @deprecated |
||||
* @see #standby() |
||||
*/ |
||||
public void pause() { |
||||
this.standby(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void standby() { |
||||
sched.standby(); |
||||
} |
||||
|
||||
/** |
||||
* Whether the scheduler has been started. |
||||
* |
||||
* <p> |
||||
* Note: This only reflects whether <code>{@link #start()}</code> has ever |
||||
* been called on this Scheduler, so it will return <code>true</code> even |
||||
* if the <code>Scheduler</code> is currently in standby mode or has been |
||||
* since shutdown. |
||||
* </p> |
||||
* |
||||
* @see #start() |
||||
* @see #isShutdown() |
||||
* @see #isInStandbyMode() |
||||
*/ |
||||
public boolean isStarted() { |
||||
return (sched.runningSince() != null); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean isInStandbyMode() { |
||||
return sched.isInStandbyMode(); |
||||
} |
||||
|
||||
/** |
||||
* @deprecated |
||||
*/ |
||||
public boolean isPaused() { |
||||
return isInStandbyMode(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void shutdown() { |
||||
sched.shutdown(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void shutdown(boolean waitForJobsToComplete) { |
||||
sched.shutdown(waitForJobsToComplete); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean isShutdown() { |
||||
return sched.isShutdown(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public List getCurrentlyExecutingJobs() { |
||||
return sched.getCurrentlyExecutingJobs(); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Scheduling-related Methods
|
||||
///
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Date scheduleJob(JobDetail jobDetail, Trigger trigger) |
||||
throws SchedulerException { |
||||
return sched.scheduleJob(schedCtxt, jobDetail, trigger); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Date scheduleJob(Trigger trigger) throws SchedulerException { |
||||
return sched.scheduleJob(schedCtxt, trigger); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void addJob(JobDetail jobDetail, boolean replace) |
||||
throws SchedulerException { |
||||
sched.addJob(schedCtxt, jobDetail, replace); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public boolean deleteJob(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
return sched.deleteJob(schedCtxt, jobName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public boolean unscheduleJob(String triggerName, String groupName) |
||||
throws SchedulerException { |
||||
return sched.unscheduleJob(schedCtxt, triggerName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Date rescheduleJob(String triggerName, |
||||
String groupName, Trigger newTrigger) throws SchedulerException { |
||||
return sched.rescheduleJob(schedCtxt, triggerName, groupName, newTrigger); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void triggerJob(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
triggerJob(jobName, groupName, null); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void triggerJob(String jobName, String groupName, JobDataMap data) |
||||
throws SchedulerException { |
||||
sched.triggerJob(schedCtxt, jobName, groupName, data); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void triggerJobWithVolatileTrigger(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
triggerJobWithVolatileTrigger(jobName, groupName, null); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void triggerJobWithVolatileTrigger(String jobName, String groupName, JobDataMap data) |
||||
throws SchedulerException { |
||||
sched.triggerJobWithVolatileTrigger(schedCtxt, jobName, groupName, data); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void pauseTrigger(String triggerName, String groupName) |
||||
throws SchedulerException { |
||||
sched.pauseTrigger(schedCtxt, triggerName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void pauseTriggerGroup(String groupName) throws SchedulerException { |
||||
sched.pauseTriggerGroup(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void pauseJob(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
sched.pauseJob(schedCtxt, jobName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* @see com.fr.third.org.quartz.Scheduler#getPausedTriggerGroups() |
||||
*/ |
||||
public Set getPausedTriggerGroups() throws SchedulerException { |
||||
return sched.getPausedTriggerGroups(schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void pauseJobGroup(String groupName) throws SchedulerException { |
||||
sched.pauseJobGroup(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void resumeTrigger(String triggerName, String groupName) |
||||
throws SchedulerException { |
||||
sched.resumeTrigger(schedCtxt, triggerName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void resumeTriggerGroup(String groupName) throws SchedulerException { |
||||
sched.resumeTriggerGroup(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void resumeJob(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
sched.resumeJob(schedCtxt, jobName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void resumeJobGroup(String groupName) throws SchedulerException { |
||||
sched.resumeJobGroup(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void pauseAll() throws SchedulerException { |
||||
sched.pauseAll(schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void resumeAll() throws SchedulerException { |
||||
sched.resumeAll(schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public String[] getJobGroupNames() throws SchedulerException { |
||||
return sched.getJobGroupNames(schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Trigger[] getTriggersOfJob(String jobName, String groupName) |
||||
throws SchedulerException { |
||||
return sched.getTriggersOfJob(schedCtxt, jobName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public String[] getJobNames(String groupName) throws SchedulerException { |
||||
return sched.getJobNames(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public String[] getTriggerGroupNames() throws SchedulerException { |
||||
return sched.getTriggerGroupNames(schedCtxt); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public String[] getTriggerNames(String groupName) throws SchedulerException { |
||||
return sched.getTriggerNames(schedCtxt, groupName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public JobDetail getJobDetail(String jobName, String jobGroup) |
||||
throws SchedulerException { |
||||
return sched.getJobDetail(schedCtxt, jobName, jobGroup); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Trigger getTrigger(String triggerName, String triggerGroup) |
||||
throws SchedulerException { |
||||
return sched.getTrigger(schedCtxt, triggerName, triggerGroup); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public int getTriggerState(String triggerName, String triggerGroup) |
||||
throws SchedulerException { |
||||
return sched.getTriggerState(schedCtxt, triggerName, triggerGroup); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public void addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers) |
||||
throws SchedulerException { |
||||
sched.addCalendar(schedCtxt, calName, calendar, replace, updateTriggers); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public boolean deleteCalendar(String calName) throws SchedulerException { |
||||
return sched.deleteCalendar(schedCtxt, calName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public Calendar getCalendar(String calName) throws SchedulerException { |
||||
return sched.getCalendar(schedCtxt, calName); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>, |
||||
* passing the <code>SchedulingContext</code> associated with this |
||||
* instance. |
||||
* </p> |
||||
*/ |
||||
public String[] getCalendarNames() throws SchedulerException { |
||||
return sched.getCalendarNames(schedCtxt); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Listener-related Methods
|
||||
///
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void addGlobalJobListener(JobListener jobListener) { |
||||
sched.addGlobalJobListener(jobListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void addJobListener(JobListener jobListener) { |
||||
sched.addJobListener(jobListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
* @deprecated Use <code>{@link #removeGlobalJobListener(String)}</code> |
||||
*/ |
||||
public boolean removeGlobalJobListener(JobListener jobListener) { |
||||
return sched.removeGlobalJobListener( |
||||
(jobListener == null) ? null : jobListener.getName()); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean removeGlobalJobListener(String name) { |
||||
return sched.removeGlobalJobListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean removeJobListener(String name) { |
||||
return sched.removeJobListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public List getGlobalJobListeners() { |
||||
return sched.getGlobalJobListeners(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public Set getJobListenerNames() { |
||||
return sched.getJobListenerNames(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public JobListener getGlobalJobListener(String name) { |
||||
return sched.getGlobalJobListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public JobListener getJobListener(String name) { |
||||
return sched.getJobListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void addGlobalTriggerListener(TriggerListener triggerListener) { |
||||
sched.addGlobalTriggerListener(triggerListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void addTriggerListener(TriggerListener triggerListener) { |
||||
sched.addTriggerListener(triggerListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
* |
||||
* @deprecated Use <code>{@link #removeGlobalTriggerListener(String)}</code> |
||||
*/ |
||||
public boolean removeGlobalTriggerListener(TriggerListener triggerListener) { |
||||
return sched.removeGlobalTriggerListener( |
||||
(triggerListener == null) ? null : triggerListener.getName()); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean removeGlobalTriggerListener(String name) { |
||||
return sched.removeGlobalTriggerListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean removeTriggerListener(String name) { |
||||
return sched.removeTriggerListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public List getGlobalTriggerListeners() { |
||||
return sched.getGlobalTriggerListeners(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public Set getTriggerListenerNames() { |
||||
return sched.getTriggerListenerNames(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public TriggerListener getGlobalTriggerListener(String name) { |
||||
return sched.getGlobalTriggerListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public TriggerListener getTriggerListener(String name) { |
||||
return sched.getTriggerListener(name); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public void addSchedulerListener(SchedulerListener schedulerListener) { |
||||
sched.addSchedulerListener(schedulerListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public boolean removeSchedulerListener(SchedulerListener schedulerListener) { |
||||
return sched.removeSchedulerListener(schedulerListener); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Calls the equivalent method on the 'proxied' <code>QuartzScheduler</code>. |
||||
* </p> |
||||
*/ |
||||
public List getSchedulerListeners() { |
||||
return sched.getSchedulerListeners(); |
||||
} |
||||
|
||||
public boolean interrupt(String jobName, String groupName) throws UnableToInterruptJobException { |
||||
return sched.interrupt(schedCtxt, jobName, groupName); |
||||
} |
||||
|
||||
/** |
||||
* @see com.fr.third.org.quartz.Scheduler#setJobFactory(com.fr.third.org.quartz.spi.JobFactory) |
||||
*/ |
||||
public void setJobFactory(JobFactory factory) throws SchedulerException { |
||||
sched.setJobFactory(factory); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,294 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
* and Juergen Donnerstag (c) 2002, EDS 2002 |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.Iterator; |
||||
import java.util.TimeZone; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
|
||||
/** |
||||
* <p> |
||||
* This implementation of the Calendar excludes a set of days of the year. You |
||||
* may use it to exclude bank holidays which are on the same date every year. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar |
||||
* @see com.fr.third.org.quartz.impl.calendar.BaseCalendar |
||||
* |
||||
* @author Juergen Donnerstag |
||||
*/ |
||||
public class AnnualCalendar extends BaseCalendar implements Calendar, |
||||
Serializable { |
||||
|
||||
static final long serialVersionUID = 7346867105876610961L; |
||||
|
||||
private ArrayList excludeDays = new ArrayList(); |
||||
|
||||
// true, if excludeDays is sorted
|
||||
private boolean dataSorted = false; |
||||
|
||||
public AnnualCalendar() { |
||||
} |
||||
|
||||
public AnnualCalendar(Calendar baseCalendar) { |
||||
super(baseCalendar); |
||||
} |
||||
|
||||
public AnnualCalendar(TimeZone timeZone) { |
||||
super(timeZone); |
||||
} |
||||
|
||||
public AnnualCalendar(Calendar baseCalendar, TimeZone timeZone) { |
||||
super(baseCalendar, timeZone); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the array which defines the exclude-value of each day of month |
||||
* </p> |
||||
*/ |
||||
public ArrayList getDaysExcluded() { |
||||
return excludeDays; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return true, if day is defined to be exluded. |
||||
* </p> |
||||
*/ |
||||
public boolean isDayExcluded(java.util.Calendar day) { |
||||
|
||||
if (day == null) { |
||||
throw new IllegalArgumentException( |
||||
"Parameter day must not be null"); |
||||
} |
||||
|
||||
// Check baseCalendar first
|
||||
if (! super.isTimeIncluded(day.getTime().getTime())) { |
||||
return true; |
||||
} |
||||
|
||||
int dmonth = day.get(java.util.Calendar.MONTH); |
||||
int dday = day.get(java.util.Calendar.DAY_OF_MONTH); |
||||
|
||||
if (dataSorted == false) { |
||||
Collections.sort(excludeDays, new CalendarComparator()); |
||||
dataSorted = true; |
||||
} |
||||
|
||||
Iterator iter = excludeDays.iterator(); |
||||
while (iter.hasNext()) { |
||||
java.util.Calendar cl = (java.util.Calendar) iter.next(); |
||||
|
||||
// remember, the list is sorted
|
||||
if (dmonth < cl.get(java.util.Calendar.MONTH)) { |
||||
return false; |
||||
} |
||||
|
||||
if (dday != cl.get(java.util.Calendar.DAY_OF_MONTH)) { |
||||
continue; |
||||
} |
||||
|
||||
if (dmonth != cl.get(java.util.Calendar.MONTH)) { |
||||
continue; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine the list of days excluded. The ArrayList |
||||
* should contain <code>java.util.Calendar</code> objects. |
||||
* </p> |
||||
*/ |
||||
public void setDaysExcluded(ArrayList days) { |
||||
if (days == null) { |
||||
excludeDays = new ArrayList(); |
||||
} else { |
||||
excludeDays = days; |
||||
} |
||||
|
||||
dataSorted = false; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine a certain day to be excluded (true) or included (false). |
||||
* </p> |
||||
*/ |
||||
public void setDayExcluded(java.util.Calendar day, boolean exclude) { |
||||
if (exclude) { |
||||
if (isDayExcluded(day)) { |
||||
return; |
||||
} |
||||
|
||||
excludeDays.add(day); |
||||
dataSorted = false; |
||||
} else { |
||||
if (!isDayExcluded(day)) { |
||||
return; |
||||
} |
||||
|
||||
removeExcludedDay(day, true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the given day from the list of excluded days |
||||
* |
||||
* @param day |
||||
* @return |
||||
*/ |
||||
public void removeExcludedDay(java.util.Calendar day) { |
||||
removeExcludedDay(day, false); |
||||
} |
||||
|
||||
private void removeExcludedDay(java.util.Calendar day, boolean isChecked) { |
||||
if (! isChecked && |
||||
! isDayExcluded(day)) { |
||||
return; |
||||
} |
||||
|
||||
// Fast way, see if exact day object was already in list
|
||||
if (this.excludeDays.remove(day)) { |
||||
return; |
||||
} |
||||
|
||||
int dmonth = day.get(java.util.Calendar.MONTH); |
||||
int dday = day.get(java.util.Calendar.DAY_OF_MONTH); |
||||
|
||||
// Since there is no guarantee that the given day is in the arraylist with the exact same year
|
||||
// search for the object based on month and day of month in the list and remove it
|
||||
Iterator iter = excludeDays.iterator(); |
||||
while (iter.hasNext()) { |
||||
java.util.Calendar cl = (java.util.Calendar) iter.next(); |
||||
|
||||
if (dmonth != cl.get(java.util.Calendar.MONTH)) { |
||||
continue; |
||||
} |
||||
|
||||
if (dday != cl.get(java.util.Calendar.DAY_OF_MONTH)) { |
||||
continue; |
||||
} |
||||
|
||||
day = cl; |
||||
break; |
||||
} |
||||
|
||||
this.excludeDays.remove(day); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* <p> |
||||
* Determine whether the given time (in milliseconds) is 'included' by the |
||||
* Calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public boolean isTimeIncluded(long timeStamp) { |
||||
// Test the base calendar first. Only if the base calendar not already
|
||||
// excludes the time/date, continue evaluating this calendar instance.
|
||||
if (super.isTimeIncluded(timeStamp) == false) { return false; } |
||||
|
||||
java.util.Calendar day = createJavaCalendar(timeStamp); |
||||
|
||||
return !(isDayExcluded(day)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. Return the original value if timeStamp is |
||||
* included. Return 0 if all days are excluded. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public long getNextIncludedTime(long timeStamp) { |
||||
// Call base calendar implementation first
|
||||
long baseTime = super.getNextIncludedTime(timeStamp); |
||||
if ((baseTime > 0) && (baseTime > timeStamp)) { |
||||
timeStamp = baseTime; |
||||
} |
||||
|
||||
// Get timestamp for 00:00:00
|
||||
java.util.Calendar day = getStartOfDayJavaCalendar(timeStamp); |
||||
if (isDayExcluded(day) == false) { |
||||
return timeStamp; // return the original value
|
||||
} |
||||
|
||||
while (isDayExcluded(day) == true) { |
||||
day.add(java.util.Calendar.DATE, 1); |
||||
} |
||||
|
||||
return day.getTime().getTime(); |
||||
} |
||||
} |
||||
|
||||
class CalendarComparator implements Comparator { |
||||
public CalendarComparator() { |
||||
} |
||||
|
||||
/** |
||||
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) |
||||
*/ |
||||
public int compare(Object arg0, Object arg1) { |
||||
java.util.Calendar c1 = (java.util.Calendar) arg0; |
||||
java.util.Calendar c2 = (java.util.Calendar) arg1; |
||||
|
||||
int month1 = c1.get(java.util.Calendar.MONTH); |
||||
int month2 = c2.get(java.util.Calendar.MONTH); |
||||
|
||||
int day1 = c1.get(java.util.Calendar.DAY_OF_MONTH); |
||||
int day2 = c2.get(java.util.Calendar.DAY_OF_MONTH); |
||||
|
||||
if (month1 < month2) { |
||||
return -1; |
||||
} |
||||
if (month1 > month2) { |
||||
return 1; |
||||
} |
||||
if (day1 < day2) { |
||||
return -1; |
||||
} |
||||
if (day1 > day2) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
} |
@ -0,0 +1,283 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
* and Juergen Donnerstag (c) 2002, EDS 2002 |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import java.util.TimeZone; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
|
||||
/** |
||||
* <p> |
||||
* This implementation of the Calendar may be used (you don't have to) as a |
||||
* base class for more sophisticated one's. It merely implements the base |
||||
* functionality required by each Calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Regarded as base functionality is the treatment of base calendars. Base |
||||
* calendar allow you to chain (stack) as much calendars as you may need. For |
||||
* example to exclude weekends you may use WeeklyCalendar. In order to exclude |
||||
* holidays as well you may define a WeeklyCalendar instance to be the base |
||||
* calendar for HolidayCalendar instance. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar |
||||
* |
||||
* @author Juergen Donnerstag |
||||
* @author James House |
||||
*/ |
||||
public class BaseCalendar implements Calendar, Serializable { |
||||
|
||||
static final long serialVersionUID = 3106623404629760239L; |
||||
|
||||
// <p>A optional base calendar.</p>
|
||||
private Calendar baseCalendar; |
||||
|
||||
private String description; |
||||
|
||||
private TimeZone timeZone; |
||||
|
||||
public BaseCalendar() { |
||||
} |
||||
|
||||
public BaseCalendar(Calendar baseCalendar) { |
||||
setBaseCalendar(baseCalendar); |
||||
} |
||||
|
||||
/** |
||||
* @param timeZone The time zone to use for this Calendar, <code>null</code> |
||||
* if <code>{@link TimeZone#getDefault()}</code> should be used |
||||
*/ |
||||
public BaseCalendar(TimeZone timeZone) { |
||||
setTimeZone(timeZone); |
||||
} |
||||
|
||||
/** |
||||
* @param timeZone The time zone to use for this Calendar, <code>null</code> |
||||
* if <code>{@link TimeZone#getDefault()}</code> should be used |
||||
*/ |
||||
public BaseCalendar(Calendar baseCalendar, TimeZone timeZone) { |
||||
setBaseCalendar(baseCalendar); |
||||
setTimeZone(timeZone); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set a new base calendar or remove the existing one |
||||
* </p> |
||||
*/ |
||||
public void setBaseCalendar(Calendar baseCalendar) { |
||||
this.baseCalendar = baseCalendar; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the base calendar. Will be null, if not set. |
||||
* </p> |
||||
*/ |
||||
public Calendar getBaseCalendar() { |
||||
return this.baseCalendar; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return the description given to the <code>Calendar</code> instance by |
||||
* its creator (if any). |
||||
* </p> |
||||
* |
||||
* @return null if no description was set. |
||||
*/ |
||||
public String getDescription() { |
||||
return description; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Set a description for the <code>Calendar</code> instance - may be |
||||
* useful for remembering/displaying the purpose of the calendar, though |
||||
* the description has no meaning to Quartz. |
||||
* </p> |
||||
*/ |
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
/** |
||||
* Returns the time zone for which this <code>Calendar</code> will be |
||||
* resolved. |
||||
* |
||||
* @return This Calendar's timezone, <code>null</code> if Calendar should |
||||
* use the <code>{@link TimeZone#getDefault()}</code> |
||||
*/ |
||||
public TimeZone getTimeZone() { |
||||
return timeZone; |
||||
} |
||||
|
||||
/** |
||||
* Sets the time zone for which this <code>Calendar</code> will be resolved. |
||||
* |
||||
* @param timeZone The time zone to use for this Calendar, <code>null</code> |
||||
* if <code>{@link TimeZone#getDefault()}</code> should be used |
||||
*/ |
||||
public void setTimeZone(TimeZone timeZone) { |
||||
this.timeZone = timeZone; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Check if date/time represented by timeStamp is included. If included |
||||
* return true. The implementation of BaseCalendar simply calls the base |
||||
* calendars isTimeIncluded() method if base calendar is set. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar#isTimeIncluded(long) |
||||
*/ |
||||
public boolean isTimeIncluded(long timeStamp) { |
||||
|
||||
if (timeStamp <= 0) { |
||||
throw new IllegalArgumentException( |
||||
"timeStamp must be greater 0"); |
||||
} |
||||
|
||||
if (baseCalendar != null) { |
||||
if (baseCalendar.isTimeIncluded(timeStamp) == false) { return false; } |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. Return the original value if timeStamp is |
||||
* included. Return 0 if all days are excluded. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar#getNextIncludedTime(long) |
||||
*/ |
||||
public long getNextIncludedTime(long timeStamp) { |
||||
|
||||
if (timeStamp <= 0) { |
||||
throw new IllegalArgumentException( |
||||
"timeStamp must be greater 0"); |
||||
} |
||||
|
||||
if (baseCalendar != null) { |
||||
return baseCalendar.getNextIncludedTime(timeStamp); |
||||
} |
||||
|
||||
return timeStamp; |
||||
} |
||||
|
||||
/** |
||||
* Utility method. Return the date of excludeDate. The time fraction will |
||||
* be reset to 00.00:00. |
||||
* |
||||
* @deprecated Always uses the default time zone. |
||||
*/ |
||||
public static Date buildHoliday(Date excludedDate) { |
||||
return new BaseCalendar().getStartOfDayJavaCalendar(excludedDate.getTime()).getTime(); |
||||
} |
||||
|
||||
/** |
||||
* Utility method. Return just the date of timeStamp. The time fraction |
||||
* will be reset to 00.00:00. |
||||
* |
||||
* @deprecated Always uses the default time zone. |
||||
*/ |
||||
public static long buildHoliday(long timeStamp) { |
||||
return new BaseCalendar().getStartOfDayJavaCalendar(timeStamp).getTime().getTime(); |
||||
} |
||||
|
||||
/** |
||||
* Utility method. Return a java.util.Calendar for timeStamp. |
||||
* |
||||
* @deprecated Always uses the default time zone. |
||||
*/ |
||||
public static java.util.Calendar getJavaCalendar(long timeStamp) { |
||||
return new BaseCalendar().createJavaCalendar(timeStamp); |
||||
} |
||||
|
||||
/** |
||||
* Build a <code>{@link java.util.Calendar}</code> for the given timeStamp. |
||||
* The new Calendar will use the <code>BaseCalendar</code> time zone if it |
||||
* is not <code>null</code>. |
||||
*/ |
||||
protected java.util.Calendar createJavaCalendar(long timeStamp) { |
||||
java.util.Calendar calendar = createJavaCalendar(); |
||||
calendar.setTime(new Date(timeStamp)); |
||||
return calendar; |
||||
} |
||||
|
||||
/** |
||||
* Build a <code>{@link java.util.Calendar}</code> with the current time. |
||||
* The new Calendar will use the <code>BaseCalendar</code> time zone if |
||||
* it is not <code>null</code>. |
||||
*/ |
||||
protected java.util.Calendar createJavaCalendar() { |
||||
return |
||||
(getTimeZone() == null) ? |
||||
java.util.Calendar.getInstance() : |
||||
java.util.Calendar.getInstance(getTimeZone()); |
||||
} |
||||
|
||||
/** |
||||
* Returns the start of the given day as a <code>{@link java.util.Calendar}</code>. |
||||
* This calculation will take the <code>BaseCalendar</code> |
||||
* time zone into account if it is not <code>null</code>. |
||||
* |
||||
* @param timeInMillis A time containing the desired date for the |
||||
* start-of-day time |
||||
* @return A <code>{@link java.util.Calendar}</code> set to the start of |
||||
* the given day. |
||||
*/ |
||||
protected java.util.Calendar getStartOfDayJavaCalendar(long timeInMillis) { |
||||
java.util.Calendar startOfDay = createJavaCalendar(timeInMillis); |
||||
startOfDay.set(java.util.Calendar.HOUR_OF_DAY, 0); |
||||
startOfDay.set(java.util.Calendar.MINUTE, 0); |
||||
startOfDay.set(java.util.Calendar.SECOND, 0); |
||||
startOfDay.set(java.util.Calendar.MILLISECOND, 0); |
||||
return startOfDay; |
||||
} |
||||
|
||||
/** |
||||
* Returns the end of the given day <code>{@link java.util.Calendar}</code>. |
||||
* This calculation will take the <code>BaseCalendar</code> |
||||
* time zone into account if it is not <code>null</code>. |
||||
* |
||||
* @param timeInMillis a time containing the desired date for the |
||||
* end-of-day time. |
||||
* @return A <code>{@link java.util.Calendar}</code> set to the end of |
||||
* the given day. |
||||
*/ |
||||
protected java.util.Calendar getEndOfDayJavaCalendar(long timeInMillis) { |
||||
java.util.Calendar endOfDay = createJavaCalendar(timeInMillis); |
||||
endOfDay.set(java.util.Calendar.HOUR_OF_DAY, 23); |
||||
endOfDay.set(java.util.Calendar.MINUTE, 59); |
||||
endOfDay.set(java.util.Calendar.SECOND, 59); |
||||
endOfDay.set(java.util.Calendar.MILLISECOND, 999); |
||||
return endOfDay; |
||||
} |
||||
} |
@ -0,0 +1,262 @@
|
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.text.ParseException; |
||||
import java.util.Date; |
||||
import java.util.TimeZone; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
import com.fr.third.org.quartz.CronExpression; |
||||
|
||||
/** |
||||
* This implementation of the Calendar excludes the set of times expressed by a |
||||
* given {@link com.fr.third.org.quartz.CronExpression CronExpression}. For example, you |
||||
* could use this calendar to exclude all but business hours (8AM - 5PM) every |
||||
* day using the expression "* * 0-7,18-23 ? * *". |
||||
* <P> |
||||
* It is important to remember that the cron expression here describes a set of |
||||
* times to be <I>excluded</I> from firing. Whereas the cron expression in |
||||
* {@link com.fr.third.org.quartz.CronTrigger CronTrigger} describes a set of times that can |
||||
* be <I>included</I> for firing. Thus, if a <CODE>CronTrigger</CODE> has a |
||||
* given cron expression and is associated with a <CODE>CronCalendar</CODE> with |
||||
* the <I>same</I> expression, the calendar will exclude all the times the |
||||
* trigger includes, and they will cancel each other out. |
||||
* |
||||
* @author Aaron Craven |
||||
*/ |
||||
public class CronCalendar extends BaseCalendar { |
||||
static final long serialVersionUID = -8172103999750856831L; |
||||
|
||||
/** @deprecated The use of <code>name</code> is no longer supported. */ |
||||
private String name; |
||||
|
||||
CronExpression cronExpression; |
||||
|
||||
/** |
||||
* Create a <CODE>CronCalendar</CODE> with the given cron expression and no |
||||
* <CODE>baseCalendar</CODE>. |
||||
* |
||||
* @param expression a String representation of the desired cron expression |
||||
*/ |
||||
public CronCalendar(String expression) |
||||
throws ParseException { |
||||
this(null, expression, null); |
||||
} |
||||
|
||||
/** |
||||
* Create a <CODE>CronCalendar</CODE> with the given cron expression and |
||||
* <CODE>baseCalendar</CODE>. |
||||
* |
||||
* @param baseCalendar the base calendar for this calendar instance – |
||||
* see {@link BaseCalendar} for more information on base |
||||
* calendar functionality |
||||
* @param expression a String representation of the desired cron expression |
||||
*/ |
||||
public CronCalendar(Calendar baseCalendar, |
||||
String expression) throws ParseException { |
||||
this(baseCalendar, expression, null); |
||||
} |
||||
|
||||
/** |
||||
* Create a <CODE>CronCalendar</CODE> with the given cron exprssion, |
||||
* <CODE>baseCalendar</CODE>, and <code>TimeZone</code>. |
||||
* |
||||
* @param baseCalendar the base calendar for this calendar instance – |
||||
* see {@link BaseCalendar} for more information on base |
||||
* calendar functionality |
||||
* @param expression a String representation of the desired cron expression |
||||
* @param timeZone |
||||
* Specifies for which time zone the <code>expression</code> |
||||
* should be interpreted, i.e. the expression 0 0 10 * * ?, is |
||||
* resolved to 10:00 am in this time zone. If |
||||
* <code>timeZone</code> is <code>null</code> then |
||||
* <code>TimeZone.getDefault()</code> will be used. |
||||
*/ |
||||
public CronCalendar(Calendar baseCalendar, |
||||
String expression, TimeZone timeZone) throws ParseException { |
||||
super(baseCalendar); |
||||
this.cronExpression = new CronExpression(expression); |
||||
this.cronExpression.setTimeZone(timeZone); |
||||
} |
||||
|
||||
/** |
||||
* @deprecated The use of <code>name</code> is no longer supported. |
||||
* |
||||
* @see #CronCalendar(String) |
||||
*/ |
||||
public CronCalendar(String name, String expression) |
||||
throws ParseException { |
||||
this(expression); |
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* @deprecated The use of <code>name</code> is no longer supported. |
||||
* |
||||
* @see #CronCalendar(Calendar, String) |
||||
*/ |
||||
public CronCalendar(String name, Calendar baseCalendar, |
||||
String expression) throws ParseException { |
||||
this(baseCalendar, expression); |
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* @deprecated The use of <code>name</code> is no longer supported. |
||||
* |
||||
* @see #CronCalendar(Calendar, String, TimeZone) |
||||
*/ |
||||
public CronCalendar(String name, Calendar baseCalendar, |
||||
String expression, TimeZone timeZone) throws ParseException { |
||||
this(baseCalendar, expression, timeZone); |
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* Returns the time zone for which the <code>CronExpression</code> of |
||||
* this <code>CronCalendar</code> will be resolved. |
||||
* <p> |
||||
* Overrides <code>{@link BaseCalendar#getTimeZone()}</code> to |
||||
* defer to its <code>CronExpression</code>. |
||||
* </p> |
||||
*/ |
||||
public TimeZone getTimeZone() { |
||||
return cronExpression.getTimeZone(); |
||||
} |
||||
|
||||
/** |
||||
* Sets the time zone for which the <code>CronExpression</code> of this |
||||
* <code>CronCalendar</code> will be resolved. If <code>timeZone</code> |
||||
* is <code>null</code> then <code>TimeZone.getDefault()</code> will be |
||||
* used. |
||||
* <p> |
||||
* Overrides <code>{@link BaseCalendar#setTimeZone(TimeZone)}</code> to |
||||
* defer to its <code>CronExpression</code>. |
||||
* </p> |
||||
*/ |
||||
public void setTimeZone(TimeZone timeZone) { |
||||
cronExpression.setTimeZone(timeZone); |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of the <CODE>CronCalendar</CODE> |
||||
* |
||||
* @return the name of the <CODE>CronCalendar</CODE> |
||||
* |
||||
* @deprecated The use of <code>name</code> is no longer supported. |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Determines whether the given time (in milliseconds) is 'included' by the |
||||
* <CODE>BaseCalendar</CODE> |
||||
* |
||||
* @param timeInMillis the date/time to test |
||||
* @return a boolean indicating whether the specified time is 'included' by |
||||
* the <CODE>CronCalendar</CODE> |
||||
*/ |
||||
public boolean isTimeIncluded(long timeInMillis) { |
||||
if ((getBaseCalendar() != null) && |
||||
(getBaseCalendar().isTimeIncluded(timeInMillis) == false)) { |
||||
return false; |
||||
} |
||||
|
||||
return (!(cronExpression.isSatisfiedBy(new Date(timeInMillis)))); |
||||
} |
||||
|
||||
/** |
||||
* Determines the next time included by the <CODE>CronCalendar</CODE> |
||||
* after the specified time. |
||||
* |
||||
* @param timeInMillis the initial date/time after which to find an |
||||
* included time |
||||
* @return the time in milliseconds representing the next time included |
||||
* after the specified time. |
||||
*/ |
||||
public long getNextIncludedTime(long timeInMillis) { |
||||
long nextIncludedTime = timeInMillis + 1; //plus on millisecond
|
||||
|
||||
while (!isTimeIncluded(nextIncludedTime)) { |
||||
|
||||
//If the time is in a range excluded by this calendar, we can
|
||||
// move to the end of the excluded time range and continue testing
|
||||
// from there. Otherwise, if nextIncludedTime is excluded by the
|
||||
// baseCalendar, ask it the next time it includes and begin testing
|
||||
// from there. Failing this, add one millisecond and continue
|
||||
// testing.
|
||||
if (cronExpression.isSatisfiedBy(new Date(nextIncludedTime))) { |
||||
nextIncludedTime = cronExpression.getNextInvalidTimeAfter( |
||||
new Date(nextIncludedTime)).getTime(); |
||||
} else if ((getBaseCalendar() != null) && |
||||
(!getBaseCalendar().isTimeIncluded(nextIncludedTime))){ |
||||
nextIncludedTime = |
||||
getBaseCalendar().getNextIncludedTime(nextIncludedTime); |
||||
} else { |
||||
nextIncludedTime++; |
||||
} |
||||
} |
||||
|
||||
return nextIncludedTime; |
||||
} |
||||
|
||||
/** |
||||
* Returns a string representing the properties of the |
||||
* <CODE>CronCalendar</CODE> |
||||
* |
||||
* @return the properteis of the CronCalendar in a String format |
||||
*/ |
||||
public String toString() { |
||||
StringBuffer buffer = new StringBuffer(); |
||||
if (name != null) { |
||||
buffer.append(name).append(": "); |
||||
} |
||||
buffer.append("base calendar: ["); |
||||
if (getBaseCalendar() != null) { |
||||
buffer.append(getBaseCalendar().toString()); |
||||
} else { |
||||
buffer.append("null"); |
||||
} |
||||
buffer.append("], excluded cron expression: '"); |
||||
buffer.append(cronExpression); |
||||
buffer.append("'"); |
||||
return buffer.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the object representation of the cron expression that defines the |
||||
* dates and times this calendar excludes. |
||||
* |
||||
* @return the cron expression |
||||
* @see com.fr.third.org.quartz.CronExpression |
||||
*/ |
||||
public CronExpression getCronExpression() { |
||||
return cronExpression; |
||||
} |
||||
|
||||
/** |
||||
* Sets the cron expression for the calendar to a new value |
||||
* |
||||
* @param expression the new string value to build a cron expression from |
||||
* @throws ParseException |
||||
* if the string expression cannot be parsed |
||||
*/ |
||||
public void setCronExpression(String expression) throws ParseException { |
||||
CronExpression newExp = new CronExpression(expression); |
||||
|
||||
this.cronExpression = newExp; |
||||
} |
||||
|
||||
/** |
||||
* Sets the cron expression for the calendar to a new value |
||||
* |
||||
* @param expression the new cron expression |
||||
*/ |
||||
public void setCronExpression(CronExpression expression) { |
||||
if (expression == null) { |
||||
throw new IllegalArgumentException("expression cannot be null"); |
||||
} |
||||
|
||||
this.cronExpression = expression; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,146 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.SortedSet; |
||||
import java.util.TimeZone; |
||||
import java.util.TreeSet; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
|
||||
/** |
||||
* <p> |
||||
* This implementation of the Calendar stores a list of holidays (full days |
||||
* that are excluded from scheduling). |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* The implementation DOES take the year into consideration, so if you want to |
||||
* exclude July 4th for the next 10 years, you need to add 10 entries to the |
||||
* exclude list. |
||||
* </p> |
||||
* |
||||
* @author Sharada Jambula |
||||
* @author Juergen Donnerstag |
||||
*/ |
||||
public class HolidayCalendar extends BaseCalendar implements Calendar, |
||||
Serializable { |
||||
static final long serialVersionUID = -7590908752291814693L; |
||||
|
||||
// A sorted set to store the holidays
|
||||
private TreeSet dates = new TreeSet(); |
||||
|
||||
public HolidayCalendar() { |
||||
} |
||||
|
||||
public HolidayCalendar(Calendar baseCalendar) { |
||||
super(baseCalendar); |
||||
} |
||||
|
||||
public HolidayCalendar(TimeZone timeZone) { |
||||
super(timeZone); |
||||
} |
||||
|
||||
public HolidayCalendar(Calendar baseCalendar, TimeZone timeZone) { |
||||
super(baseCalendar, timeZone); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine whether the given time (in milliseconds) is 'included' by the |
||||
* Calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public boolean isTimeIncluded(long timeStamp) { |
||||
if (super.isTimeIncluded(timeStamp) == false) { |
||||
return false; |
||||
} |
||||
|
||||
Date lookFor = getStartOfDayJavaCalendar(timeStamp).getTime(); |
||||
|
||||
return !(dates.contains(lookFor)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public long getNextIncludedTime(long timeStamp) { |
||||
|
||||
// Call base calendar implementation first
|
||||
long baseTime = super.getNextIncludedTime(timeStamp); |
||||
if ((baseTime > 0) && (baseTime > timeStamp)) { |
||||
timeStamp = baseTime; |
||||
} |
||||
|
||||
// Get timestamp for 00:00:00
|
||||
java.util.Calendar day = getStartOfDayJavaCalendar(timeStamp); |
||||
while (isTimeIncluded(day.getTime().getTime()) == false) { |
||||
day.add(java.util.Calendar.DATE, 1); |
||||
} |
||||
|
||||
return day.getTime().getTime(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Add the given Date to the list of excluded days. Only the month, day and |
||||
* year of the returned dates are significant. |
||||
* </p> |
||||
*/ |
||||
public void addExcludedDate(Date excludedDate) { |
||||
Date date = getStartOfDayJavaCalendar(excludedDate.getTime()).getTime(); |
||||
/* |
||||
* System.err.println( "HolidayCalendar.add(): date=" + |
||||
* excludedDate.toLocaleString()); |
||||
*/ |
||||
this.dates.add(date); |
||||
} |
||||
|
||||
public void removeExcludedDate(Date dateToRemove) { |
||||
Date date = getStartOfDayJavaCalendar(dateToRemove.getTime()).getTime(); |
||||
dates.remove(date); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Returns a <code>SortedSet</code> of Dates representing the excluded |
||||
* days. Only the month, day and year of the returned dates are |
||||
* significant. |
||||
* </p> |
||||
*/ |
||||
public SortedSet getExcludedDates() { |
||||
return Collections.unmodifiableSortedSet(dates); |
||||
} |
||||
} |
@ -0,0 +1,218 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
* and Juergen Donnerstag (c) 2002, EDS 2002 |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.TimeZone; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
|
||||
/** |
||||
* <p> |
||||
* This implementation of the Calendar excludes a set of days of the month. You |
||||
* may use it to exclude every first day of each month for example. But you may define |
||||
* any day of a month. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar |
||||
* @see com.fr.third.org.quartz.impl.calendar.BaseCalendar |
||||
* |
||||
* @author Juergen Donnerstag |
||||
*/ |
||||
public class MonthlyCalendar extends BaseCalendar implements Calendar, |
||||
Serializable { |
||||
|
||||
static final long serialVersionUID = 419164961091807944L; |
||||
|
||||
private static final int MAX_DAYS_IN_MONTH = 31; |
||||
|
||||
// An array to store a months days which are to be excluded.
|
||||
// java.util.Calendar.get( ) as index.
|
||||
private boolean[] excludeDays = new boolean[MAX_DAYS_IN_MONTH]; |
||||
|
||||
// Will be set to true, if all week days are excluded
|
||||
private boolean excludeAll = false; |
||||
|
||||
public MonthlyCalendar() { |
||||
this(null, null); |
||||
} |
||||
|
||||
public MonthlyCalendar(Calendar baseCalendar) { |
||||
this(baseCalendar, null); |
||||
} |
||||
|
||||
public MonthlyCalendar(TimeZone timeZone) { |
||||
this(null, timeZone); |
||||
} |
||||
|
||||
public MonthlyCalendar(Calendar baseCalendar, TimeZone timeZone) { |
||||
super(baseCalendar, timeZone); |
||||
|
||||
// all days are included by default
|
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the array which defines the exclude-value of each day of month. |
||||
* Only the first 31 elements of the array are relevant, with the 0 index |
||||
* element representing the first day of the month. |
||||
* </p> |
||||
*/ |
||||
public boolean[] getDaysExcluded() { |
||||
return excludeDays; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return true, if day is defined to be excluded. |
||||
* </p> |
||||
* |
||||
* @param day The day of the month (from 1 to 31) to check. |
||||
*/ |
||||
public boolean isDayExcluded(int day) { |
||||
if ((day < 1) || (day > MAX_DAYS_IN_MONTH)) { |
||||
throw new IllegalArgumentException( |
||||
"The day parameter must be in the range of 1 to " + MAX_DAYS_IN_MONTH); |
||||
} |
||||
|
||||
return excludeDays[day - 1]; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine the array of days excluded. The array must non-null and of size |
||||
* greater or equal to 31. The 0 index element represents the first day of |
||||
* the month. |
||||
* </p> |
||||
*/ |
||||
public void setDaysExcluded(boolean[] days) { |
||||
if (days == null) { |
||||
throw new IllegalArgumentException("The days parameter cannot be null."); |
||||
} |
||||
|
||||
if (days.length < MAX_DAYS_IN_MONTH) { |
||||
throw new IllegalArgumentException( |
||||
"The days parameter must have a length of at least " + MAX_DAYS_IN_MONTH + " elements."); |
||||
} |
||||
|
||||
excludeDays = days; |
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine a certain day of the month to be excluded (true) or included |
||||
* (false). |
||||
* </p> |
||||
* |
||||
* @param day The day of the month (from 1 to 31) to set. |
||||
*/ |
||||
public void setDayExcluded(int day, boolean exclude) { |
||||
if ((day < 1) || (day > MAX_DAYS_IN_MONTH)) { |
||||
throw new IllegalArgumentException( |
||||
"The day parameter must be in the range of 1 to " + MAX_DAYS_IN_MONTH); |
||||
} |
||||
|
||||
excludeDays[day - 1] = exclude; |
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Check if all days are excluded. That is no day is included. |
||||
* </p> |
||||
*/ |
||||
public boolean areAllDaysExcluded() { |
||||
for (int i = 1; i <= MAX_DAYS_IN_MONTH; i++) { |
||||
if (isDayExcluded(i) == false) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine whether the given time (in milliseconds) is 'included' by the |
||||
* Calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public boolean isTimeIncluded(long timeStamp) { |
||||
if (excludeAll == true) { |
||||
return false; |
||||
} |
||||
|
||||
// Test the base calendar first. Only if the base calendar not already
|
||||
// excludes the time/date, continue evaluating this calendar instance.
|
||||
if (super.isTimeIncluded(timeStamp) == false) { return false; } |
||||
|
||||
java.util.Calendar cl = createJavaCalendar(timeStamp); |
||||
int day = cl.get(java.util.Calendar.DAY_OF_MONTH); |
||||
|
||||
return !(isDayExcluded(day)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. Return the original value if timeStamp is |
||||
* included. Return 0 if all days are excluded. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public long getNextIncludedTime(long timeStamp) { |
||||
if (excludeAll == true) { |
||||
return 0; |
||||
} |
||||
|
||||
// Call base calendar implementation first
|
||||
long baseTime = super.getNextIncludedTime(timeStamp); |
||||
if ((baseTime > 0) && (baseTime > timeStamp)) { |
||||
timeStamp = baseTime; |
||||
} |
||||
|
||||
// Get timestamp for 00:00:00
|
||||
java.util.Calendar cl = getStartOfDayJavaCalendar(timeStamp); |
||||
int day = cl.get(java.util.Calendar.DAY_OF_MONTH); |
||||
|
||||
if (!isDayExcluded(day)) { |
||||
return timeStamp; // return the original value
|
||||
} |
||||
|
||||
while (isDayExcluded(day) == true) { |
||||
cl.add(java.util.Calendar.DATE, 1); |
||||
day = cl.get(java.util.Calendar.DAY_OF_MONTH); |
||||
} |
||||
|
||||
return cl.getTime().getTime(); |
||||
} |
||||
} |
@ -0,0 +1,200 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
* and Juergen Donnerstag (c) 2002, EDS 2002 |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.calendar; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.TimeZone; |
||||
|
||||
import com.fr.third.org.quartz.Calendar; |
||||
|
||||
/** |
||||
* <p> |
||||
* This implementation of the Calendar excludes a set of days of the week. You |
||||
* may use it to exclude weekends for example. But you may define any day of |
||||
* the week. By default it excludes SATURDAY and SUNDAY. |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.Calendar |
||||
* @see com.fr.third.org.quartz.impl.calendar.BaseCalendar |
||||
* |
||||
* @author Juergen Donnerstag |
||||
*/ |
||||
public class WeeklyCalendar extends BaseCalendar implements Calendar, |
||||
Serializable { |
||||
static final long serialVersionUID = -6809298821229007586L; |
||||
|
||||
// An array to store the week days which are to be excluded.
|
||||
// java.util.Calendar.MONDAY etc. are used as index.
|
||||
private boolean[] excludeDays = new boolean[8]; |
||||
|
||||
// Will be set to true, if all week days are excluded
|
||||
private boolean excludeAll = false; |
||||
|
||||
public WeeklyCalendar() { |
||||
this(null, null); |
||||
} |
||||
|
||||
public WeeklyCalendar(Calendar baseCalendar) { |
||||
this(baseCalendar, null); |
||||
} |
||||
|
||||
public WeeklyCalendar(TimeZone timeZone) { |
||||
super(null, timeZone); |
||||
} |
||||
|
||||
public WeeklyCalendar(Calendar baseCalendar, TimeZone timeZone) { |
||||
super(baseCalendar, timeZone); |
||||
|
||||
excludeDays[java.util.Calendar.SUNDAY] = true; |
||||
excludeDays[java.util.Calendar.SATURDAY] = true; |
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the array with the week days |
||||
* </p> |
||||
*/ |
||||
public boolean[] getDaysExcluded() { |
||||
return excludeDays; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Return true, if wday (see Calendar.get()) is defined to be exluded. E. g. |
||||
* saturday and sunday. |
||||
* </p> |
||||
*/ |
||||
public boolean isDayExcluded(int wday) { |
||||
return excludeDays[wday]; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine the array of days excluded. The array must of size greater or |
||||
* equal 8. java.util.Calendar's constants like MONDAY should be used as |
||||
* index. A value of true is regarded as: exclude it. |
||||
* </p> |
||||
*/ |
||||
public void setDaysExcluded(boolean[] weekDays) { |
||||
if (weekDays == null) { |
||||
return; |
||||
} |
||||
|
||||
excludeDays = weekDays; |
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Redefine a certain day of the week to be excluded (true) or included |
||||
* (false). Use java.util.Calendar's constants like MONDAY to determine the |
||||
* wday. |
||||
* </p> |
||||
*/ |
||||
public void setDayExcluded(int wday, boolean exclude) { |
||||
excludeDays[wday] = exclude; |
||||
excludeAll = areAllDaysExcluded(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Check if all week days are excluded. That is no day is included. |
||||
* </p> |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public boolean areAllDaysExcluded() { |
||||
return |
||||
isDayExcluded(java.util.Calendar.SUNDAY) && |
||||
isDayExcluded(java.util.Calendar.MONDAY) && |
||||
isDayExcluded(java.util.Calendar.TUESDAY) && |
||||
isDayExcluded(java.util.Calendar.WEDNESDAY) && |
||||
isDayExcluded(java.util.Calendar.THURSDAY) && |
||||
isDayExcluded(java.util.Calendar.FRIDAY) && |
||||
isDayExcluded(java.util.Calendar.SATURDAY); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine whether the given time (in milliseconds) is 'included' by the |
||||
* Calendar. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public boolean isTimeIncluded(long timeStamp) { |
||||
if (excludeAll == true) { |
||||
return false; |
||||
} |
||||
|
||||
// Test the base calendar first. Only if the base calendar not already
|
||||
// excludes the time/date, continue evaluating this calendar instance.
|
||||
if (super.isTimeIncluded(timeStamp) == false) { return false; } |
||||
|
||||
java.util.Calendar cl = createJavaCalendar(timeStamp); |
||||
int wday = cl.get(java.util.Calendar.DAY_OF_WEEK); |
||||
|
||||
return !(isDayExcluded(wday)); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Determine the next time (in milliseconds) that is 'included' by the |
||||
* Calendar after the given time. Return the original value if timeStamp is |
||||
* included. Return 0 if all days are excluded. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Note that this Calendar is only has full-day precision. |
||||
* </p> |
||||
*/ |
||||
public long getNextIncludedTime(long timeStamp) { |
||||
if (excludeAll == true) { |
||||
return 0; |
||||
} |
||||
|
||||
// Call base calendar implementation first
|
||||
long baseTime = super.getNextIncludedTime(timeStamp); |
||||
if ((baseTime > 0) && (baseTime > timeStamp)) { |
||||
timeStamp = baseTime; |
||||
} |
||||
|
||||
// Get timestamp for 00:00:00
|
||||
java.util.Calendar cl = getStartOfDayJavaCalendar(timeStamp); |
||||
int wday = cl.get(java.util.Calendar.DAY_OF_WEEK); |
||||
|
||||
if (!isDayExcluded(wday)) { |
||||
return timeStamp; // return the original value
|
||||
} |
||||
|
||||
while (isDayExcluded(wday) == true) { |
||||
cl.add(java.util.Calendar.DATE, 1); |
||||
wday = cl.get(java.util.Calendar.DAY_OF_WEEK); |
||||
} |
||||
|
||||
return cl.getTime().getTime(); |
||||
} |
||||
} |
@ -0,0 +1,159 @@
|
||||
/* |
||||
* Copyright 2004-2006 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.lang.reflect.InvocationHandler; |
||||
import java.lang.reflect.Method; |
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* <p> |
||||
* Protects a <code>{@link java.sql.Connection}</code>'s attributes from being permanently modfied. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* Wraps a provided <code>{@link java.sql.Connection}</code> such that its auto |
||||
* commit and transaction isolation attributes can be overwritten, but |
||||
* will automatically restored to their original values when the connection |
||||
* is actually closed (and potentially returned to a pool for reuse). |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreSupport#getConnection() |
||||
* @see com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreCMT#getNonManagedTXConnection() |
||||
*/ |
||||
public class AttributeRestoringConnectionInvocationHandler implements InvocationHandler { |
||||
private Connection conn; |
||||
|
||||
private boolean overwroteOriginalAutoCommitValue; |
||||
private boolean overwroteOriginalTxIsolationValue; |
||||
|
||||
// Set if overwroteOriginalAutoCommitValue is true
|
||||
private boolean originalAutoCommitValue; |
||||
|
||||
// Set if overwroteOriginalTxIsolationValue is true
|
||||
private int originalTxIsolationValue; |
||||
|
||||
public AttributeRestoringConnectionInvocationHandler( |
||||
Connection conn) { |
||||
this.conn = conn; |
||||
} |
||||
|
||||
protected Log getLog() { |
||||
return LogFactory.getLog(getClass()); |
||||
} |
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) |
||||
throws Throwable { |
||||
if (method.getName().equals("setAutoCommit")) { |
||||
setAutoCommit(((Boolean)args[0]).booleanValue()); |
||||
} else if (method.getName().equals("setTransactionIsolation")) { |
||||
setTransactionIsolation(((Integer)args[0]).intValue()); |
||||
} else if (method.getName().equals("close")) { |
||||
close(); |
||||
} else { |
||||
return method.invoke(conn, args); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Sets this connection's auto-commit mode to the given state, saving |
||||
* the original mode. The connection's original auto commit mode is restored |
||||
* when the connection is closed. |
||||
*/ |
||||
public void setAutoCommit(boolean autoCommit) throws SQLException { |
||||
boolean currentAutoCommitValue = conn.getAutoCommit(); |
||||
|
||||
if (autoCommit != currentAutoCommitValue) { |
||||
if (overwroteOriginalAutoCommitValue == false) { |
||||
overwroteOriginalAutoCommitValue = true; |
||||
originalAutoCommitValue = currentAutoCommitValue; |
||||
} |
||||
|
||||
conn.setAutoCommit(autoCommit); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Attempts to change the transaction isolation level to the given level, saving |
||||
* the original level. The connection's original transaction isolation level is |
||||
* restored when the connection is closed. |
||||
*/ |
||||
public void setTransactionIsolation(int level) throws SQLException { |
||||
int currentLevel = conn.getTransactionIsolation(); |
||||
|
||||
if (level != currentLevel) { |
||||
if (overwroteOriginalTxIsolationValue == false) { |
||||
overwroteOriginalTxIsolationValue = true; |
||||
originalTxIsolationValue = currentLevel; |
||||
} |
||||
|
||||
conn.setTransactionIsolation(level); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets the underlying connection to which all operations ultimately |
||||
* defer. This is provided in case a user ever needs to punch through |
||||
* the wrapper to access vendor specific methods outside of the |
||||
* standard <code>java.sql.Connection</code> interface. |
||||
* |
||||
* @return The underlying connection to which all operations |
||||
* ultimately defer. |
||||
*/ |
||||
public Connection getWrappedConnection() { |
||||
return conn; |
||||
} |
||||
|
||||
/** |
||||
* Attempts to restore the auto commit and transaction isolation connection |
||||
* attributes of the wrapped connection to their original values (if they |
||||
* were overwritten). |
||||
*/ |
||||
public void restoreOriginalAtributes() { |
||||
try { |
||||
if (overwroteOriginalAutoCommitValue) { |
||||
conn.setAutoCommit(originalAutoCommitValue); |
||||
} |
||||
} catch (Throwable t) { |
||||
getLog().warn("Failed restore connection's original auto commit setting.", t); |
||||
} |
||||
|
||||
try { |
||||
if (overwroteOriginalTxIsolationValue) { |
||||
conn.setTransactionIsolation(originalTxIsolationValue); |
||||
} |
||||
} catch (Throwable t) { |
||||
getLog().warn("Failed restore connection's original transaction isolation setting.", t); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Attempts to restore the auto commit and transaction isolation connection |
||||
* attributes of the wrapped connection to their original values (if they |
||||
* were overwritten), before finally actually closing the wrapped connection. |
||||
*/ |
||||
public void close() throws SQLException { |
||||
restoreOriginalAtributes(); |
||||
|
||||
conn.close(); |
||||
} |
||||
} |
@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.IOException; |
||||
import java.io.ObjectInputStream; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* <p> |
||||
* This is a driver delegate for the Cloudscape database, not surprisingly, |
||||
* it is known to work with Derby as well. Though later versions of Derby |
||||
* may simply use StdJDBCDelegate. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
* @author Sridhar Jawaharlal, Srinivas Venkatarangaiah |
||||
* @deprecated Use the StdJDBCDelegate for latest versions of Derby |
||||
*/ |
||||
public class CloudscapeDelegate extends StdJDBCDelegate { |
||||
/** |
||||
* <p> |
||||
* Create new CloudscapeDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public CloudscapeDelegate(Log log, String tablePrefix, String instanceId) { |
||||
super(log, tablePrefix, instanceId); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create new CloudscapeDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
* @param useProperties |
||||
* useProperties flag |
||||
*/ |
||||
public CloudscapeDelegate(Log log, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// protected methods that can be overridden by subclasses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs. The default implementation uses standard |
||||
* JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getObjectFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
Object obj = null; |
||||
|
||||
byte[] inputBytes = rs.getBytes(colName); |
||||
|
||||
if (null != inputBytes && inputBytes.length != 0) { |
||||
ByteArrayInputStream bais = new |
||||
ByteArrayInputStream(inputBytes); |
||||
|
||||
ObjectInputStream in = new ObjectInputStream(bais); |
||||
try { |
||||
obj = in.readObject(); |
||||
} finally { |
||||
in.close(); |
||||
} |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,193 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
/** |
||||
* <p> |
||||
* This interface can be implemented by any <code>{@link |
||||
* com.fr.third.org.quartz.impl.jdbcjobstore.DriverDelegate}</code> |
||||
* class that needs to use the constants contained herein. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
* @author James House |
||||
*/ |
||||
public interface Constants { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
// Table names
|
||||
String TABLE_JOB_DETAILS = "JOB_DETAILS"; |
||||
|
||||
String TABLE_TRIGGERS = "TRIGGERS"; |
||||
|
||||
String TABLE_SIMPLE_TRIGGERS = "SIMPLE_TRIGGERS"; |
||||
|
||||
String TABLE_CRON_TRIGGERS = "CRON_TRIGGERS"; |
||||
|
||||
String TABLE_BLOB_TRIGGERS = "BLOB_TRIGGERS"; |
||||
|
||||
String TABLE_FIRED_TRIGGERS = "FIRED_TRIGGERS"; |
||||
|
||||
String TABLE_JOB_LISTENERS = "JOB_LISTENERS"; |
||||
|
||||
String TABLE_TRIGGER_LISTENERS = "TRIGGER_LISTENERS"; |
||||
|
||||
String TABLE_CALENDARS = "CALENDARS"; |
||||
|
||||
String TABLE_PAUSED_TRIGGERS = "PAUSED_TRIGGER_GRPS"; |
||||
|
||||
String TABLE_LOCKS = "LOCKS"; |
||||
|
||||
String TABLE_SCHEDULER_STATE = "SCHEDULER_STATE"; |
||||
|
||||
// TABLE_JOB_DETAILS columns names
|
||||
String COL_JOB_NAME = "JOB_NAME"; |
||||
|
||||
String COL_JOB_GROUP = "JOB_GROUP"; |
||||
|
||||
String COL_IS_DURABLE = "IS_DURABLE"; |
||||
|
||||
String COL_IS_VOLATILE = "IS_VOLATILE"; |
||||
|
||||
String COL_IS_STATEFUL = "IS_STATEFUL"; |
||||
|
||||
String COL_REQUESTS_RECOVERY = "REQUESTS_RECOVERY"; |
||||
|
||||
String COL_JOB_DATAMAP = "JOB_DATA"; |
||||
|
||||
String COL_JOB_CLASS = "JOB_CLASS_NAME"; |
||||
|
||||
String COL_DESCRIPTION = "DESCRIPTION"; |
||||
|
||||
// TABLE_JOB_LISTENERS columns names
|
||||
String COL_JOB_LISTENER = "JOB_LISTENER"; |
||||
|
||||
// TABLE_TRIGGERS columns names
|
||||
String COL_TRIGGER_NAME = "TRIGGER_NAME"; |
||||
|
||||
String COL_TRIGGER_GROUP = "TRIGGER_GROUP"; |
||||
|
||||
String COL_NEXT_FIRE_TIME = "NEXT_FIRE_TIME"; |
||||
|
||||
String COL_PREV_FIRE_TIME = "PREV_FIRE_TIME"; |
||||
|
||||
String COL_TRIGGER_STATE = "TRIGGER_STATE"; |
||||
|
||||
String COL_TRIGGER_TYPE = "TRIGGER_TYPE"; |
||||
|
||||
String COL_START_TIME = "START_TIME"; |
||||
|
||||
String COL_END_TIME = "END_TIME"; |
||||
|
||||
String COL_PRIORITY = "PRIORITY"; |
||||
|
||||
String COL_MISFIRE_INSTRUCTION = "MISFIRE_INSTR"; |
||||
|
||||
String ALIAS_COL_NEXT_FIRE_TIME = "ALIAS_NXT_FR_TM"; |
||||
|
||||
// TABLE_SIMPLE_TRIGGERS columns names
|
||||
String COL_REPEAT_COUNT = "REPEAT_COUNT"; |
||||
|
||||
String COL_REPEAT_INTERVAL = "REPEAT_INTERVAL"; |
||||
|
||||
String COL_TIMES_TRIGGERED = "TIMES_TRIGGERED"; |
||||
|
||||
// TABLE_CRON_TRIGGERS columns names
|
||||
String COL_CRON_EXPRESSION = "CRON_EXPRESSION"; |
||||
|
||||
// TABLE_BLOB_TRIGGERS columns names
|
||||
String COL_BLOB = "BLOB_DATA"; |
||||
|
||||
String COL_TIME_ZONE_ID = "TIME_ZONE_ID"; |
||||
|
||||
// TABLE_TRIGGER_LISTENERS
|
||||
String COL_TRIGGER_LISTENER = "TRIGGER_LISTENER"; |
||||
|
||||
// TABLE_FIRED_TRIGGERS columns names
|
||||
String COL_INSTANCE_NAME = "INSTANCE_NAME"; |
||||
|
||||
String COL_FIRED_TIME = "FIRED_TIME"; |
||||
|
||||
String COL_ENTRY_ID = "ENTRY_ID"; |
||||
|
||||
String COL_ENTRY_STATE = "STATE"; |
||||
|
||||
// TABLE_CALENDARS columns names
|
||||
String COL_CALENDAR_NAME = "CALENDAR_NAME"; |
||||
|
||||
String COL_CALENDAR = "CALENDAR"; |
||||
|
||||
// TABLE_LOCKS columns names
|
||||
String COL_LOCK_NAME = "LOCK_NAME"; |
||||
|
||||
// TABLE_LOCKS columns names
|
||||
String COL_LAST_CHECKIN_TIME = "LAST_CHECKIN_TIME"; |
||||
|
||||
String COL_CHECKIN_INTERVAL = "CHECKIN_INTERVAL"; |
||||
|
||||
// MISC CONSTANTS
|
||||
String DEFAULT_TABLE_PREFIX = "QRTZ_"; |
||||
|
||||
// STATES
|
||||
String STATE_WAITING = "WAITING"; |
||||
|
||||
String STATE_ACQUIRED = "ACQUIRED"; |
||||
|
||||
String STATE_EXECUTING = "EXECUTING"; |
||||
|
||||
String STATE_COMPLETE = "COMPLETE"; |
||||
|
||||
String STATE_BLOCKED = "BLOCKED"; |
||||
|
||||
String STATE_ERROR = "ERROR"; |
||||
|
||||
String STATE_PAUSED = "PAUSED"; |
||||
|
||||
String STATE_PAUSED_BLOCKED = "PAUSED_BLOCKED"; |
||||
|
||||
String STATE_DELETED = "DELETED"; |
||||
|
||||
/** |
||||
* @deprecated Whether a trigger has misfired is no longer a state, but |
||||
* rather now identified dynamically by whether the trigger's next fire |
||||
* time is more than the misfire threshold time in the past. |
||||
*/ |
||||
String STATE_MISFIRED = "MISFIRED"; |
||||
|
||||
String ALL_GROUPS_PAUSED = "_$_ALL_GROUPS_PAUSED_$_"; |
||||
|
||||
// TRIGGER TYPES
|
||||
String TTYPE_SIMPLE = "SIMPLE"; |
||||
|
||||
String TTYPE_CRON = "CRON"; |
||||
|
||||
String TTYPE_BLOB = "BLOB"; |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,146 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* Quartz JDBC delegate for DB2 v6 databases. <code>select count(name)</code> |
||||
* had to be replaced with <code>select count(*)</code>. |
||||
* |
||||
* @author Martin Renner |
||||
* @author James House |
||||
*/ |
||||
public class DB2v6Delegate extends StdJDBCDelegate { |
||||
public static final String SELECT_NUM_JOBS = "SELECT COUNT(*) FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS; |
||||
|
||||
public static final String SELECT_NUM_TRIGGERS_FOR_JOB = "SELECT COUNT(*) FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_JOB_NAME |
||||
+ " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
public static final String SELECT_NUM_TRIGGERS = "SELECT COUNT(*) FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS; |
||||
|
||||
public static final String SELECT_NUM_CALENDARS = "SELECT COUNT(*) FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CALENDARS; |
||||
|
||||
public DB2v6Delegate(Log logger, String tablePrefix, String instanceId) { |
||||
super(logger, tablePrefix, instanceId); |
||||
} |
||||
|
||||
public DB2v6Delegate(Log logger, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(logger, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
public int selectNumJobs(Connection conn) throws SQLException { |
||||
PreparedStatement ps = null; |
||||
ResultSet rs = null; |
||||
|
||||
try { |
||||
int count = 0; |
||||
ps = conn.prepareStatement(rtp(SELECT_NUM_JOBS)); |
||||
rs = ps.executeQuery(); |
||||
|
||||
if (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
|
||||
return count; |
||||
} finally { |
||||
closeResultSet(rs); |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
public int selectNumTriggersForJob(Connection conn, String jobName, |
||||
String groupName) throws SQLException { |
||||
PreparedStatement ps = null; |
||||
ResultSet rs = null; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(SELECT_NUM_TRIGGERS_FOR_JOB)); |
||||
ps.setString(1, jobName); |
||||
ps.setString(2, groupName); |
||||
rs = ps.executeQuery(); |
||||
|
||||
if (rs.next()) { |
||||
return rs.getInt(1); |
||||
} else { |
||||
return 0; |
||||
} |
||||
} finally { |
||||
closeResultSet(rs); |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
public int selectNumTriggers(Connection conn) throws SQLException { |
||||
PreparedStatement ps = null; |
||||
ResultSet rs = null; |
||||
|
||||
try { |
||||
int count = 0; |
||||
ps = conn.prepareStatement(rtp(SELECT_NUM_TRIGGERS)); |
||||
rs = ps.executeQuery(); |
||||
|
||||
if (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
|
||||
return count; |
||||
} finally { |
||||
closeResultSet(rs); |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
public int selectNumCalendars(Connection conn) throws SQLException { |
||||
PreparedStatement ps = null; |
||||
ResultSet rs = null; |
||||
|
||||
try { |
||||
int count = 0; |
||||
ps = conn.prepareStatement(rtp(SELECT_NUM_CALENDARS)); |
||||
rs = ps.executeQuery(); |
||||
|
||||
if (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
|
||||
return count; |
||||
} finally { |
||||
closeResultSet(rs); |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* Quartz JDBC delegate for DB2 v7 databases. |
||||
* <p> |
||||
* This differs from the <code>StdJDBCDelegate</code> in that it stores |
||||
* <code>boolean</code> values in an <code>varchar(1)</code> column, and saves |
||||
* serialized data in a byte array using |
||||
* <code>{@link PreparedStatement#setObject(int, java.lang.Object, int)}</code> |
||||
* rather than <code>{@link PreparedStatement#setBytes(int, byte[])}</code>. |
||||
* </p> |
||||
* |
||||
* @author Blair Jensen |
||||
*/ |
||||
public class DB2v7Delegate extends StdJDBCDelegate { |
||||
|
||||
public DB2v7Delegate(Log logger, String tablePrefix, String instanceId) { |
||||
super(logger, tablePrefix, instanceId); |
||||
} |
||||
|
||||
public DB2v7Delegate(Log log, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
/** |
||||
* Sets the designated parameter to the byte array of the given |
||||
* <code>ByteArrayOutputStream</code>. Will set parameter value to null if the |
||||
* <code>ByteArrayOutputStream</code> is null. |
||||
* Wraps <code>{@link PreparedStatement#setObject(int, java.lang.Object, int)}</code> rather than |
||||
* <code>{@link PreparedStatement#setBytes(int, byte[])}</code> as required by the |
||||
* DB2 v7 database. |
||||
*/ |
||||
protected void setBytes(PreparedStatement ps, int index, ByteArrayOutputStream baos) throws SQLException { |
||||
ps.setObject(index, ((baos == null) ? null : baos.toByteArray()), java.sql.Types.BLOB); |
||||
} |
||||
|
||||
/** |
||||
* Sets the designated parameter to the given Java <code>boolean</code> value. |
||||
* This translates the boolean to 1/0 for true/false. |
||||
*/ |
||||
protected void setBoolean(PreparedStatement ps, int index, boolean val) throws SQLException { |
||||
ps.setString(index, ((val) ? "1" : "0")); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,51 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* Quartz JDBC delegate for DB2 v8 databases. |
||||
* <p> |
||||
* This differs from the <code>StdJDBCDelegate</code> in that it stores |
||||
* <code>boolean</code> values in an <code>integer</code> column. |
||||
* </p> |
||||
* |
||||
* @author Blair Jensen |
||||
*/ |
||||
public class DB2v8Delegate extends StdJDBCDelegate { |
||||
|
||||
public DB2v8Delegate(Log logger, String tablePrefix, String instanceId) { |
||||
super(logger, tablePrefix, instanceId); |
||||
} |
||||
|
||||
public DB2v8Delegate(Log log, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
/** |
||||
* Sets the designated parameter to the given Java <code>boolean</code> value. |
||||
* This translates the boolean to 1/0 for true/false. |
||||
*/ |
||||
protected void setBoolean(PreparedStatement ps, int index, boolean val) throws SQLException { |
||||
ps.setInt(index, ((val) ? 1 : 0)); |
||||
} |
||||
} |
@ -0,0 +1,201 @@
|
||||
/* |
||||
* Copyright 2004-2006 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.util.HashSet; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Base class for database based lock handlers for providing thread/resource locking |
||||
* in order to protect resources from being altered by multiple threads at the |
||||
* same time. |
||||
*/ |
||||
public abstract class DBSemaphore implements Semaphore, Constants, |
||||
StdJDBCConstants, TablePrefixAware { |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
ThreadLocal lockOwners = new ThreadLocal(); |
||||
|
||||
private String sql; |
||||
|
||||
private String tablePrefix; |
||||
|
||||
private String expandedSQL; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public DBSemaphore(String tablePrefix, String sql, String defaultSQL) { |
||||
this.sql = defaultSQL; |
||||
this.tablePrefix = tablePrefix; |
||||
setSQL(sql); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
private HashSet getThreadLocks() { |
||||
HashSet threadLocks = (HashSet) lockOwners.get(); |
||||
if (threadLocks == null) { |
||||
threadLocks = new HashSet(); |
||||
lockOwners.set(threadLocks); |
||||
} |
||||
return threadLocks; |
||||
} |
||||
|
||||
/** |
||||
* Execute the SQL that will lock the proper database row. |
||||
*/ |
||||
protected abstract void executeSQL( |
||||
Connection conn, String lockName, String expandedSQL) throws LockException; |
||||
|
||||
/** |
||||
* Grants a lock on the identified resource to the calling thread (blocking |
||||
* until it is available). |
||||
* |
||||
* @return true if the lock was obtained. |
||||
*/ |
||||
public boolean obtainLock(Connection conn, String lockName) |
||||
throws LockException { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
Log log = getLog(); |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' is desired by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
if (!isLockOwner(conn, lockName)) { |
||||
|
||||
executeSQL(conn, lockName, expandedSQL); |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' given to: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
getThreadLocks().add(lockName); |
||||
//getThreadLocksObtainer().put(lockName, new
|
||||
// Exception("Obtainer..."));
|
||||
} else if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' Is already owned by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Release the lock on the identified resource if it is held by the calling |
||||
* thread. |
||||
*/ |
||||
public void releaseLock(Connection conn, String lockName) { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
if (isLockOwner(conn, lockName)) { |
||||
if(getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' returned by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
getThreadLocks().remove(lockName); |
||||
//getThreadLocksObtainer().remove(lockName);
|
||||
} else if (getLog().isDebugEnabled()) { |
||||
getLog().warn( |
||||
"Lock '" + lockName + "' attempt to return by: " |
||||
+ Thread.currentThread().getName() |
||||
+ " -- but not owner!", |
||||
new Exception("stack-trace of wrongful returner")); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determine whether the calling thread owns a lock on the identified |
||||
* resource. |
||||
*/ |
||||
public boolean isLockOwner(Connection conn, String lockName) { |
||||
lockName = lockName.intern(); |
||||
|
||||
return getThreadLocks().contains(lockName); |
||||
} |
||||
|
||||
/** |
||||
* This Semaphore implementation does use the database. |
||||
*/ |
||||
public boolean requiresConnection() { |
||||
return true; |
||||
} |
||||
|
||||
protected String getSQL() { |
||||
return sql; |
||||
} |
||||
|
||||
protected void setSQL(String sql) { |
||||
if ((sql != null) && (sql.trim().length() != 0)) { |
||||
this.sql = sql; |
||||
} |
||||
|
||||
setExpandedSQL(); |
||||
} |
||||
|
||||
private void setExpandedSQL() { |
||||
if (getTablePrefix() != null) { |
||||
expandedSQL = Util.rtp(this.sql, getTablePrefix()); |
||||
} |
||||
} |
||||
|
||||
protected String getTablePrefix() { |
||||
return tablePrefix; |
||||
} |
||||
|
||||
public void setTablePrefix(String tablePrefix) { |
||||
this.tablePrefix = tablePrefix; |
||||
|
||||
setExpandedSQL(); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,154 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import com.fr.third.org.quartz.utils.Key; |
||||
|
||||
/** |
||||
* <p> |
||||
* Conveys the state of a fired-trigger record. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class FiredTriggerRecord implements java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private String fireInstanceId; |
||||
|
||||
private long fireTimestamp; |
||||
|
||||
private String schedulerInstanceId; |
||||
|
||||
private Key triggerKey; |
||||
|
||||
private String fireInstanceState; |
||||
|
||||
private boolean triggerIsVolatile; |
||||
|
||||
private Key jobKey; |
||||
|
||||
private boolean jobIsStateful; |
||||
|
||||
private boolean jobRequestsRecovery; |
||||
|
||||
private int priority; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public String getFireInstanceId() { |
||||
return fireInstanceId; |
||||
} |
||||
|
||||
public long getFireTimestamp() { |
||||
return fireTimestamp; |
||||
} |
||||
|
||||
public boolean isJobIsStateful() { |
||||
return jobIsStateful; |
||||
} |
||||
|
||||
public Key getJobKey() { |
||||
return jobKey; |
||||
} |
||||
|
||||
public String getSchedulerInstanceId() { |
||||
return schedulerInstanceId; |
||||
} |
||||
|
||||
public Key getTriggerKey() { |
||||
return triggerKey; |
||||
} |
||||
|
||||
public String getFireInstanceState() { |
||||
return fireInstanceState; |
||||
} |
||||
|
||||
public void setFireInstanceId(String string) { |
||||
fireInstanceId = string; |
||||
} |
||||
|
||||
public void setFireTimestamp(long l) { |
||||
fireTimestamp = l; |
||||
} |
||||
|
||||
public void setJobIsStateful(boolean b) { |
||||
jobIsStateful = b; |
||||
} |
||||
|
||||
public void setJobKey(Key key) { |
||||
jobKey = key; |
||||
} |
||||
|
||||
public void setSchedulerInstanceId(String string) { |
||||
schedulerInstanceId = string; |
||||
} |
||||
|
||||
public void setTriggerKey(Key key) { |
||||
triggerKey = key; |
||||
} |
||||
|
||||
public void setFireInstanceState(String string) { |
||||
fireInstanceState = string; |
||||
} |
||||
|
||||
public boolean isJobRequestsRecovery() { |
||||
return jobRequestsRecovery; |
||||
} |
||||
|
||||
public boolean isTriggerIsVolatile() { |
||||
return triggerIsVolatile; |
||||
} |
||||
|
||||
public void setJobRequestsRecovery(boolean b) { |
||||
jobRequestsRecovery = b; |
||||
} |
||||
|
||||
public void setTriggerIsVolatile(boolean b) { |
||||
triggerIsVolatile = b; |
||||
} |
||||
|
||||
public int getPriority() { |
||||
return priority; |
||||
} |
||||
|
||||
|
||||
public void setPriority(int priority) { |
||||
this.priority = priority; |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,122 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.ObjectInputStream; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* <p> |
||||
* This is a driver delegate for the HSQLDB database. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public class HSQLDBDelegate extends StdJDBCDelegate { |
||||
/** |
||||
* <p> |
||||
* Create new HSQLDBDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public HSQLDBDelegate(Log log, String tablePrefix, String instanceId) { |
||||
super(log, tablePrefix, instanceId); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create new MSSQLDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
* @param useProperties |
||||
* use java.util.Properties for storage |
||||
*/ |
||||
public HSQLDBDelegate(Log log, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// protected methods that can be overridden by subclasses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs. The default implementation uses standard |
||||
* JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getObjectFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
InputStream binaryInput = rs.getBinaryStream(colName); |
||||
|
||||
if(binaryInput == null || binaryInput.available() == 0) { |
||||
return null; |
||||
} |
||||
|
||||
Object obj = null; |
||||
|
||||
ObjectInputStream in = new ObjectInputStream(binaryInput); |
||||
try { |
||||
obj = in.readObject(); |
||||
} finally { |
||||
in.close(); |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
protected Object getJobDetailFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
if (canUseProperties()) { |
||||
InputStream binaryInput = rs.getBinaryStream(colName); |
||||
return binaryInput; |
||||
} |
||||
return getObjectFromBlob(rs, colName); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,50 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
/** |
||||
* <p> |
||||
* Exception class for when a driver delegate cannot be found for a given |
||||
* configuration, or lack thereof. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public class InvalidConfigurationException extends Exception { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public InvalidConfigurationException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
public InvalidConfigurationException() { |
||||
super(); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,304 @@
|
||||
/* |
||||
* Copyright 2004-2006 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.util.HashSet; |
||||
|
||||
import javax.naming.InitialContext; |
||||
import javax.naming.NamingException; |
||||
import javax.transaction.Synchronization; |
||||
import javax.transaction.SystemException; |
||||
import javax.transaction.Transaction; |
||||
import javax.transaction.TransactionManager; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Provides in memory thread/resource locking that is JTA |
||||
* <code>{@link javax.transaction.Transaction}</code> aware. |
||||
* It is most appropriate for use when using |
||||
* <code>{@link com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreCMT}</code> without clustering. |
||||
* |
||||
* <p> |
||||
* This <code>Semaphore</code> implementation is <b>not</b> Quartz cluster safe. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* When a lock is obtained/released but there is no active JTA |
||||
* <code>{@link javax.transaction.Transaction}</code>, then this <code>Semaphore</code> operates |
||||
* just like <code>{@link com.fr.third.org.quartz.impl.jdbcjobstore.SimpleSemaphore}</code>. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* By default, this class looks for the <code>{@link javax.transaction.TransactionManager}</code> |
||||
* in JNDI under name "java:TransactionManager". If this is not where your Application Server |
||||
* registers it, you can modify the JNDI lookup location using the |
||||
* "transactionManagerJNDIName" property. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* <b>IMPORTANT:</b> This Semaphore implementation is currently experimental. |
||||
* It has been tested a limited amount on JBoss 4.0.3SP1. If you do choose to |
||||
* use it, any feedback would be most appreciated! |
||||
* </p> |
||||
* |
||||
* @see com.fr.third.org.quartz.impl.jdbcjobstore.SimpleSemaphore |
||||
*/ |
||||
public class JTANonClusteredSemaphore implements Semaphore { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final String DEFAULT_TRANSACTION_MANANGER_LOCATION = "java:TransactionManager"; |
||||
|
||||
ThreadLocal lockOwners = new ThreadLocal(); |
||||
|
||||
HashSet locks = new HashSet(); |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
private String transactionManagerJNDIName = DEFAULT_TRANSACTION_MANANGER_LOCATION; |
||||
|
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
public void setTransactionManagerJNDIName(String transactionManagerJNDIName) { |
||||
this.transactionManagerJNDIName = transactionManagerJNDIName; |
||||
} |
||||
|
||||
private HashSet getThreadLocks() { |
||||
HashSet threadLocks = (HashSet) lockOwners.get(); |
||||
if (threadLocks == null) { |
||||
threadLocks = new HashSet(); |
||||
lockOwners.set(threadLocks); |
||||
} |
||||
return threadLocks; |
||||
} |
||||
|
||||
/** |
||||
* Grants a lock on the identified resource to the calling thread (blocking |
||||
* until it is available). |
||||
* |
||||
* @return true if the lock was obtained. |
||||
*/ |
||||
public synchronized boolean obtainLock(Connection conn, String lockName) throws LockException { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
Log log = getLog(); |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' is desired by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
|
||||
if (!isLockOwner(conn, lockName)) { |
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' is being obtained: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
|
||||
while (locks.contains(lockName)) { |
||||
try { |
||||
this.wait(); |
||||
} catch (InterruptedException ie) { |
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' was not obtained by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// If we are in a transaction, register a callback to actually release
|
||||
// the lock when the transaction completes
|
||||
Transaction t = getTransaction(); |
||||
if (t != null) { |
||||
try { |
||||
t.registerSynchronization(new SemaphoreSynchronization(lockName)); |
||||
} catch (Exception e) { |
||||
throw new LockException("Failed to register semaphore with Transaction.", e); |
||||
} |
||||
} |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' given to: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
|
||||
|
||||
getThreadLocks().add(lockName); |
||||
locks.add(lockName); |
||||
} else if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' already owned by: " |
||||
+ Thread.currentThread().getName() |
||||
+ " -- but not owner!", |
||||
new Exception("stack-trace of wrongful returner")); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Helper method to get the current <code>{@link javax.transaction.Transaction}</code> |
||||
* from the <code>{@link javax.transaction.TransactionManager}</code> in JNDI. |
||||
* |
||||
* @return The current <code>{@link javax.transaction.Transaction}</code>, null if |
||||
* not currently in a transaction. |
||||
*/ |
||||
protected Transaction getTransaction() throws LockException{ |
||||
InitialContext ic = null; |
||||
try { |
||||
ic = new InitialContext(); |
||||
TransactionManager tm = (TransactionManager)ic.lookup(transactionManagerJNDIName); |
||||
|
||||
return tm.getTransaction(); |
||||
} catch (SystemException e) { |
||||
throw new LockException("Failed to get Transaction from TransactionManager", e); |
||||
} catch (NamingException e) { |
||||
throw new LockException("Failed to find TransactionManager in JNDI under name: " + transactionManagerJNDIName, e); |
||||
} finally { |
||||
if (ic != null) { |
||||
try { |
||||
ic.close(); |
||||
} catch (NamingException ignored) { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Release the lock on the identified resource if it is held by the calling |
||||
* thread, unless currently in a JTA transaction. |
||||
*/ |
||||
public synchronized void releaseLock(Connection conn, String lockName) throws LockException { |
||||
releaseLock(lockName, false); |
||||
} |
||||
|
||||
/** |
||||
* Release the lock on the identified resource if it is held by the calling |
||||
* thread, unless currently in a JTA transaction. |
||||
* |
||||
* @param fromSynchronization True if this method is being invoked from |
||||
* <code>{@link Synchronization}</code> notified of the enclosing |
||||
* transaction having completed. |
||||
* |
||||
* @throws LockException Thrown if there was a problem accessing the JTA |
||||
* <code>Transaction</code>. Only relevant if <code>fromSynchronization</code> |
||||
* is false. |
||||
*/ |
||||
protected synchronized void releaseLock( |
||||
String lockName, boolean fromSynchronization) throws LockException { |
||||
lockName = lockName.intern(); |
||||
|
||||
if (isLockOwner(null, lockName)) { |
||||
|
||||
if (fromSynchronization == false) { |
||||
Transaction t = getTransaction(); |
||||
if (t != null) { |
||||
if(getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' is in a JTA transaction. " + |
||||
"Return deferred by: " + Thread.currentThread().getName()); |
||||
} |
||||
|
||||
// If we are still in a transaction, then we don't want to
|
||||
// actually release the lock.
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
if(getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' returned by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
getThreadLocks().remove(lockName); |
||||
locks.remove(lockName); |
||||
this.notify(); |
||||
} else if (getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' attempt to return by: " |
||||
+ Thread.currentThread().getName() |
||||
+ " -- but not owner!", |
||||
new Exception("stack-trace of wrongful returner")); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determine whether the calling thread owns a lock on the identified |
||||
* resource. |
||||
*/ |
||||
public synchronized boolean isLockOwner(Connection conn, String lockName) { |
||||
lockName = lockName.intern(); |
||||
|
||||
return getThreadLocks().contains(lockName); |
||||
} |
||||
|
||||
/** |
||||
* This Semaphore implementation does not use the database. |
||||
*/ |
||||
public boolean requiresConnection() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Helper class that is registered with the active |
||||
* <code>{@link javax.transaction.Transaction}</code> so that the lock |
||||
* will be released when the transaction completes. |
||||
*/ |
||||
private class SemaphoreSynchronization implements Synchronization { |
||||
private String lockName; |
||||
|
||||
public SemaphoreSynchronization(String lockName) { |
||||
this.lockName = lockName; |
||||
} |
||||
|
||||
public void beforeCompletion() { |
||||
// nothing to do...
|
||||
} |
||||
|
||||
public void afterCompletion(int status) { |
||||
try { |
||||
releaseLock(lockName, true); |
||||
} catch (LockException e) { |
||||
// Ignore as can't be thrown with fromSynchronization set to true
|
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,255 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
import com.fr.third.org.quartz.SchedulerConfigException; |
||||
import com.fr.third.org.quartz.spi.ClassLoadHelper; |
||||
import com.fr.third.org.quartz.spi.SchedulerSignaler; |
||||
import com.fr.third.org.quartz.utils.DBConnectionManager; |
||||
|
||||
/** |
||||
* <p> |
||||
* <code>JobStoreCMT</code> is meant to be used in an application-server |
||||
* environment that provides container-managed-transactions. No commit / |
||||
* rollback will be1 handled by this class. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If you need commit / rollback, use <code>{@link |
||||
* com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreTX}</code> |
||||
* instead. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
* @author James House |
||||
* @author Srinivas Venkatarangaiah |
||||
* |
||||
*/ |
||||
public class JobStoreCMT extends JobStoreSupport { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected String nonManagedTxDsName; |
||||
|
||||
// Great name huh?
|
||||
protected boolean dontSetNonManagedTXConnectionAutoCommitFalse = false; |
||||
|
||||
|
||||
protected boolean setTxIsolationLevelReadCommitted = false; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Set the name of the <code>DataSource</code> that should be used for |
||||
* performing database functions. |
||||
* </p> |
||||
*/ |
||||
public void setNonManagedTXDataSource(String nonManagedTxDsName) { |
||||
this.nonManagedTxDsName = nonManagedTxDsName; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Get the name of the <code>DataSource</code> that should be used for |
||||
* performing database functions. |
||||
* </p> |
||||
*/ |
||||
public String getNonManagedTXDataSource() { |
||||
return nonManagedTxDsName; |
||||
} |
||||
|
||||
public boolean isDontSetNonManagedTXConnectionAutoCommitFalse() { |
||||
return dontSetNonManagedTXConnectionAutoCommitFalse; |
||||
} |
||||
|
||||
/** |
||||
* Don't call set autocommit(false) on connections obtained from the |
||||
* DataSource. This can be helpfull in a few situations, such as if you |
||||
* have a driver that complains if it is called when it is already off. |
||||
* |
||||
* @param b |
||||
*/ |
||||
public void setDontSetNonManagedTXConnectionAutoCommitFalse(boolean b) { |
||||
dontSetNonManagedTXConnectionAutoCommitFalse = b; |
||||
} |
||||
|
||||
|
||||
public boolean isTxIsolationLevelReadCommitted() { |
||||
return setTxIsolationLevelReadCommitted; |
||||
} |
||||
|
||||
/** |
||||
* Set the transaction isolation level of DB connections to sequential. |
||||
* |
||||
* @param b |
||||
*/ |
||||
public void setTxIsolationLevelReadCommitted(boolean b) { |
||||
setTxIsolationLevelReadCommitted = b; |
||||
} |
||||
|
||||
|
||||
public void initialize(ClassLoadHelper loadHelper, |
||||
SchedulerSignaler signaler) throws SchedulerConfigException { |
||||
|
||||
if (nonManagedTxDsName == null) { |
||||
throw new SchedulerConfigException( |
||||
"Non-ManagedTX DataSource name not set! " + |
||||
"If your 'com.fr.third.org.quartz.jobStore.dataSource' is XA, then set " + |
||||
"'com.fr.third.org.quartz.jobStore.nonManagedTXDataSource' to a non-XA "+ |
||||
"datasource (for the same DB). " + |
||||
"Otherwise, you can set them to be the same."); |
||||
} |
||||
|
||||
if (getLockHandler() == null) { |
||||
// If the user hasn't specified an explicit lock handler,
|
||||
// then we *must* use DB locks with CMT...
|
||||
setUseDBLocks(true); |
||||
} |
||||
|
||||
super.initialize(loadHelper, signaler); |
||||
|
||||
getLog().info("JobStoreCMT initialized."); |
||||
} |
||||
|
||||
public void shutdown() { |
||||
|
||||
super.shutdown(); |
||||
|
||||
try { |
||||
DBConnectionManager.getInstance().shutdown(getNonManagedTXDataSource()); |
||||
} catch (SQLException sqle) { |
||||
getLog().warn("Database connection shutdown unsuccessful.", sqle); |
||||
} |
||||
} |
||||
|
||||
protected Connection getNonManagedTXConnection() |
||||
throws JobPersistenceException { |
||||
Connection conn = null; |
||||
try { |
||||
conn = DBConnectionManager.getInstance().getConnection( |
||||
getNonManagedTXDataSource()); |
||||
} catch (SQLException sqle) { |
||||
throw new JobPersistenceException( |
||||
"Failed to obtain DB connection from data source '" |
||||
+ getNonManagedTXDataSource() + "': " |
||||
+ sqle.toString(), sqle); |
||||
} catch (Throwable e) { |
||||
throw new JobPersistenceException( |
||||
"Failed to obtain DB connection from data source '" |
||||
+ getNonManagedTXDataSource() + "': " |
||||
+ e.toString(), e, |
||||
JobPersistenceException.ERR_PERSISTENCE_CRITICAL_FAILURE); |
||||
} |
||||
|
||||
if (conn == null) { |
||||
throw new JobPersistenceException( |
||||
"Could not get connection from DataSource '" |
||||
+ getNonManagedTXDataSource() + "'"); |
||||
} |
||||
|
||||
// Protect connection attributes we might change.
|
||||
conn = getAttributeRestoringConnection(conn); |
||||
|
||||
// Set any connection connection attributes we are to override.
|
||||
try { |
||||
if (!isDontSetNonManagedTXConnectionAutoCommitFalse()) { |
||||
conn.setAutoCommit(false); |
||||
} |
||||
|
||||
if (isTxIsolationLevelReadCommitted()) { |
||||
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); |
||||
} |
||||
} catch (SQLException sqle) { |
||||
getLog().warn("Failed to override connection auto commit/transaction isolation.", sqle); |
||||
} catch (Throwable e) { |
||||
try { conn.close(); } catch(Throwable tt) {} |
||||
|
||||
throw new JobPersistenceException( |
||||
"Failure setting up connection.", e); |
||||
} |
||||
|
||||
return conn; |
||||
} |
||||
|
||||
/** |
||||
* Execute the given callback having optionally aquired the given lock. |
||||
* Because CMT assumes that the connection is already part of a managed |
||||
* transaction, it does not attempt to commit or rollback the |
||||
* enclosing transaction. |
||||
* |
||||
* @param lockName The name of the lock to aquire, for example |
||||
* "TRIGGER_ACCESS". If null, then no lock is aquired, but the |
||||
* txCallback is still executed in a transaction. |
||||
* |
||||
* @see JobStoreSupport#executeInNonManagedTXLock(String, TransactionCallback) |
||||
* @see JobStoreTX#executeInLock(String, TransactionCallback) |
||||
* @see JobStoreSupport#getNonManagedTXConnection() |
||||
* @see JobStoreSupport#getConnection() |
||||
*/ |
||||
protected Object executeInLock( |
||||
String lockName, |
||||
TransactionCallback txCallback) throws JobPersistenceException { |
||||
boolean transOwner = false; |
||||
Connection conn = null; |
||||
try { |
||||
if (lockName != null) { |
||||
// If we aren't using db locks, then delay getting DB connection
|
||||
// until after aquiring the lock since it isn't needed.
|
||||
if (getLockHandler().requiresConnection()) { |
||||
conn = getConnection(); |
||||
} |
||||
|
||||
transOwner = getLockHandler().obtainLock(conn, lockName); |
||||
} |
||||
|
||||
if (conn == null) { |
||||
conn = getConnection(); |
||||
} |
||||
|
||||
return txCallback.execute(conn); |
||||
} finally { |
||||
try { |
||||
releaseLock(conn, LOCK_TRIGGER_ACCESS, transOwner); |
||||
} finally { |
||||
cleanupConnection(conn); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// EOF
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,96 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
|
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
import com.fr.third.org.quartz.SchedulerConfigException; |
||||
import com.fr.third.org.quartz.spi.ClassLoadHelper; |
||||
import com.fr.third.org.quartz.spi.SchedulerSignaler; |
||||
|
||||
/** |
||||
* <p> |
||||
* <code>JobStoreTX</code> is meant to be used in a standalone environment. |
||||
* Both commit and rollback will be handled by this class. |
||||
* </p> |
||||
* |
||||
* <p> |
||||
* If you need a <code>{@link com.fr.third.org.quartz.spi.JobStore}</code> class to use |
||||
* within an application-server environment, use <code>{@link |
||||
* com.fr.third.org.quartz.impl.jdbcjobstore.JobStoreCMT}</code> |
||||
* instead. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
* @author James House |
||||
*/ |
||||
public class JobStoreTX extends JobStoreSupport { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public void initialize(ClassLoadHelper loadHelper, |
||||
SchedulerSignaler signaler) throws SchedulerConfigException { |
||||
|
||||
super.initialize(loadHelper, signaler); |
||||
|
||||
getLog().info("JobStoreTX initialized."); |
||||
} |
||||
|
||||
/** |
||||
* For <code>JobStoreTX</code>, the non-managed TX connection is just |
||||
* the normal connection because it is not CMT. |
||||
* |
||||
* @see JobStoreSupport#getConnection() |
||||
*/ |
||||
protected Connection getNonManagedTXConnection() |
||||
throws JobPersistenceException { |
||||
return getConnection(); |
||||
} |
||||
|
||||
/** |
||||
* Execute the given callback having optionally aquired the given lock. |
||||
* For <code>JobStoreTX</code>, because it manages its own transactions |
||||
* and only has the one datasource, this is the same behavior as |
||||
* executeInNonManagedTXLock(). |
||||
* |
||||
* @param lockName The name of the lock to aquire, for example |
||||
* "TRIGGER_ACCESS". If null, then no lock is aquired, but the |
||||
* lockCallback is still executed in a transaction. |
||||
* |
||||
* @see JobStoreSupport#executeInNonManagedTXLock(String, TransactionCallback) |
||||
* @see JobStoreCMT#executeInLock(String, TransactionCallback) |
||||
* @see JobStoreSupport#getNonManagedTXConnection() |
||||
* @see JobStoreSupport#getConnection() |
||||
*/ |
||||
protected Object executeInLock( |
||||
String lockName, |
||||
TransactionCallback txCallback) throws JobPersistenceException { |
||||
return executeInNonManagedTXLock(lockName, txCallback); |
||||
} |
||||
} |
||||
// EOF
|
@ -0,0 +1,54 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Exception class for when there is a failure obtaining or releasing a |
||||
* resource lock. |
||||
* </p> |
||||
* |
||||
* @see Semaphore |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class LockException extends JobPersistenceException { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public LockException(String msg) { |
||||
super(msg); |
||||
} |
||||
|
||||
public LockException(String msg, Throwable cause) { |
||||
super(msg, cause); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,108 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.ObjectInputStream; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* <p> |
||||
* This is a driver delegate for the MSSQL JDBC driver. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public class MSSQLDelegate extends StdJDBCDelegate { |
||||
/** |
||||
* <p> |
||||
* Create new MSSQLDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public MSSQLDelegate(Log log, String tablePrefix, String instanceId) { |
||||
super(log, tablePrefix, instanceId); |
||||
} |
||||
|
||||
public MSSQLDelegate(Log log, String tablePrefix, String instanceId, Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// protected methods that can be overridden by subclasses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs. The default implementation uses standard |
||||
* JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getObjectFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
InputStream binaryInput = rs.getBinaryStream(colName); |
||||
|
||||
if(binaryInput == null || binaryInput.available() == 0) { |
||||
return null; |
||||
} |
||||
|
||||
Object obj = null; |
||||
|
||||
ObjectInputStream in = new ObjectInputStream(binaryInput); |
||||
try { |
||||
obj = in.readObject(); |
||||
} finally { |
||||
in.close(); |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
protected Object getJobDetailFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
if (canUseProperties()) { |
||||
InputStream binaryInput = rs.getBinaryStream(colName); |
||||
return binaryInput; |
||||
} |
||||
return getObjectFromBlob(rs, colName); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import com.fr.third.org.quartz.JobPersistenceException; |
||||
|
||||
/** |
||||
* <p> |
||||
* Exception class for when a driver delegate cannot be found for a given |
||||
* configuration, or lack thereof. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public class NoSuchDelegateException extends JobPersistenceException { |
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public NoSuchDelegateException(String msg) { |
||||
super(msg); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,507 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.ObjectInputStream; |
||||
import java.math.BigDecimal; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import com.fr.third.org.quartz.Calendar; |
||||
import com.fr.third.org.quartz.CronTrigger; |
||||
import com.fr.third.org.quartz.JobDetail; |
||||
import com.fr.third.org.quartz.SimpleTrigger; |
||||
import com.fr.third.org.quartz.Trigger; |
||||
|
||||
/** |
||||
* <p> |
||||
* This is a driver delegate for the Pointbase JDBC driver. |
||||
* </p> |
||||
* |
||||
* @author Gregg Freeman |
||||
*/ |
||||
public class PointbaseDelegate extends StdJDBCDelegate { |
||||
|
||||
//private static Category log =
|
||||
// Category.getInstance(PointbaseJDBCDelegate.class);
|
||||
/** |
||||
* <p> |
||||
* Create new PointbaseJDBCDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param logger |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public PointbaseDelegate(Log logger, String tablePrefix, String instanceId) { |
||||
super(logger, tablePrefix, instanceId); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create new PointbaseJDBCDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param logger |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public PointbaseDelegate(Log logger, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(logger, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// jobs
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* Insert the job detail record. |
||||
* </p> |
||||
* |
||||
* @param conn |
||||
* the DB Connection |
||||
* @param job |
||||
* the job to insert |
||||
* @return number of rows inserted |
||||
* @throws IOException |
||||
* if there were problems serializing the JobDataMap |
||||
*/ |
||||
public int insertJobDetail(Connection conn, JobDetail job) |
||||
throws IOException, SQLException { |
||||
//log.debug( "Inserting JobDetail " + job );
|
||||
ByteArrayOutputStream baos = serializeJobData(job.getJobDataMap()); |
||||
int len = baos.toByteArray().length; |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
int insertResult = 0; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(INSERT_JOB_DETAIL)); |
||||
ps.setString(1, job.getName()); |
||||
ps.setString(2, job.getGroup()); |
||||
ps.setString(3, job.getDescription()); |
||||
ps.setString(4, job.getJobClass().getName()); |
||||
setBoolean(ps, 5, job.isDurable()); |
||||
setBoolean(ps, 6, job.isVolatile()); |
||||
setBoolean(ps, 7, job.isStateful()); |
||||
setBoolean(ps, 8, job.requestsRecovery()); |
||||
ps.setBinaryStream(9, bais, len); |
||||
|
||||
insertResult = ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
|
||||
if (insertResult > 0) { |
||||
String[] jobListeners = job.getJobListenerNames(); |
||||
for (int i = 0; jobListeners != null && i < jobListeners.length; i++) { |
||||
insertJobListener(conn, job, jobListeners[i]); |
||||
} |
||||
} |
||||
|
||||
return insertResult; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Update the job detail record. |
||||
* </p> |
||||
* |
||||
* @param conn |
||||
* the DB Connection |
||||
* @param job |
||||
* the job to update |
||||
* @return number of rows updated |
||||
* @throws IOException |
||||
* if there were problems serializing the JobDataMap |
||||
*/ |
||||
public int updateJobDetail(Connection conn, JobDetail job) |
||||
throws IOException, SQLException { |
||||
//log.debug( "Updating job detail " + job );
|
||||
ByteArrayOutputStream baos = serializeJobData(job.getJobDataMap()); |
||||
int len = baos.toByteArray().length; |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
int insertResult = 0; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(UPDATE_JOB_DETAIL)); |
||||
ps.setString(1, job.getDescription()); |
||||
ps.setString(2, job.getJobClass().getName()); |
||||
setBoolean(ps, 3, job.isDurable()); |
||||
setBoolean(ps, 4, job.isVolatile()); |
||||
setBoolean(ps, 5, job.isStateful()); |
||||
setBoolean(ps, 6, job.requestsRecovery()); |
||||
ps.setBinaryStream(7, bais, len); |
||||
ps.setString(8, job.getName()); |
||||
ps.setString(9, job.getGroup()); |
||||
|
||||
insertResult = ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
|
||||
if (insertResult > 0) { |
||||
deleteJobListeners(conn, job.getName(), job.getGroup()); |
||||
|
||||
String[] jobListeners = job.getJobListenerNames(); |
||||
for (int i = 0; jobListeners != null && i < jobListeners.length; i++) { |
||||
insertJobListener(conn, job, jobListeners[i]); |
||||
} |
||||
} |
||||
|
||||
return insertResult; |
||||
} |
||||
|
||||
public int insertTrigger(Connection conn, Trigger trigger, String state, |
||||
JobDetail jobDetail) throws SQLException, IOException { |
||||
|
||||
ByteArrayOutputStream baos = serializeJobData(trigger.getJobDataMap()); |
||||
int len = baos.toByteArray().length; |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
int insertResult = 0; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(INSERT_TRIGGER)); |
||||
ps.setString(1, trigger.getName()); |
||||
ps.setString(2, trigger.getGroup()); |
||||
ps.setString(3, trigger.getJobName()); |
||||
ps.setString(4, trigger.getJobGroup()); |
||||
setBoolean(ps, 5, trigger.isVolatile()); |
||||
ps.setString(6, trigger.getDescription()); |
||||
ps.setBigDecimal(7, new BigDecimal(String.valueOf(trigger |
||||
.getNextFireTime().getTime()))); |
||||
long prevFireTime = -1; |
||||
if (trigger.getPreviousFireTime() != null) { |
||||
prevFireTime = trigger.getPreviousFireTime().getTime(); |
||||
} |
||||
ps.setBigDecimal(8, new BigDecimal(String.valueOf(prevFireTime))); |
||||
ps.setString(9, state); |
||||
if (trigger instanceof SimpleTrigger && ((SimpleTrigger)trigger).hasAdditionalProperties() == false ) { |
||||
ps.setString(10, TTYPE_SIMPLE); |
||||
} else if (trigger instanceof CronTrigger && ((CronTrigger)trigger).hasAdditionalProperties() == false ) { |
||||
ps.setString(10, TTYPE_CRON); |
||||
} else { |
||||
ps.setString(10, TTYPE_BLOB); |
||||
} |
||||
ps.setBigDecimal(11, new BigDecimal(String.valueOf(trigger |
||||
.getStartTime().getTime()))); |
||||
long endTime = 0; |
||||
if (trigger.getEndTime() != null) { |
||||
endTime = trigger.getEndTime().getTime(); |
||||
} |
||||
ps.setBigDecimal(12, new BigDecimal(String.valueOf(endTime))); |
||||
ps.setString(13, trigger.getCalendarName()); |
||||
ps.setInt(14, trigger.getMisfireInstruction()); |
||||
ps.setBinaryStream(15, bais, len); |
||||
ps.setInt(16, trigger.getPriority()); |
||||
|
||||
insertResult = ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
|
||||
if (insertResult > 0) { |
||||
String[] trigListeners = trigger.getTriggerListenerNames(); |
||||
for (int i = 0; trigListeners != null && i < trigListeners.length; i++) { |
||||
insertTriggerListener(conn, trigger, trigListeners[i]); |
||||
} |
||||
} |
||||
|
||||
return insertResult; |
||||
} |
||||
|
||||
public int updateTrigger(Connection conn, Trigger trigger, String state, |
||||
JobDetail jobDetail) throws SQLException, IOException { |
||||
|
||||
ByteArrayOutputStream baos = serializeJobData(trigger.getJobDataMap()); |
||||
int len = baos.toByteArray().length; |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
int insertResult = 0; |
||||
|
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(UPDATE_TRIGGER)); |
||||
|
||||
ps.setString(1, trigger.getJobName()); |
||||
ps.setString(2, trigger.getJobGroup()); |
||||
setBoolean(ps, 3, trigger.isVolatile()); |
||||
ps.setString(4, trigger.getDescription()); |
||||
long nextFireTime = -1; |
||||
if (trigger.getNextFireTime() != null) { |
||||
nextFireTime = trigger.getNextFireTime().getTime(); |
||||
} |
||||
ps.setBigDecimal(5, new BigDecimal(String.valueOf(nextFireTime))); |
||||
long prevFireTime = -1; |
||||
if (trigger.getPreviousFireTime() != null) { |
||||
prevFireTime = trigger.getPreviousFireTime().getTime(); |
||||
} |
||||
ps.setBigDecimal(6, new BigDecimal(String.valueOf(prevFireTime))); |
||||
ps.setString(7, state); |
||||
if (trigger instanceof SimpleTrigger && ((SimpleTrigger)trigger).hasAdditionalProperties() == false ) { |
||||
// updateSimpleTrigger(conn, (SimpleTrigger)trigger);
|
||||
ps.setString(8, TTYPE_SIMPLE); |
||||
} else if (trigger instanceof CronTrigger && ((CronTrigger)trigger).hasAdditionalProperties() == false ) { |
||||
// updateCronTrigger(conn, (CronTrigger)trigger);
|
||||
ps.setString(8, TTYPE_CRON); |
||||
} else { |
||||
// updateBlobTrigger(conn, trigger);
|
||||
ps.setString(8, TTYPE_BLOB); |
||||
} |
||||
ps.setBigDecimal(9, new BigDecimal(String.valueOf(trigger |
||||
.getStartTime().getTime()))); |
||||
long endTime = 0; |
||||
if (trigger.getEndTime() != null) { |
||||
endTime = trigger.getEndTime().getTime(); |
||||
} |
||||
ps.setBigDecimal(10, new BigDecimal(String.valueOf(endTime))); |
||||
ps.setString(11, trigger.getCalendarName()); |
||||
ps.setInt(12, trigger.getMisfireInstruction()); |
||||
|
||||
ps.setInt(13, trigger.getPriority()); |
||||
ps.setBinaryStream(14, bais, len); |
||||
ps.setString(15, trigger.getName()); |
||||
ps.setString(16, trigger.getGroup()); |
||||
|
||||
insertResult = ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
|
||||
if (insertResult > 0) { |
||||
deleteTriggerListeners(conn, trigger.getName(), trigger.getGroup()); |
||||
|
||||
String[] trigListeners = trigger.getTriggerListenerNames(); |
||||
for (int i = 0; trigListeners != null && i < trigListeners.length; i++) { |
||||
insertTriggerListener(conn, trigger, trigListeners[i]); |
||||
} |
||||
} |
||||
|
||||
return insertResult; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Update the job data map for the given job. |
||||
* </p> |
||||
* |
||||
* @param conn |
||||
* the DB Connection |
||||
* @param job |
||||
* the job to update |
||||
* @return the number of rows updated |
||||
*/ |
||||
public int updateJobData(Connection conn, JobDetail job) |
||||
throws IOException, SQLException { |
||||
//log.debug( "Updating Job Data for Job " + job );
|
||||
ByteArrayOutputStream baos = serializeJobData(job.getJobDataMap()); |
||||
int len = baos.toByteArray().length; |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
PreparedStatement ps = null; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(UPDATE_JOB_DATA)); |
||||
ps.setBinaryStream(1, bais, len); |
||||
ps.setString(2, job.getName()); |
||||
ps.setString(3, job.getGroup()); |
||||
|
||||
return ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// triggers
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// calendars
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* Insert a new calendar. |
||||
* </p> |
||||
* |
||||
* @param conn |
||||
* the DB Connection |
||||
* @param calendarName |
||||
* the name for the new calendar |
||||
* @param calendar |
||||
* the calendar |
||||
* @return the number of rows inserted |
||||
* @throws IOException |
||||
* if there were problems serializing the calendar |
||||
*/ |
||||
public int insertCalendar(Connection conn, String calendarName, |
||||
Calendar calendar) throws IOException, SQLException { |
||||
//log.debug( "Inserting Calendar " + calendarName + " : " + calendar
|
||||
// );
|
||||
ByteArrayOutputStream baos = serializeObject(calendar); |
||||
byte buf[] = baos.toByteArray(); |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(buf); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(INSERT_CALENDAR)); |
||||
ps.setString(1, calendarName); |
||||
ps.setBinaryStream(2, bais, buf.length); |
||||
|
||||
return ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Update a calendar. |
||||
* </p> |
||||
* |
||||
* @param conn |
||||
* the DB Connection |
||||
* @param calendarName |
||||
* the name for the new calendar |
||||
* @param calendar |
||||
* the calendar |
||||
* @return the number of rows updated |
||||
* @throws IOException |
||||
* if there were problems serializing the calendar |
||||
*/ |
||||
public int updateCalendar(Connection conn, String calendarName, |
||||
Calendar calendar) throws IOException, SQLException { |
||||
//log.debug( "Updating calendar " + calendarName + " : " + calendar );
|
||||
ByteArrayOutputStream baos = serializeObject(calendar); |
||||
byte buf[] = baos.toByteArray(); |
||||
ByteArrayInputStream bais = new ByteArrayInputStream(buf); |
||||
|
||||
PreparedStatement ps = null; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(rtp(UPDATE_CALENDAR)); |
||||
ps.setBinaryStream(1, bais, buf.length); |
||||
ps.setString(2, calendarName); |
||||
|
||||
return ps.executeUpdate(); |
||||
} finally { |
||||
closeStatement(ps); |
||||
} |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// protected methods that can be overridden by subclasses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs. The default implementation uses standard |
||||
* JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getObjectFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
//log.debug( "Getting blob from column: " + colName );
|
||||
Object obj = null; |
||||
|
||||
byte binaryData[] = rs.getBytes(colName); |
||||
|
||||
InputStream binaryInput = new ByteArrayInputStream(binaryData); |
||||
|
||||
if (null != binaryInput && binaryInput.available() != 0) { |
||||
ObjectInputStream in = new ObjectInputStream(binaryInput); |
||||
try { |
||||
obj = in.readObject(); |
||||
} finally { |
||||
in.close(); |
||||
} |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs for job details. The default implementation |
||||
* uses standard JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getJobDetailFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
//log.debug( "Getting Job details from blob in col " + colName );
|
||||
if (canUseProperties()) { |
||||
byte data[] = rs.getBytes(colName); |
||||
if(data == null) { |
||||
return null; |
||||
} |
||||
InputStream binaryInput = new ByteArrayInputStream(data); |
||||
return binaryInput; |
||||
} |
||||
|
||||
return getObjectFromBlob(rs, colName); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,129 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.ObjectInputStream; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
|
||||
/** |
||||
* <p> |
||||
* This is a driver delegate for the PostgreSQL JDBC driver. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public class PostgreSQLDelegate extends StdJDBCDelegate { |
||||
/** |
||||
* <p> |
||||
* Create new PostgreSQLDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
*/ |
||||
public PostgreSQLDelegate(Log log, String tablePrefix, String instanceId) { |
||||
super(log, tablePrefix, instanceId); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Create new PostgreSQLDelegate instance. |
||||
* </p> |
||||
* |
||||
* @param log |
||||
* the logger to use during execution |
||||
* @param tablePrefix |
||||
* the prefix of all table names |
||||
* @param useProperties |
||||
* use java.util.Properties for storage |
||||
*/ |
||||
public PostgreSQLDelegate(Log log, String tablePrefix, String instanceId, |
||||
Boolean useProperties) { |
||||
super(log, tablePrefix, instanceId, useProperties); |
||||
} |
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// protected methods that can be overridden by subclasses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* <p> |
||||
* This method should be overridden by any delegate subclasses that need |
||||
* special handling for BLOBs. The default implementation uses standard |
||||
* JDBC <code>java.sql.Blob</code> operations. |
||||
* </p> |
||||
* |
||||
* @param rs |
||||
* the result set, already queued to the correct row |
||||
* @param colName |
||||
* the column name for the BLOB |
||||
* @return the deserialized Object from the ResultSet BLOB |
||||
* @throws ClassNotFoundException |
||||
* if a class found during deserialization cannot be found |
||||
* @throws IOException |
||||
* if deserialization causes an error |
||||
*/ |
||||
protected Object getObjectFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
InputStream binaryInput = null; |
||||
byte[] bytes = rs.getBytes(colName); |
||||
|
||||
Object obj = null; |
||||
|
||||
if(bytes != null && bytes.length != 0) { |
||||
binaryInput = new ByteArrayInputStream(bytes); |
||||
|
||||
ObjectInputStream in = new ObjectInputStream(binaryInput); |
||||
try { |
||||
obj = in.readObject(); |
||||
} finally { |
||||
in.close(); |
||||
} |
||||
|
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
protected Object getJobDetailFromBlob(ResultSet rs, String colName) |
||||
throws ClassNotFoundException, IOException, SQLException { |
||||
if (canUseProperties()) { |
||||
InputStream binaryInput = null; |
||||
byte[] bytes = rs.getBytes(colName); |
||||
if(bytes == null || bytes.length == 0) { |
||||
return null; |
||||
} |
||||
binaryInput = new ByteArrayInputStream(bytes); |
||||
return binaryInput; |
||||
} |
||||
return getObjectFromBlob(rs, colName); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,92 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
/** |
||||
* <p> |
||||
* Conveys a scheduler-instance state record. |
||||
* </p> |
||||
* |
||||
* @author James House |
||||
*/ |
||||
public class SchedulerStateRecord implements java.io.Serializable { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
private String schedulerInstanceId; |
||||
|
||||
private long checkinTimestamp; |
||||
|
||||
private long checkinInterval; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
*/ |
||||
public long getCheckinInterval() { |
||||
return checkinInterval; |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public long getCheckinTimestamp() { |
||||
return checkinTimestamp; |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public String getSchedulerInstanceId() { |
||||
return schedulerInstanceId; |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public void setCheckinInterval(long l) { |
||||
checkinInterval = l; |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public void setCheckinTimestamp(long l) { |
||||
checkinTimestamp = l; |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public void setSchedulerInstanceId(String string) { |
||||
schedulerInstanceId = string; |
||||
} |
||||
|
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,79 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
|
||||
/** |
||||
* An interface for providing thread/resource locking in order to protect |
||||
* resources from being altered by multiple threads at the same time. |
||||
* |
||||
* @author jhouse |
||||
*/ |
||||
public interface Semaphore { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Grants a lock on the identified resource to the calling thread (blocking |
||||
* until it is available). |
||||
* |
||||
* @param conn Database connection used to establish lock. Can be null if |
||||
* <code>{@link #requiresConnection()}</code> returns false. |
||||
* |
||||
* @return true if the lock was obtained. |
||||
*/ |
||||
boolean obtainLock(Connection conn, String lockName) throws LockException; |
||||
|
||||
/** |
||||
* Release the lock on the identified resource if it is held by the calling |
||||
* thread. |
||||
|
||||
* @param conn Database connection used to establish lock. Can be null if |
||||
* <code>{@link #requiresConnection()}</code> returns false. |
||||
*/ |
||||
void releaseLock(Connection conn, String lockName) throws LockException; |
||||
|
||||
/** |
||||
* Determine whether the calling thread owns a lock on the identified |
||||
* resource. |
||||
|
||||
* @param conn Database connection used to establish lock. Can be null if |
||||
* <code>{@link #requiresConnection()}</code> returns false. |
||||
*/ |
||||
boolean isLockOwner(Connection conn, String lockName) throws LockException; |
||||
|
||||
/** |
||||
* Whether this Semaphore implementation requires a database connection for |
||||
* its lock management operations. |
||||
* |
||||
* @see #isLockOwner(Connection, String) |
||||
* @see #obtainLock(Connection, String) |
||||
* @see #releaseLock(Connection, String) |
||||
*/ |
||||
boolean requiresConnection(); |
||||
} |
@ -0,0 +1,170 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.util.HashSet; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Internal in-memory lock handler for providing thread/resource locking in |
||||
* order to protect resources from being altered by multiple threads at the |
||||
* same time. |
||||
* |
||||
* @author jhouse |
||||
*/ |
||||
public class SimpleSemaphore implements Semaphore { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Data members. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
ThreadLocal lockOwners = new ThreadLocal(); |
||||
|
||||
HashSet locks = new HashSet(); |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
private HashSet getThreadLocks() { |
||||
HashSet threadLocks = (HashSet) lockOwners.get(); |
||||
if (threadLocks == null) { |
||||
threadLocks = new HashSet(); |
||||
lockOwners.set(threadLocks); |
||||
} |
||||
return threadLocks; |
||||
} |
||||
|
||||
/** |
||||
* Grants a lock on the identified resource to the calling thread (blocking |
||||
* until it is available). |
||||
* |
||||
* @return true if the lock was obtained. |
||||
*/ |
||||
public synchronized boolean obtainLock(Connection conn, String lockName) { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
Log log = getLog(); |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' is desired by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
|
||||
if (!isLockOwner(conn, lockName)) { |
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' is being obtained: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
while (locks.contains(lockName)) { |
||||
try { |
||||
this.wait(); |
||||
} catch (InterruptedException ie) { |
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' was not obtained by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' given to: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
getThreadLocks().add(lockName); |
||||
locks.add(lockName); |
||||
} else if(log.isDebugEnabled()) { |
||||
log.debug( |
||||
"Lock '" + lockName + "' already owned by: " |
||||
+ Thread.currentThread().getName() |
||||
+ " -- but not owner!", |
||||
new Exception("stack-trace of wrongful returner")); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Release the lock on the identified resource if it is held by the calling |
||||
* thread. |
||||
*/ |
||||
public synchronized void releaseLock(Connection conn, String lockName) { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
if (isLockOwner(conn, lockName)) { |
||||
if(getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' retuned by: " |
||||
+ Thread.currentThread().getName()); |
||||
} |
||||
getThreadLocks().remove(lockName); |
||||
locks.remove(lockName); |
||||
this.notifyAll(); |
||||
} else if (getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' attempt to retun by: " |
||||
+ Thread.currentThread().getName() |
||||
+ " -- but not owner!", |
||||
new Exception("stack-trace of wrongful returner")); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determine whether the calling thread owns a lock on the identified |
||||
* resource. |
||||
*/ |
||||
public synchronized boolean isLockOwner(Connection conn, String lockName) { |
||||
|
||||
lockName = lockName.intern(); |
||||
|
||||
return getThreadLocks().contains(lockName); |
||||
} |
||||
|
||||
/** |
||||
* This Semaphore implementation does not use the database. |
||||
*/ |
||||
public boolean requiresConnection() { |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,609 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
/** |
||||
* <p> |
||||
* This interface extends <code>{@link |
||||
* com.fr.third.org.quartz.impl.jdbcjobstore.Constants}</code> |
||||
* to include the query string constants in use by the <code>{@link |
||||
* com.fr.third.org.quartz.impl.jdbcjobstore.StdJDBCDelegate}</code> |
||||
* class. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public interface StdJDBCConstants extends Constants { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
// table prefix substitution string
|
||||
String TABLE_PREFIX_SUBST = "{0}"; |
||||
|
||||
// QUERIES
|
||||
String UPDATE_TRIGGER_STATES_FROM_OTHER_STATES = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " SET " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ?" |
||||
+ " WHERE " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ? OR " |
||||
+ COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_STATE_FROM_OTHER_STATES_BEFORE_TIME = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " SET " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ?" |
||||
+ " WHERE (" |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ? OR " |
||||
+ COL_TRIGGER_STATE + " = ?) AND " + COL_NEXT_FIRE_TIME + " < ?"; |
||||
|
||||
String SELECT_MISFIRED_TRIGGERS = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_NEXT_FIRE_TIME + " < ? ORDER BY START_TIME ASC"; |
||||
|
||||
String SELECT_TRIGGERS_IN_STATE = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String SELECT_MISFIRED_TRIGGERS_IN_STATE = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_NEXT_FIRE_TIME + " < ? AND " + COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String COUNT_MISFIRED_TRIGGERS_IN_STATES = "SELECT COUNT(" |
||||
+ COL_TRIGGER_NAME + ") FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_NEXT_FIRE_TIME + " < ? " |
||||
+"AND ((" + COL_TRIGGER_STATE + " = ?) OR (" + COL_TRIGGER_STATE + " = ?))"; |
||||
|
||||
String SELECT_MISFIRED_TRIGGERS_IN_STATES = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_NEXT_FIRE_TIME + " < ? " |
||||
+"AND ((" + COL_TRIGGER_STATE + " = ?) OR (" + COL_TRIGGER_STATE + " = ?))"; |
||||
|
||||
String SELECT_MISFIRED_TRIGGERS_IN_GROUP_IN_STATE = "SELECT " |
||||
+ COL_TRIGGER_NAME |
||||
+ " FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_NEXT_FIRE_TIME |
||||
+ " < ? AND " |
||||
+ COL_TRIGGER_GROUP |
||||
+ " = ? AND " + COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String SELECT_VOLATILE_TRIGGERS = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " + COL_IS_VOLATILE |
||||
+ " = ?"; |
||||
|
||||
String DELETE_FIRED_TRIGGERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS; |
||||
|
||||
String INSERT_JOB_DETAIL = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " (" + COL_JOB_NAME |
||||
+ ", " + COL_JOB_GROUP + ", " + COL_DESCRIPTION + ", " |
||||
+ COL_JOB_CLASS + ", " + COL_IS_DURABLE + ", " + COL_IS_VOLATILE |
||||
+ ", " + COL_IS_STATEFUL + ", " + COL_REQUESTS_RECOVERY + ", " |
||||
+ COL_JOB_DATAMAP + ") " + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
||||
String UPDATE_JOB_DETAIL = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " SET " |
||||
+ COL_DESCRIPTION + " = ?, " + COL_JOB_CLASS + " = ?, " |
||||
+ COL_IS_DURABLE + " = ?, " + COL_IS_VOLATILE + " = ?, " |
||||
+ COL_IS_STATEFUL + " = ?, " + COL_REQUESTS_RECOVERY + " = ?, " |
||||
+ COL_JOB_DATAMAP + " = ? " + " WHERE " + COL_JOB_NAME |
||||
+ " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGERS_FOR_JOB = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " + COL_JOB_NAME |
||||
+ " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGERS_FOR_CALENDAR = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " + COL_CALENDAR_NAME |
||||
+ " = ?"; |
||||
|
||||
String SELECT_STATEFUL_JOBS_OF_TRIGGER_GROUP = "SELECT DISTINCT J." |
||||
+ COL_JOB_NAME |
||||
+ ", J." |
||||
+ COL_JOB_GROUP |
||||
+ " FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " T, " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_DETAILS |
||||
+ " J WHERE T." |
||||
+ COL_TRIGGER_GROUP |
||||
+ " = ? AND T." |
||||
+ COL_JOB_NAME |
||||
+ " = J." |
||||
+ COL_JOB_NAME |
||||
+ " AND T." |
||||
+ COL_JOB_GROUP |
||||
+ " = J." |
||||
+ COL_JOB_GROUP |
||||
+ " AND J." |
||||
+ COL_IS_STATEFUL + " = ?"; |
||||
|
||||
String DELETE_JOB_LISTENERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_LISTENERS + " WHERE " |
||||
+ COL_JOB_NAME + " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String DELETE_JOB_DETAIL = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " WHERE " + COL_JOB_NAME |
||||
+ " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_JOB_STATEFUL = "SELECT " |
||||
+ COL_IS_STATEFUL + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_DETAILS + " WHERE " + COL_JOB_NAME + " = ? AND " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_JOB_EXISTENCE = "SELECT " + COL_JOB_NAME |
||||
+ " FROM " + TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " WHERE " |
||||
+ COL_JOB_NAME + " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String UPDATE_JOB_DATA = "UPDATE " + TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_DETAILS + " SET " + COL_JOB_DATAMAP + " = ? " |
||||
+ " WHERE " + COL_JOB_NAME + " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String INSERT_JOB_LISTENER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_LISTENERS + " (" + COL_JOB_NAME |
||||
+ ", " + COL_JOB_GROUP + ", " + COL_JOB_LISTENER |
||||
+ ") VALUES(?, ?, ?)"; |
||||
|
||||
String SELECT_JOB_LISTENERS = "SELECT " |
||||
+ COL_JOB_LISTENER + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_LISTENERS + " WHERE " + COL_JOB_NAME + " = ? AND " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_JOB_DETAIL = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " WHERE " + COL_JOB_NAME |
||||
+ " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_NUM_JOBS = "SELECT COUNT(" + COL_JOB_NAME |
||||
+ ") " + " FROM " + TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS; |
||||
|
||||
String SELECT_JOB_GROUPS = "SELECT DISTINCT(" |
||||
+ COL_JOB_GROUP + ") FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_DETAILS; |
||||
|
||||
String SELECT_JOBS_IN_GROUP = "SELECT " + COL_JOB_NAME |
||||
+ " FROM " + TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " WHERE " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_VOLATILE_JOBS = "SELECT " + COL_JOB_NAME |
||||
+ ", " + COL_JOB_GROUP + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_JOB_DETAILS + " WHERE " + COL_IS_VOLATILE + " = ?"; |
||||
|
||||
String INSERT_TRIGGER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " (" + COL_TRIGGER_NAME |
||||
+ ", " + COL_TRIGGER_GROUP + ", " + COL_JOB_NAME + ", " |
||||
+ COL_JOB_GROUP + ", " + COL_IS_VOLATILE + ", " + COL_DESCRIPTION |
||||
+ ", " + COL_NEXT_FIRE_TIME + ", " + COL_PREV_FIRE_TIME + ", " |
||||
+ COL_TRIGGER_STATE + ", " + COL_TRIGGER_TYPE + ", " |
||||
+ COL_START_TIME + ", " + COL_END_TIME + ", " + COL_CALENDAR_NAME |
||||
+ ", " + COL_MISFIRE_INSTRUCTION + ", " + COL_JOB_DATAMAP + ", " + COL_PRIORITY + ") " |
||||
+ " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
||||
String INSERT_SIMPLE_TRIGGER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " (" |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " |
||||
+ COL_REPEAT_COUNT + ", " + COL_REPEAT_INTERVAL + ", " |
||||
+ COL_TIMES_TRIGGERED + ") " + " VALUES(?, ?, ?, ?, ?)"; |
||||
|
||||
String INSERT_CRON_TRIGGER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CRON_TRIGGERS + " (" |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " |
||||
+ COL_CRON_EXPRESSION + ", " + COL_TIME_ZONE_ID + ") " |
||||
+ " VALUES(?, ?, ?, ?)"; |
||||
|
||||
String INSERT_BLOB_TRIGGER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_BLOB_TRIGGERS + " (" |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " + COL_BLOB |
||||
+ ") " + " VALUES(?, ?, ?)"; |
||||
|
||||
String UPDATE_TRIGGER_SKIP_DATA = "UPDATE " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " SET " + COL_JOB_NAME + " = ?, " |
||||
+ COL_JOB_GROUP + " = ?, " + COL_IS_VOLATILE + " = ?, " |
||||
+ COL_DESCRIPTION + " = ?, " + COL_NEXT_FIRE_TIME + " = ?, " |
||||
+ COL_PREV_FIRE_TIME + " = ?, " + COL_TRIGGER_STATE + " = ?, " |
||||
+ COL_TRIGGER_TYPE + " = ?, " + COL_START_TIME + " = ?, " |
||||
+ COL_END_TIME + " = ?, " + COL_CALENDAR_NAME + " = ?, " |
||||
+ COL_MISFIRE_INSTRUCTION + " = ?, " + COL_PRIORITY |
||||
+ " = ? WHERE " + COL_TRIGGER_NAME |
||||
+ " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String UPDATE_TRIGGER = "UPDATE " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " SET " + COL_JOB_NAME + " = ?, " |
||||
+ COL_JOB_GROUP + " = ?, " + COL_IS_VOLATILE + " = ?, " |
||||
+ COL_DESCRIPTION + " = ?, " + COL_NEXT_FIRE_TIME + " = ?, " |
||||
+ COL_PREV_FIRE_TIME + " = ?, " + COL_TRIGGER_STATE + " = ?, " |
||||
+ COL_TRIGGER_TYPE + " = ?, " + COL_START_TIME + " = ?, " |
||||
+ COL_END_TIME + " = ?, " + COL_CALENDAR_NAME + " = ?, " |
||||
+ COL_MISFIRE_INSTRUCTION + " = ?, " + COL_PRIORITY + " = ?, " |
||||
+ COL_JOB_DATAMAP + " = ? WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String UPDATE_SIMPLE_TRIGGER = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " SET " |
||||
+ COL_REPEAT_COUNT + " = ?, " + COL_REPEAT_INTERVAL + " = ?, " |
||||
+ COL_TIMES_TRIGGERED + " = ? WHERE " + COL_TRIGGER_NAME |
||||
+ " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String UPDATE_CRON_TRIGGER = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CRON_TRIGGERS + " SET " |
||||
+ COL_CRON_EXPRESSION + " = ? WHERE " + COL_TRIGGER_NAME |
||||
+ " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String UPDATE_BLOB_TRIGGER = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_BLOB_TRIGGERS + " SET " + COL_BLOB |
||||
+ " = ? WHERE " + COL_TRIGGER_NAME + " = ? AND " |
||||
+ COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGER_EXISTENCE = "SELECT " |
||||
+ COL_TRIGGER_NAME + " FROM " + TABLE_PREFIX_SUBST + TABLE_TRIGGERS |
||||
+ " WHERE " + COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP |
||||
+ " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " SET " + COL_TRIGGER_STATE |
||||
+ " = ?" + " WHERE " + COL_TRIGGER_NAME + " = ? AND " |
||||
+ COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_STATE_FROM_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " SET " + COL_TRIGGER_STATE |
||||
+ " = ?" + " WHERE " + COL_TRIGGER_NAME + " = ? AND " |
||||
+ COL_TRIGGER_GROUP + " = ? AND " + COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_GROUP_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " SET " + COL_TRIGGER_STATE |
||||
+ " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_GROUP_STATE_FROM_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " SET " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ?" |
||||
+ " WHERE " |
||||
+ COL_TRIGGER_GROUP |
||||
+ " = ? AND " |
||||
+ COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String UPDATE_TRIGGER_STATE_FROM_STATES = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " SET " + COL_TRIGGER_STATE |
||||
+ " = ?" + " WHERE " + COL_TRIGGER_NAME + " = ? AND " |
||||
+ COL_TRIGGER_GROUP + " = ? AND (" + COL_TRIGGER_STATE + " = ? OR " |
||||
+ COL_TRIGGER_STATE + " = ? OR " + COL_TRIGGER_STATE + " = ?)"; |
||||
|
||||
String UPDATE_TRIGGER_GROUP_STATE_FROM_STATES = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " SET " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ?" |
||||
+ " WHERE " |
||||
+ COL_TRIGGER_GROUP |
||||
+ " = ? AND (" |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ? OR " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ? OR " |
||||
+ COL_TRIGGER_STATE + " = ?)"; |
||||
|
||||
String UPDATE_JOB_TRIGGER_STATES = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " SET " + COL_TRIGGER_STATE |
||||
+ " = ? WHERE " + COL_JOB_NAME + " = ? AND " + COL_JOB_GROUP |
||||
+ " = ?"; |
||||
|
||||
String UPDATE_JOB_TRIGGER_STATES_FROM_OTHER_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS |
||||
+ " SET " |
||||
+ COL_TRIGGER_STATE |
||||
+ " = ? WHERE " |
||||
+ COL_JOB_NAME |
||||
+ " = ? AND " |
||||
+ COL_JOB_GROUP |
||||
+ " = ? AND " + COL_TRIGGER_STATE + " = ?"; |
||||
|
||||
String DELETE_TRIGGER_LISTENERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGER_LISTENERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String INSERT_TRIGGER_LISTENER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGER_LISTENERS + " (" |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " |
||||
+ COL_TRIGGER_LISTENER + ") VALUES(?, ?, ?)"; |
||||
|
||||
String SELECT_TRIGGER_LISTENERS = "SELECT " |
||||
+ COL_TRIGGER_LISTENER + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGER_LISTENERS + " WHERE " + COL_TRIGGER_NAME |
||||
+ " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String DELETE_SIMPLE_TRIGGER = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String DELETE_CRON_TRIGGER = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CRON_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String DELETE_BLOB_TRIGGER = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_BLOB_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String DELETE_TRIGGER = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_NUM_TRIGGERS_FOR_JOB = "SELECT COUNT(" |
||||
+ COL_TRIGGER_NAME + ") FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " WHERE " + COL_JOB_NAME + " = ? AND " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_JOB_FOR_TRIGGER = "SELECT J." |
||||
+ COL_JOB_NAME + ", J." + COL_JOB_GROUP + ", J." + COL_IS_DURABLE |
||||
+ ", J." + COL_JOB_CLASS + ", J." + COL_REQUESTS_RECOVERY + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " T, " + TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS |
||||
+ " J WHERE T." + COL_TRIGGER_NAME + " = ? AND T." |
||||
+ COL_TRIGGER_GROUP + " = ? AND T." + COL_JOB_NAME + " = J." |
||||
+ COL_JOB_NAME + " AND T." + COL_JOB_GROUP + " = J." |
||||
+ COL_JOB_GROUP; |
||||
|
||||
String SELECT_TRIGGER = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGER_DATA = "SELECT " + |
||||
COL_JOB_DATAMAP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGER_STATE = "SELECT " |
||||
+ COL_TRIGGER_STATE + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " WHERE " + COL_TRIGGER_NAME + " = ? AND " |
||||
+ COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGER_STATUS = "SELECT " |
||||
+ COL_TRIGGER_STATE + ", " + COL_NEXT_FIRE_TIME + ", " |
||||
+ COL_JOB_NAME + ", " + COL_JOB_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_SIMPLE_TRIGGER = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_CRON_TRIGGER = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CRON_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_BLOB_TRIGGER = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_BLOB_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_NUM_TRIGGERS = "SELECT COUNT(" |
||||
+ COL_TRIGGER_NAME + ") " + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS; |
||||
|
||||
String SELECT_NUM_TRIGGERS_IN_GROUP = "SELECT COUNT(" |
||||
+ COL_TRIGGER_NAME + ") " + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " WHERE " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_TRIGGER_GROUPS = "SELECT DISTINCT(" |
||||
+ COL_TRIGGER_GROUP + ") FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS; |
||||
|
||||
String SELECT_TRIGGERS_IN_GROUP = "SELECT " |
||||
+ COL_TRIGGER_NAME + " FROM " + TABLE_PREFIX_SUBST + TABLE_TRIGGERS |
||||
+ " WHERE " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String INSERT_CALENDAR = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CALENDARS + " (" + COL_CALENDAR_NAME |
||||
+ ", " + COL_CALENDAR + ") " + " VALUES(?, ?)"; |
||||
|
||||
String UPDATE_CALENDAR = "UPDATE " + TABLE_PREFIX_SUBST |
||||
+ TABLE_CALENDARS + " SET " + COL_CALENDAR + " = ? " + " WHERE " |
||||
+ COL_CALENDAR_NAME + " = ?"; |
||||
|
||||
String SELECT_CALENDAR_EXISTENCE = "SELECT " |
||||
+ COL_CALENDAR_NAME + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_CALENDARS + " WHERE " + COL_CALENDAR_NAME + " = ?"; |
||||
|
||||
String SELECT_CALENDAR = "SELECT *" + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CALENDARS + " WHERE " |
||||
+ COL_CALENDAR_NAME + " = ?"; |
||||
|
||||
String SELECT_REFERENCED_CALENDAR = "SELECT " |
||||
+ COL_CALENDAR_NAME + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_TRIGGERS + " WHERE " + COL_CALENDAR_NAME + " = ?"; |
||||
|
||||
String DELETE_CALENDAR = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_CALENDARS + " WHERE " |
||||
+ COL_CALENDAR_NAME + " = ?"; |
||||
|
||||
String SELECT_NUM_CALENDARS = "SELECT COUNT(" |
||||
+ COL_CALENDAR_NAME + ") " + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_CALENDARS; |
||||
|
||||
String SELECT_CALENDARS = "SELECT " + COL_CALENDAR_NAME |
||||
+ " FROM " + TABLE_PREFIX_SUBST + TABLE_CALENDARS; |
||||
|
||||
String SELECT_NEXT_FIRE_TIME = "SELECT MIN(" |
||||
+ COL_NEXT_FIRE_TIME + ") AS " + ALIAS_COL_NEXT_FIRE_TIME |
||||
+ " FROM " + TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " >= 0"; |
||||
|
||||
String SELECT_TRIGGER_FOR_FIRE_TIME = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " = ?"; |
||||
|
||||
String SELECT_NEXT_TRIGGER_TO_ACQUIRE = "SELECT " |
||||
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " |
||||
+ COL_NEXT_FIRE_TIME + ", " + COL_PRIORITY + " FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " < ? " |
||||
+ "AND (" + COL_NEXT_FIRE_TIME + " >= ?) " |
||||
+ "ORDER BY "+ COL_NEXT_FIRE_TIME + " ASC, " + COL_PRIORITY + " DESC"; |
||||
|
||||
|
||||
String INSERT_FIRED_TRIGGER = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " (" + COL_ENTRY_ID |
||||
+ ", " + COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " |
||||
+ COL_IS_VOLATILE + ", " + COL_INSTANCE_NAME + ", " |
||||
+ COL_FIRED_TIME + ", " + COL_ENTRY_STATE + ", " + COL_JOB_NAME |
||||
+ ", " + COL_JOB_GROUP + ", " + COL_IS_STATEFUL + ", " |
||||
+ COL_REQUESTS_RECOVERY + ", " + COL_PRIORITY |
||||
+ ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
||||
String UPDATE_INSTANCES_FIRED_TRIGGER_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " SET " |
||||
+ COL_ENTRY_STATE + " = ? AND " + COL_FIRED_TIME + " = ? AND " + COL_PRIORITY+ " = ? WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String SELECT_INSTANCES_FIRED_TRIGGERS = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String SELECT_INSTANCES_RECOVERABLE_FIRED_TRIGGERS = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ? AND " + COL_REQUESTS_RECOVERY + " = ?"; |
||||
|
||||
String SELECT_JOB_EXECUTION_COUNT = "SELECT COUNT(" |
||||
+ COL_TRIGGER_NAME + ") FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS + " WHERE " + COL_JOB_NAME + " = ? AND " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_FIRED_TRIGGERS = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS; |
||||
|
||||
String SELECT_FIRED_TRIGGER = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_NAME + " = ? AND " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_FIRED_TRIGGER_GROUP = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_FIRED_TRIGGERS_OF_JOB = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_JOB_NAME + " = ? AND " + COL_JOB_GROUP + " = ?"; |
||||
|
||||
String SELECT_FIRED_TRIGGERS_OF_JOB_GROUP = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_JOB_GROUP + " = ?"; |
||||
|
||||
String DELETE_FIRED_TRIGGER = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_ENTRY_ID + " = ?"; |
||||
|
||||
String DELETE_INSTANCES_FIRED_TRIGGERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String DELETE_VOLATILE_FIRED_TRIGGERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_FIRED_TRIGGERS + " WHERE " |
||||
+ COL_IS_VOLATILE + " = ?"; |
||||
|
||||
String DELETE_NO_RECOVERY_FIRED_TRIGGERS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS |
||||
+ " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?" + COL_REQUESTS_RECOVERY + " = ?"; |
||||
|
||||
String SELECT_FIRED_TRIGGER_INSTANCE_NAMES = |
||||
"SELECT DISTINCT " + COL_INSTANCE_NAME + " FROM " |
||||
+ TABLE_PREFIX_SUBST |
||||
+ TABLE_FIRED_TRIGGERS; |
||||
|
||||
String INSERT_SCHEDULER_STATE = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SCHEDULER_STATE + " (" |
||||
+ COL_INSTANCE_NAME + ", " + COL_LAST_CHECKIN_TIME + ", " |
||||
+ COL_CHECKIN_INTERVAL + ") VALUES(?, ?, ?)"; |
||||
|
||||
String SELECT_SCHEDULER_STATE = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SCHEDULER_STATE + " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String SELECT_SCHEDULER_STATES = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SCHEDULER_STATE; |
||||
|
||||
String DELETE_SCHEDULER_STATE = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SCHEDULER_STATE + " WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String UPDATE_SCHEDULER_STATE = "UPDATE " |
||||
+ TABLE_PREFIX_SUBST + TABLE_SCHEDULER_STATE + " SET " |
||||
+ COL_LAST_CHECKIN_TIME + " = ? WHERE " |
||||
+ COL_INSTANCE_NAME + " = ?"; |
||||
|
||||
String INSERT_PAUSED_TRIGGER_GROUP = "INSERT INTO " |
||||
+ TABLE_PREFIX_SUBST + TABLE_PAUSED_TRIGGERS + " (" |
||||
+ COL_TRIGGER_GROUP + ") VALUES(?)"; |
||||
|
||||
String SELECT_PAUSED_TRIGGER_GROUP = "SELECT " |
||||
+ COL_TRIGGER_GROUP + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_PAUSED_TRIGGERS + " WHERE " + COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String SELECT_PAUSED_TRIGGER_GROUPS = "SELECT " |
||||
+ COL_TRIGGER_GROUP + " FROM " + TABLE_PREFIX_SUBST |
||||
+ TABLE_PAUSED_TRIGGERS; |
||||
|
||||
String DELETE_PAUSED_TRIGGER_GROUP = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_PAUSED_TRIGGERS + " WHERE " |
||||
+ COL_TRIGGER_GROUP + " = ?"; |
||||
|
||||
String DELETE_PAUSED_TRIGGER_GROUPS = "DELETE FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_PAUSED_TRIGGERS; |
||||
|
||||
// CREATE TABLE qrtz_scheduler_state(INSTANCE_NAME VARCHAR2(80) NOT NULL,
|
||||
// LAST_CHECKIN_TIME NUMBER(13) NOT NULL, CHECKIN_INTERVAL NUMBER(13) NOT
|
||||
// NULL, PRIMARY KEY (INSTANCE_NAME));
|
||||
|
||||
} |
||||
|
||||
// EOF
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,137 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
|
||||
/** |
||||
* Internal database based lock handler for providing thread/resource locking |
||||
* in order to protect resources from being altered by multiple threads at the |
||||
* same time. |
||||
* |
||||
* @author jhouse |
||||
*/ |
||||
public class StdRowLockSemaphore extends DBSemaphore { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final String SELECT_FOR_LOCK = "SELECT * FROM " |
||||
+ TABLE_PREFIX_SUBST + TABLE_LOCKS + " WHERE " + COL_LOCK_NAME |
||||
+ " = ? FOR UPDATE"; |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* This constructor is for using the <code>StdRowLockSemaphore</code> as |
||||
* a bean. |
||||
*/ |
||||
public StdRowLockSemaphore() { |
||||
super(DEFAULT_TABLE_PREFIX, null, SELECT_FOR_LOCK); |
||||
} |
||||
|
||||
public StdRowLockSemaphore(String tablePrefix, String selectWithLockSQL) { |
||||
super(tablePrefix, selectWithLockSQL, SELECT_FOR_LOCK); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Execute the SQL select for update that will lock the proper database row. |
||||
*/ |
||||
protected void executeSQL(Connection conn, String lockName, String expandedSQL) throws LockException { |
||||
PreparedStatement ps = null; |
||||
ResultSet rs = null; |
||||
try { |
||||
ps = conn.prepareStatement(expandedSQL); |
||||
ps.setString(1, lockName); |
||||
|
||||
if (getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' is being obtained: " + |
||||
Thread.currentThread().getName()); |
||||
} |
||||
rs = ps.executeQuery(); |
||||
if (!rs.next()) { |
||||
throw new SQLException(Util.rtp( |
||||
"No row exists in table " + TABLE_PREFIX_SUBST + |
||||
TABLE_LOCKS + " for lock named: " + lockName, getTablePrefix())); |
||||
} |
||||
} catch (SQLException sqle) { |
||||
//Exception src =
|
||||
// (Exception)getThreadLocksObtainer().get(lockName);
|
||||
//if(src != null)
|
||||
// src.printStackTrace();
|
||||
//else
|
||||
// System.err.println("--- ***************** NO OBTAINER!");
|
||||
|
||||
if (getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' was not obtained by: " + |
||||
Thread.currentThread().getName()); |
||||
} |
||||
|
||||
throw new LockException("Failure obtaining db row lock: " |
||||
+ sqle.getMessage(), sqle); |
||||
} finally { |
||||
if (rs != null) { |
||||
try { |
||||
rs.close(); |
||||
} catch (Exception ignore) { |
||||
} |
||||
} |
||||
if (ps != null) { |
||||
try { |
||||
ps.close(); |
||||
} catch (Exception ignore) { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected String getSelectWithLockSQL() { |
||||
return getSQL(); |
||||
} |
||||
|
||||
public void setSelectWithLockSQL(String selectWithLockSQL) { |
||||
setSQL(selectWithLockSQL); |
||||
} |
||||
} |
@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2004-2006 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
/** |
||||
* Interface for Quartz objects that need to know what the table prefix of |
||||
* the tables used by a JDBC JobStore is. |
||||
*/ |
||||
public interface TablePrefixAware { |
||||
void setTablePrefix(String tablePrefix); |
||||
} |
@ -0,0 +1,126 @@
|
||||
/* |
||||
* Copyright 2004-2006 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
|
||||
/** |
||||
* Provide thread/resource locking in order to protect |
||||
* resources from being altered by multiple threads at the same time using |
||||
* a db row update. |
||||
* |
||||
* <p> |
||||
* <b>Note:</b> This Semaphore implementation is useful for databases that do |
||||
* not support row locking via "SELECT FOR UPDATE" type syntax, for example |
||||
* Microsoft SQLServer (MSSQL). |
||||
* </p> |
||||
*/ |
||||
public class UpdateLockRowSemaphore extends DBSemaphore { |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public static final String UPDATE_FOR_LOCK = |
||||
"UPDATE " + TABLE_PREFIX_SUBST + TABLE_LOCKS + |
||||
" SET " + COL_LOCK_NAME + " = " + COL_LOCK_NAME + |
||||
" WHERE " + COL_LOCK_NAME + " = ? "; |
||||
|
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constructors. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public UpdateLockRowSemaphore() { |
||||
super(DEFAULT_TABLE_PREFIX, null, UPDATE_FOR_LOCK); |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Execute the SQL select for update that will lock the proper database row. |
||||
*/ |
||||
protected void executeSQL(Connection conn, String lockName, String expandedSQL) throws LockException { |
||||
PreparedStatement ps = null; |
||||
|
||||
try { |
||||
ps = conn.prepareStatement(expandedSQL); |
||||
ps.setString(1, lockName); |
||||
|
||||
if (getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' is being obtained: " + |
||||
Thread.currentThread().getName()); |
||||
} |
||||
|
||||
int numUpdate = ps.executeUpdate(); |
||||
|
||||
if (numUpdate < 1) { |
||||
throw new SQLException(Util.rtp( |
||||
"No row exists in table " + TABLE_PREFIX_SUBST + TABLE_LOCKS + |
||||
" for lock named: " + lockName, getTablePrefix())); |
||||
} |
||||
} catch (SQLException sqle) { |
||||
//Exception src =
|
||||
// (Exception)getThreadLocksObtainer().get(lockName);
|
||||
//if(src != null)
|
||||
// src.printStackTrace();
|
||||
//else
|
||||
// System.err.println("--- ***************** NO OBTAINER!");
|
||||
|
||||
if(getLog().isDebugEnabled()) { |
||||
getLog().debug( |
||||
"Lock '" + lockName + "' was not obtained by: " + |
||||
Thread.currentThread().getName()); |
||||
} |
||||
|
||||
throw new LockException( |
||||
"Failure obtaining db row lock: " + sqle.getMessage(), sqle); |
||||
} finally { |
||||
if (ps != null) { |
||||
try { |
||||
ps.close(); |
||||
} catch (Exception ignore) { |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected String getUpdateLockRowSQL() { |
||||
return getSQL(); |
||||
} |
||||
|
||||
public void setUpdateLockRowSQL(String updateLockRowSQL) { |
||||
setSQL(updateLockRowSQL); |
||||
} |
||||
} |
@ -0,0 +1,95 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.impl.jdbcjobstore; |
||||
|
||||
import java.text.MessageFormat; |
||||
|
||||
/** |
||||
* <p> |
||||
* This class contains utility functions for use in all delegate classes. |
||||
* </p> |
||||
* |
||||
* @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a> |
||||
*/ |
||||
public final class Util { |
||||
|
||||
/** |
||||
* Private constructor because this is a pure utility class. |
||||
*/ |
||||
private Util() { |
||||
} |
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* <p> |
||||
* Replace the table prefix in a query by replacing any occurrences of |
||||
* "{0}" with the table prefix. |
||||
* </p> |
||||
* |
||||
* @param query |
||||
* the unsubstitued query |
||||
* @param tablePrefix |
||||
* the table prefix |
||||
* @return the query, with proper table prefix substituted |
||||
*/ |
||||
public static String rtp(String query, String tablePrefix) { |
||||
return MessageFormat.format(query, new Object[]{tablePrefix}); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Obtain a unique key for a given job. |
||||
* </p> |
||||
* |
||||
* @param jobName |
||||
* the job name |
||||
* @param groupName |
||||
* the group containing the job |
||||
* @return a unique <code>String</code> key |
||||
*/ |
||||
static String getJobNameKey(String jobName, String groupName) { |
||||
return (groupName + "_$x$x$_" + jobName).intern(); |
||||
} |
||||
|
||||
/** |
||||
* <p> |
||||
* Obtain a unique key for a given trigger. |
||||
* </p> |
||||
* |
||||
* @param triggerName |
||||
* the trigger name |
||||
* @param groupName |
||||
* the group containing the trigger |
||||
* @return a unique <code>String</code> key |
||||
*/ |
||||
static String getTriggerNameKey(String triggerName, String groupName) { |
||||
return (groupName + "_$x$x$_" + triggerName).intern(); |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,18 @@
|
||||
<html> |
||||
<head> |
||||
<title>Package com.fr.third.org.quartz.impl</title> |
||||
</head> |
||||
<body> |
||||
<p>Contains implementations of the SchedulerFactory, JobStore, ThreadPool, and |
||||
other interfaces required by the com.fr.third.org.quartz.core.QuartzScheduler.</p> |
||||
|
||||
<p>Classes in this package may have dependencies on third-party packages.</p> |
||||
|
||||
<br> |
||||
<br> |
||||
<hr> |
||||
See the <a href="http://www.opensymphony.com/quartz">Quartz</a> project |
||||
at <a href="http://www.opensymphony.com">Open Symphony</a> for more information. |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,136 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.jobs; |
||||
|
||||
import java.io.File; |
||||
import java.net.URL; |
||||
import java.net.URLDecoder; |
||||
|
||||
import com.fr.third.org.quartz.JobDataMap; |
||||
import com.fr.third.org.quartz.JobExecutionContext; |
||||
import com.fr.third.org.quartz.JobExecutionException; |
||||
import com.fr.third.org.quartz.SchedulerContext; |
||||
import com.fr.third.org.quartz.SchedulerException; |
||||
import com.fr.third.org.quartz.StatefulJob; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Inspects a file and compares whether it's "last modified date" has changed |
||||
* since the last time it was inspected. If the file has been updated, the |
||||
* job invokes a "call-back" method on an identified |
||||
* <code>FileScanListener</code> that can be found in the |
||||
* <code>SchedulerContext</code>. |
||||
* |
||||
* @author jhouse |
||||
* @author pl47ypus |
||||
* @see com.fr.third.org.quartz.jobs.FileScanListener |
||||
*/ |
||||
public class FileScanJob implements StatefulJob { |
||||
|
||||
public static final String FILE_NAME = "FILE_NAME"; |
||||
public static final String FILE_SCAN_LISTENER_NAME = "FILE_SCAN_LISTENER_NAME"; |
||||
private static final String LAST_MODIFIED_TIME = "LAST_MODIFIED_TIME"; |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
public FileScanJob() { |
||||
} |
||||
|
||||
/** |
||||
* @see com.fr.third.org.quartz.Job#execute(com.fr.third.org.quartz.JobExecutionContext) |
||||
*/ |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
JobDataMap mergedJobDataMap = context.getMergedJobDataMap(); |
||||
SchedulerContext schedCtxt = null; |
||||
try { |
||||
schedCtxt = context.getScheduler().getContext(); |
||||
} catch (SchedulerException e) { |
||||
throw new JobExecutionException("Error obtaining scheduler context.", e, false); |
||||
} |
||||
|
||||
String fileName = mergedJobDataMap.getString(FILE_NAME); |
||||
String listenerName = mergedJobDataMap.getString(FILE_SCAN_LISTENER_NAME); |
||||
|
||||
if(fileName == null) { |
||||
throw new JobExecutionException("Required parameter '" + |
||||
FILE_NAME + "' not found in merged JobDataMap"); |
||||
} |
||||
if(listenerName == null) { |
||||
throw new JobExecutionException("Required parameter '" + |
||||
FILE_SCAN_LISTENER_NAME + "' not found in merged JobDataMap"); |
||||
} |
||||
|
||||
FileScanListener listener = (FileScanListener)schedCtxt.get(listenerName); |
||||
|
||||
if(listener == null) { |
||||
throw new JobExecutionException("FileScanListener named '" + |
||||
listenerName + "' not found in SchedulerContext"); |
||||
} |
||||
|
||||
long lastDate = -1; |
||||
if(mergedJobDataMap.containsKey(LAST_MODIFIED_TIME)) { |
||||
lastDate = mergedJobDataMap.getLong(LAST_MODIFIED_TIME); |
||||
} |
||||
|
||||
long newDate = getLastModifiedDate(fileName); |
||||
|
||||
if(newDate < 0) { |
||||
log.warn("File '"+fileName+"' does not exist."); |
||||
return; |
||||
} |
||||
|
||||
if(lastDate > 0 && (newDate != lastDate)) { |
||||
// notify call back...
|
||||
log.info("File '"+fileName+"' updated, notifying listener."); |
||||
listener.fileUpdated(fileName); |
||||
} else if (log.isDebugEnabled()) { |
||||
log.debug("File '"+fileName+"' unchanged."); |
||||
} |
||||
|
||||
// It is the JobDataMap on the JobDetail which is actually stateful
|
||||
context.getJobDetail().getJobDataMap().put(LAST_MODIFIED_TIME, newDate); |
||||
} |
||||
|
||||
protected long getLastModifiedDate(String fileName) { |
||||
URL resource = Thread.currentThread().getContextClassLoader().getResource(fileName); |
||||
|
||||
// Get the absolute path.
|
||||
String filePath = (resource == null) ? fileName : URLDecoder.decode(resource.getFile()); ; |
||||
|
||||
// If the jobs file is inside a jar point to the jar file (to get it modification date).
|
||||
// Otherwise continue as usual.
|
||||
int jarIndicator = filePath.indexOf('!'); |
||||
|
||||
if (jarIndicator > 0) { |
||||
filePath = filePath.substring(5, filePath.indexOf('!')); |
||||
} |
||||
|
||||
File file = new File(filePath); |
||||
|
||||
if(!file.exists()) { |
||||
return -1; |
||||
} else { |
||||
return file.lastModified(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,121 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package org.quartz.jobs; |
||||
|
||||
import java.io.File; |
||||
|
||||
import org.quartz.JobDataMap; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
import org.quartz.SchedulerContext; |
||||
import org.quartz.SchedulerException; |
||||
import org.quartz.StatefulJob; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Inspects a file and compares whether it's "last modified date" has changed |
||||
* since the last time it was inspected. If the file has been updated, the |
||||
* job invokes a "call-back" method on an identified |
||||
* <code>FileScanListener</code> that can be found in the |
||||
* <code>SchedulerContext</code>. |
||||
* |
||||
* @author jhouse |
||||
* @see org.quartz.jobs.FileScanListener |
||||
*/ |
||||
public class FileScanJob implements StatefulJob { |
||||
|
||||
public static String FILE_NAME = "FILE_NAME"; |
||||
public static String FILE_SCAN_LISTENER_NAME = "FILE_SCAN_LISTENER_NAME"; |
||||
private static String LAST_MODIFIED_TIME = "LAST_MODIFIED_TIME"; |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
public FileScanJob() { |
||||
} |
||||
|
||||
/** |
||||
* @see org.quartz.Job#execute(org.quartz.JobExecutionContext) |
||||
*/ |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
JobDataMap mergedJobDataMap = context.getMergedJobDataMap(); |
||||
SchedulerContext schedCtxt = null; |
||||
try { |
||||
schedCtxt = context.getScheduler().getContext(); |
||||
} catch (SchedulerException e) { |
||||
throw new JobExecutionException("Error obtaining scheduler context.", e, false); |
||||
} |
||||
|
||||
String fileName = mergedJobDataMap.getString(FILE_NAME); |
||||
String listenerName = mergedJobDataMap.getString(FILE_SCAN_LISTENER_NAME); |
||||
|
||||
if(fileName == null) { |
||||
throw new JobExecutionException("Required parameter '" + |
||||
FILE_NAME + "' not found in merged JobDataMap"); |
||||
} |
||||
if(listenerName == null) { |
||||
throw new JobExecutionException("Required parameter '" + |
||||
FILE_SCAN_LISTENER_NAME + "' not found in merged JobDataMap"); |
||||
} |
||||
|
||||
FileScanListener listener = (FileScanListener)schedCtxt.get(listenerName); |
||||
|
||||
if(listener == null) { |
||||
throw new JobExecutionException("FileScanListener named '" + |
||||
listenerName + "' not found in SchedulerContext"); |
||||
} |
||||
|
||||
long lastDate = -1; |
||||
if(mergedJobDataMap.containsKey(LAST_MODIFIED_TIME)) { |
||||
lastDate = mergedJobDataMap.getLong(LAST_MODIFIED_TIME); |
||||
} |
||||
|
||||
long newDate = getLastModifiedDate(fileName); |
||||
|
||||
if(newDate < 0) { |
||||
log.warn("File '"+fileName+"' does not exist."); |
||||
return; |
||||
} |
||||
|
||||
if(lastDate > 0 && (newDate != lastDate)) { |
||||
// notify call back...
|
||||
log.info("File '"+fileName+"' updated, notifying listener."); |
||||
listener.fileUpdated(fileName); |
||||
} else if (log.isDebugEnabled()) { |
||||
log.debug("File '"+fileName+"' unchanged."); |
||||
} |
||||
|
||||
// It is the JobDataMap on the JobDetail which is actually stateful
|
||||
context.getJobDetail().getJobDataMap().put(LAST_MODIFIED_TIME, newDate); |
||||
} |
||||
|
||||
protected long getLastModifiedDate(String fileName) { |
||||
|
||||
File file = new File(fileName); |
||||
|
||||
if(!file.exists()) { |
||||
return -1; |
||||
} else { |
||||
return file.lastModified(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
package com.fr.third.org.quartz.jobs; |
||||
|
||||
/** |
||||
* Interface for objects wishing to receive a 'call-back' from a |
||||
* <code>FileScanJob</code>. |
||||
* |
||||
* @author jhouse |
||||
* @see com.fr.third.org.quartz.jobs.FileScanJob |
||||
*/ |
||||
public interface FileScanListener { |
||||
|
||||
void fileUpdated(String fileName); |
||||
} |
@ -0,0 +1,280 @@
|
||||
/* |
||||
* Copyright 2004-2005 OpenSymphony |
||||
* |
||||
* Licensed 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* Previously Copyright (c) 2001-2004 James House |
||||
*/ |
||||
|
||||
package com.fr.third.org.quartz.jobs; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import com.fr.third.org.quartz.Job; |
||||
import com.fr.third.org.quartz.JobDataMap; |
||||
import com.fr.third.org.quartz.JobExecutionContext; |
||||
import com.fr.third.org.quartz.JobExecutionException; |
||||
|
||||
/* |
||||
* <p> Built in job for executing native executables in a separate process.</p> |
||||
* |
||||
* If PROP_WAIT_FOR_PROCESS is true, then the Integer exit value of the process |
||||
* will be saved as the job execution result in the JobExecutionContext. |
||||
* |
||||
* @see #PROP_COMMAND |
||||
* @see #PROP_PARAMETERS |
||||
* @see #PROP_WAIT_FOR_PROCESS |
||||
* @see #PROP_CONSUME_STREAMS |
||||
* |
||||
* @author Matthew Payne |
||||
* @author James House |
||||
* @author Steinar Overbeck Cook |
||||
* @date Sep 17, 2003 @Time: 11:27:13 AM |
||||
*/ |
||||
public class NativeJob implements Job { |
||||
|
||||
private final Log log = LogFactory.getLog(getClass()); |
||||
|
||||
/* |
||||
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Constants. |
||||
* |
||||
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
/** |
||||
* Required parameter that specifies the name of the command (executable) |
||||
* to be ran. |
||||
*/ |
||||
public static final String PROP_COMMAND = "command"; |
||||
|
||||
/** |
||||
* Optional parameter that specifies the parameters to be passed to the |
||||
* executed command. |
||||
*/ |
||||
public static final String PROP_PARAMETERS = "parameters"; |
||||
|
||||
|
||||
/** |
||||
* Optional parameter (value should be 'true' or 'false') that specifies |
||||
* whether the job should wait for the execution of the native process to |
||||
* complete before it completes. |
||||
* |
||||
* <p>Defaults to <code>true</code>.</p> |
||||
*/ |
||||
public static final String PROP_WAIT_FOR_PROCESS = "waitForProcess"; |
||||
|
||||
/** |
||||
* Optional parameter (value should be 'true' or 'false') that specifies |
||||
* whether the spawned process's stdout and stderr streams should be |
||||
* consumed. If the process creates output, it is possible that it might |
||||
* 'hang' if the streams are not consumed. |
||||
* |
||||
* <p>Defaults to <code>false</code>.</p> |
||||
*/ |
||||
public static final String PROP_CONSUME_STREAMS = "consumeStreams"; |
||||
|
||||
|
||||
/* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
* |
||||
* Interface. |
||||
* |
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
*/ |
||||
|
||||
public void execute(JobExecutionContext context) |
||||
throws JobExecutionException { |
||||
|
||||
JobDataMap data = context.getMergedJobDataMap(); |
||||
|
||||
String command = data.getString(PROP_COMMAND); |
||||
|
||||
String parameters = data.getString(PROP_PARAMETERS); |
||||
|
||||
if (parameters == null) { |
||||
parameters = ""; |
||||
} |
||||
|
||||
boolean wait = true; |
||||
if(data.containsKey(PROP_WAIT_FOR_PROCESS)) { |
||||
wait = data.getBooleanValue(PROP_WAIT_FOR_PROCESS); |
||||
} |
||||
boolean consumeStreams = false; |
||||
if(data.containsKey(PROP_CONSUME_STREAMS)) { |
||||
consumeStreams = data.getBooleanValue(PROP_CONSUME_STREAMS); |
||||
} |
||||
|
||||
Integer exitCode = this.runNativeCommand(command, parameters, wait, consumeStreams); |
||||
context.setResult(exitCode); |
||||
|
||||
} |
||||
|
||||
protected Log getLog() { |
||||
return log; |
||||
} |
||||
|
||||
private Integer runNativeCommand(String command, String parameters, boolean wait, boolean consumeStreams) throws JobExecutionException { |
||||
|
||||
String[] cmd = null; |
||||
String[] args = new String[2]; |
||||
Integer result = null; |
||||
args[0] = command; |
||||
args[1] = parameters; |
||||
|
||||
|
||||
try { |
||||
//with this variable will be done the swithcing
|
||||
String osName = System.getProperty("os.name"); |
||||
|
||||
//only will work with Windows NT
|
||||
if (osName.equals("Windows NT")) { |
||||
if (cmd == null) { |
||||
cmd = new String[args.length + 2]; |
||||
} |
||||
cmd[0] = "cmd.exe"; |
||||
cmd[1] = "/C"; |
||||
for (int i = 0; i < args.length; i++) { |
||||
cmd[i + 2] = args[i]; |
||||
} |
||||
} else if (osName.equals("Windows 95")) { //only will work with Windows 95
|
||||
if (cmd == null) { |
||||
cmd = new String[args.length + 2]; |
||||
} |
||||
cmd[0] = "command.com"; |
||||
cmd[1] = "/C"; |
||||
for (int i = 0; i < args.length; i++) { |
||||
cmd[i + 2] = args[i]; |
||||
} |
||||
} else if (osName.equals("Windows 2003")) { //only will work with Windows 2003
|
||||
if (cmd == null) { |
||||
cmd = new String[args.length + 2]; |
||||
} |
||||
cmd[0] = "cmd.exe"; |
||||
cmd[1] = "/C"; |
||||
|
||||
for (int i = 0; i < args.length; i++) { |
||||
cmd[i + 2] = args[i]; |
||||
} |
||||
} else if (osName.equals("Windows 2000")) { //only will work with Windows 2000
|
||||
if (cmd == null) { |
||||
cmd = new String[args.length + 2]; |
||||
} |
||||
cmd[0] = "cmd.exe"; |
||||
cmd[1] = "/C"; |
||||
|
||||
for (int i = 0; i < args.length; i++) { |
||||
cmd[i + 2] = args[i]; |
||||
} |
||||
} else if (osName.equals("Windows XP")) { //only will work with Windows XP
|
||||
if (cmd == null) { |
||||
cmd = new String[args.length + 2]; |
||||
} |
||||
cmd[0] = "cmd.exe"; |
||||
cmd[1] = "/C"; |
||||
|
||||
for (int i = 0; i < args.length; i++) { |
||||
cmd[i + 2] = args[i]; |
||||
} |
||||
} else if (osName.equals("Linux")) { |
||||
if (cmd == null) { |
||||
cmd = new String[3]; |
||||
} |
||||
cmd[0] = "/bin/sh"; |
||||
cmd[1] = "-c"; |
||||
cmd[2] = args[0] + " " + args[1]; |
||||
} else { // try this...
|
||||
cmd = args; |
||||
} |
||||
|
||||
Runtime rt = Runtime.getRuntime(); |
||||
// Executes the command
|
||||
getLog().info("About to run" + cmd[0] + " " + cmd[1] + " " + (cmd.length>2 ? cmd[2] : "") + " ..."); |
||||
Process proc = rt.exec(cmd); |
||||
// Consumes the stdout from the process
|
||||
StreamConsumer stdoutConsumer = new StreamConsumer(proc.getInputStream(), "stdout"); |
||||
|
||||
// Consumes the stderr from the process
|
||||
if(consumeStreams) { |
||||
StreamConsumer stderrConsumer = new StreamConsumer(proc.getErrorStream(), "stderr"); |
||||
stdoutConsumer.start(); |
||||
stderrConsumer.start(); |
||||
} |
||||
|
||||
if(wait) { |
||||
result = new Integer(proc.waitFor()); |
||||
} |
||||
// any error message?
|
||||
|
||||
} catch (Exception x) { |
||||
throw new JobExecutionException("Error launching native command: ", x, false); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Consumes data from the given input stream until EOF and prints the data to stdout |
||||
* |
||||
* @author cooste |
||||
* @author jhouse |
||||
*/ |
||||
class StreamConsumer extends Thread { |
||||
InputStream is; |
||||
String type; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public StreamConsumer(InputStream inputStream, String type) { |
||||
this.is = inputStream; |
||||
this.type = type; |
||||
} |
||||
|
||||
/** |
||||
* Runs this object as a separate thread, printing the contents of the InputStream |
||||
* supplied during instantiation, to either stdout or stderr |
||||
*/ |
||||
public void run() { |
||||
BufferedReader br = null; |
||||
try { |
||||
br = new BufferedReader(new InputStreamReader(is)); |
||||
String line = null; |
||||
|
||||
while ((line = br.readLine()) != null) { |
||||
if(type.equalsIgnoreCase("stderr")) { |
||||
getLog().warn(type + ">" + line); |
||||
} else { |
||||
getLog().info(type + ">" + line); |
||||
} |
||||
} |
||||
} catch (IOException ioe) { |
||||
getLog().error("Error consuming " + type + " stream of spawned process.", ioe); |
||||
} finally { |
||||
if(br != null) { |
||||
try { br.close(); } catch(Exception ignore) {} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue