Commits

jhouse  committed 3253569

Merged Quartz 1.4.4 changes.

git-svn-id: http://svn.opensymphony.com/svn/quartz/trunk@3069f7d36a-ea1c-0410-88ea-9fd03e4c9665

  • Participants
  • Parent commits 7544f01

Comments (0)

Files changed (18)

File quartz_1x/docs/dbTables/tables_postgres.sql

     JOB_GROUP VARCHAR(80) NOT NULL,
     DESCRIPTION VARCHAR(120) NULL,
     JOB_CLASS_NAME   VARCHAR(128) NOT NULL, 
-    IS_DURABLE VARCHAR(1) NOT NULL,
-    IS_VOLATILE VARCHAR(1) NOT NULL,
-    IS_STATEFUL VARCHAR(1) NOT NULL,
-    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+    IS_DURABLE BOOL NOT NULL,
+    IS_VOLATILE BOOL NOT NULL,
+    IS_STATEFUL BOOL NOT NULL,
+    REQUESTS_RECOVERY BOOL NOT NULL,
     JOB_DATA BYTEA NULL,
     PRIMARY KEY (JOB_NAME,JOB_GROUP)
 );
     TRIGGER_GROUP VARCHAR(80) NOT NULL,
     JOB_NAME  VARCHAR(80) NOT NULL, 
     JOB_GROUP VARCHAR(80) NOT NULL,
-    IS_VOLATILE VARCHAR(1) NOT NULL,
+    IS_VOLATILE BOOL NOT NULL,
     DESCRIPTION VARCHAR(120) NULL,
     NEXT_FIRE_TIME BIGINT NULL,
     PREV_FIRE_TIME BIGINT NULL,
     ENTRY_ID VARCHAR(95) NOT NULL,
     TRIGGER_NAME VARCHAR(80) NOT NULL,
     TRIGGER_GROUP VARCHAR(80) NOT NULL,
-    IS_VOLATILE VARCHAR(1) NOT NULL,
+    IS_VOLATILE BOOL NOT NULL,
     INSTANCE_NAME VARCHAR(80) NOT NULL,
     FIRED_TIME BIGINT NOT NULL,
     STATE VARCHAR(16) NOT NULL,
     JOB_NAME VARCHAR(80) NULL,
     JOB_GROUP VARCHAR(80) NULL,
-    IS_STATEFUL VARCHAR(1) NULL,
-    REQUESTS_RECOVERY VARCHAR(1) NULL,
+    IS_STATEFUL BOOL NULL,
+    REQUESTS_RECOVERY BOOL NULL,
     PRIMARY KEY (ENTRY_ID)
 );
 

File quartz_1x/docs/dbTables/tables_postgres7.sql

+# Thanks to Patrick Lightbody for submitting this...
+#
+# In your Quartz properties file, you'll need to set 
+# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostreSQLDelegate
+
+drop table qrtz_job_listeners;
+drop table qrtz_trigger_listeners;
+drop table qrtz_fired_triggers;
+DROP TABLE QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE QRTZ_SCHEDULER_STATE;
+DROP TABLE QRTZ_LOCKS;
+drop table qrtz_simple_triggers;
+drop table qrtz_cron_triggers;
+DROP TABLE QRTZ_BLOB_TRIGGERS;
+drop table qrtz_triggers;
+drop table qrtz_job_details;
+drop table qrtz_calendars;
+
+CREATE TABLE qrtz_job_details
+  (
+    JOB_NAME  VARCHAR(80) NOT NULL,
+    JOB_GROUP VARCHAR(80) NOT NULL,
+    DESCRIPTION VARCHAR(120) NULL,
+    JOB_CLASS_NAME   VARCHAR(128) NOT NULL, 
+    IS_DURABLE VARCHAR(1) NOT NULL,
+    IS_VOLATILE VARCHAR(1) NOT NULL,
+    IS_STATEFUL VARCHAR(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+    JOB_DATA BYTEA NULL,
+    PRIMARY KEY (JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE qrtz_job_listeners
+  (
+    JOB_NAME  VARCHAR(80) NOT NULL, 
+    JOB_GROUP VARCHAR(80) NOT NULL,
+    JOB_LISTENER VARCHAR(80) NOT NULL,
+    PRIMARY KEY (JOB_NAME,JOB_GROUP,JOB_LISTENER),
+    FOREIGN KEY (JOB_NAME,JOB_GROUP) 
+	REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP) 
+);
+
+CREATE TABLE qrtz_triggers
+  (
+    TRIGGER_NAME VARCHAR(80) NOT NULL,
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    JOB_NAME  VARCHAR(80) NOT NULL, 
+    JOB_GROUP VARCHAR(80) NOT NULL,
+    IS_VOLATILE VARCHAR(1) NOT NULL,
+    DESCRIPTION VARCHAR(120) NULL,
+    NEXT_FIRE_TIME BIGINT NULL,
+    PREV_FIRE_TIME BIGINT NULL,
+    TRIGGER_STATE VARCHAR(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR(8) NOT NULL,
+    START_TIME BIGINT NOT NULL,
+    END_TIME BIGINT NULL,
+    CALENDAR_NAME VARCHAR(80) NULL,
+    MISFIRE_INSTR SMALLINT NULL,
+    PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (JOB_NAME,JOB_GROUP) 
+	REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP) 
+);
+
+CREATE TABLE qrtz_simple_triggers
+  (
+    TRIGGER_NAME VARCHAR(80) NOT NULL,
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    REPEAT_COUNT BIGINT NOT NULL,
+    REPEAT_INTERVAL BIGINT NOT NULL,
+    TIMES_TRIGGERED BIGINT NOT NULL,
+    PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_cron_triggers
+  (
+    TRIGGER_NAME VARCHAR(80) NOT NULL,
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    CRON_EXPRESSION VARCHAR(80) NOT NULL,
+    TIME_ZONE_ID VARCHAR(80),
+    PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_blob_triggers
+  (
+    TRIGGER_NAME VARCHAR(80) NOT NULL,
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    BLOB_DATA BYTEA NULL,
+    PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 
+        REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_trigger_listeners
+  (
+    TRIGGER_NAME  VARCHAR(80) NOT NULL, 
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    TRIGGER_LISTENER VARCHAR(80) NOT NULL,
+    PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_LISTENER),
+    FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+
+CREATE TABLE qrtz_calendars
+  (
+    CALENDAR_NAME  VARCHAR(80) NOT NULL, 
+    CALENDAR BYTEA NOT NULL,
+    PRIMARY KEY (CALENDAR_NAME)
+);
+
+
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    TRIGGER_GROUP  VARCHAR(80) NOT NULL, 
+    PRIMARY KEY (TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_fired_triggers 
+  (
+    ENTRY_ID VARCHAR(95) NOT NULL,
+    TRIGGER_NAME VARCHAR(80) NOT NULL,
+    TRIGGER_GROUP VARCHAR(80) NOT NULL,
+    IS_VOLATILE VARCHAR(1) NOT NULL,
+    INSTANCE_NAME VARCHAR(80) NOT NULL,
+    FIRED_TIME BIGINT NOT NULL,
+    STATE VARCHAR(16) NOT NULL,
+    JOB_NAME VARCHAR(80) NULL,
+    JOB_GROUP VARCHAR(80) NULL,
+    IS_STATEFUL VARCHAR(1) NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NULL,
+    PRIMARY KEY (ENTRY_ID)
+);
+
+CREATE TABLE qrtz_scheduler_state 
+  (
+    INSTANCE_NAME VARCHAR(80) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT NOT NULL,
+    CHECKIN_INTERVAL BIGINT NOT NULL,
+    RECOVERER VARCHAR(80) NULL,
+    PRIMARY KEY (INSTANCE_NAME)
+);
+
+CREATE TABLE qrtz_locks
+  (
+    LOCK_NAME  VARCHAR(40) NOT NULL, 
+    PRIMARY KEY (LOCK_NAME)
+);
+
+
+INSERT INTO qrtz_locks values('TRIGGER_ACCESS');
+INSERT INTO qrtz_locks values('JOB_ACCESS');
+INSERT INTO qrtz_locks values('CALENDAR_ACCESS');
+INSERT INTO qrtz_locks values('STATE_ACCESS');
+INSERT INTO qrtz_locks values('MISFIRE_ACCESS');
+
+commit;
+

File quartz_1x/releaseNotes.txt

 
 
 ================================================================================
-Changes in version 1.5.0  (since version 1.4.3)
+Changes in version 1.5.0  (since version 1.4.4)
 ================================================================================
 
 1- Copyright and license of Quartz switched to OpenSymphony
+
+2- 
    
-2- Removed previously deprecated org.quartz.helpers.NoOpJob.  It was replaced 
+3- Removed previously deprecated org.quartz.helpers.NoOpJob.  It was replaced 
    by org.quartz.jobs.NoOpJob
    
 

File quartz_1x/src/java/examples/org/quartz/examples/DumbInterruptableJob.java

 import org.quartz.JobExecutionException;
 import org.quartz.UnableToInterruptJobException;
 
-import com.adventnet.utils.Scheduler;
 
 /**
  * <p>

File quartz_1x/src/java/examples/org/quartz/examples/InitJobsTest.java

     public static void schedTest(SchedulerFactory sf) throws Exception {
         Log lg = LogFactory.getLog(InitJobsTest.class);
 
-        lg.info("------- Initializing -------------------");
+        lg.info("------- Initializing ----------------------");
 
         Scheduler sched = sf.getScheduler();
 
         lg.info("------- Initialization Complete -----------");
 
-        lg
-                .info("------- (Not Scheduling any Jobs - relying on XML definitions --");
+        lg.info("------- (Not Scheduling any Jobs - relying on XML definitions --");
 
         lg.info("------- Starting Scheduler ----------------");
 
 
         sched.start();
 
-        lg.info("------- Started Scheduler -----------------");
+        lg.info("------- Started Scheduler ----------------");
 
         lg.info("------- Waiting... -----------------------");
 

File quartz_1x/src/java/main/org/quartz/CronTrigger.java

         calendardayOfWeek = false;
         calendardayOfMonth = false;
 
+        try {
         buildExpression(cronExpression.toUpperCase());
+        } catch(StringIndexOutOfBoundsException sioobe) {
+            throw new ParseException(
+              "Expression string length too short. " + sioobe.toString(), -1);
+        }
+        
         this.cronExpression = cronExpression;
     }
 
 
     protected Date getTime(int sc, int mn, int hr, int dayofmn, int mon) {
         try {
-            Calendar cl = Calendar.getInstance(timeZone);
+            Calendar cl = Calendar.getInstance(getTimeZone());
             //cl.add(Calendar.DAY_OF_MONTH,);
             if (hr >= 0 && hr <= 12) cl.set(Calendar.AM_PM, Calendar.AM);
             if (hr >= 13 && hr <= 23) cl.set(Calendar.AM_PM, Calendar.PM);

File quartz_1x/src/java/main/org/quartz/SimpleTrigger.java

      * </p>
      * 
      * @exception IllegalArgumentException
-     *              if repeatInterval is < 0
+     *              if repeatInterval is <= 0
      */
     public void setRepeatInterval(long repeatInterval) {
         if (repeatInterval < 0)

File quartz_1x/src/java/main/org/quartz/core/QuartzScheduler.java

         if (trigger.getCalendarName() != null) {
             cal = resources.getJobStore().retrieveCalendar(ctxt,
                     trigger.getCalendarName());
+            if(cal == null)
+                throw new SchedulerException(
+                    "Calendar not found: " + trigger.getCalendarName(), 
+                    SchedulerException.ERR_PERSISTENCE_CALENDAR_DOES_NOT_EXIST);
         }
         Date ft = trigger.computeFirstFireTime(cal);
 

File quartz_1x/src/java/main/org/quartz/helpers/TriggerUtils.java

         return java.util.Collections.unmodifiableList(lst);
     }
 
+
+// NOT JDK 1.3 compatable.    
+
+//      Translate a date & time from a users timezone to the another
+//      (probably server) timezone to assist in creating a simple trigger with 
+//      the right date & time.
+/*    
+    public static Date translateTime(Date date, TimeZone src, TimeZone dest) {
+
+        Date newDate = new Date();
+
+        int offset = (dest.getOffset(date.getTime()) - src.getOffset(date
+                .getTime()));
+
+        newDate.setTime(date.getTime() - offset);
+
+        return newDate;
+
+    }
+*/    
 }

File quartz_1x/src/java/main/org/quartz/impl/StdSchedulerFactory.java

                 throw initException;
             }
         } else if (requestedFile != null) {
+            InputStream in = 
+                Thread.currentThread().getContextClassLoader().getResourceAsStream(requestedFile);
+
+            if(in == null) {
             initException = new SchedulerException("Properties file: '"
                     + requestedFile + "' could not be found.");
             throw initException;
+            }
+            
+            propSrc = "specified file: '" + requestedFile + "' in the class resource path.";
+            
+            try {
+                props.load(new BufferedInputStream(in));
+                initialize(overRideWithSysProps(props));
+            } catch (IOException ioe) {
+                initException = new SchedulerException("Properties file: '"
+                        + requestedFile + "' could not be read.", ioe);
+                throw initException;
+            }
+            
         } else {
             propSrc = "default resource file in Quartz package: 'quartz.properties'";
 
         if (cfg != null) return;
         if (initException != null) throw initException;
 
-        BufferedInputStream is = null;
+        InputStream is = null;
         Properties props = new Properties();
 
+        is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+         
         try {
+            if(is != null) {
+                is = new BufferedInputStream(is);
+                propSrc = "the specified file : '" + filename + "' from the class resource path.";
+            }
+            else {
             is = new BufferedInputStream(new FileInputStream(filename));
             propSrc = "the specified file : '" + filename + "'";
+            }
             props.load(is);
         } catch (IOException ioe) {
             initException = new SchedulerException("Properties file: '"

File quartz_1x/src/java/main/org/quartz/impl/calendar/MonthlyCalendar.java

      * @return boolean
      */
     public boolean areAllDaysExcluded() {
-        for (int i = 0; i < 31; i++) {
+        for (int i = 1; i <= 31; i++) {
             if (isDayExcluded(i) == false) return false;
         }
 

File quartz_1x/src/java/main/org/quartz/impl/jdbcjobstore/JobStoreSupport.java

                     if(stat != null && stat.getNextFireTime() == null)
                         removeTrigger(conn, ctxt, trigger.getName(), trigger.getGroup());
                 }
+                else
                 removeTrigger(conn, ctxt, trigger.getName(), trigger.getGroup());
             } else if (triggerInstCode == Trigger.INSTRUCTION_SET_TRIGGER_COMPLETE) {
                 getDelegate().updateTriggerState(conn, trigger.getName(),

File quartz_1x/src/java/main/org/quartz/impl/jdbcjobstore/WebLogicDelegate.java

  * This is a driver delegate for the WebLogic JDBC driver.
  * </p>
  * 
+ * @see org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate
  * @author <a href="mailto:jeff@binaryfeed.org">Jeffrey Wescott</a>
  */
 public class WebLogicDelegate extends StdJDBCDelegate {

File quartz_1x/src/java/main/org/quartz/impl/jdbcjobstore/oracle/OracleDelegate.java

 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
+import java.sql.Blob;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
-import oracle.sql.BLOB;
-
 import org.apache.commons.logging.Log;
 import org.quartz.Calendar;
 import org.quartz.JobDetail;
  * <code>jdbcDriverVersion</code>.
  * </p>
  * 
+ * @see org.quartz.impl.jdbcjobstore.WebLogicDelegate
+ * @see org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate
  * @author James House
  * @author Patrick Lightbody
  */
 
             int res = 0;
 
-            BLOB dbBlob = null;
+            Blob dbBlob = null;
             if (rs.next()) {
-                dbBlob = (BLOB) rs.getBlob(1);
-                dbBlob.putBytes(1, data);
+                dbBlob = writeDataToBlob(rs, 1, data);
             } else {
                 return res;
             }
             int res = 0;
 
             if (rs.next()) {
-                BLOB dbBlob = (BLOB) rs.getBlob(1);
-                dbBlob.putBytes(1, data);
+                Blob dbBlob = writeDataToBlob(rs, 1, data);
                 ps2 = conn.prepareStatement(rtp(UPDATE_ORACLE_JOB_DETAIL_BLOB));
 
                 ps2.setBlob(1, dbBlob);
             rs = ps.executeQuery();
 
             if (rs.next()) {
-                BLOB dbBlob = (BLOB) rs.getBlob(1);
-                dbBlob.putBytes(1, baos.toByteArray());
+                Blob dbBlob = writeDataToBlob(rs, 1, baos.toByteArray());
                 ps2 = conn.prepareStatement(rtp(UPDATE_ORACLE_CALENDAR_BLOB));
 
                 ps2.setBlob(1, dbBlob);
             rs = ps.executeQuery();
 
             if (rs.next()) {
-                BLOB dbBlob = (BLOB) rs.getBlob(1);
-                dbBlob.putBytes(1, baos.toByteArray());
+                Blob dbBlob = writeDataToBlob(rs, 1, baos.toByteArray());
                 ps2 = conn.prepareStatement(rtp(UPDATE_ORACLE_CALENDAR_BLOB));
 
                 ps2.setBlob(1, dbBlob);
             int res = 0;
 
             if (rs.next()) {
-                BLOB dbBlob = (BLOB) rs.getBlob(1);
-                dbBlob.putBytes(1, data);
+                Blob dbBlob = writeDataToBlob(rs, 1, data);
                 ps2 = conn.prepareStatement(rtp(UPDATE_ORACLE_JOB_DETAIL_BLOB));
 
                 ps2.setBlob(1, dbBlob);
         }
     }
 
+    protected Blob writeDataToBlob(ResultSet rs, int column, byte[] data) throws SQLException {
+
+        Blob blob = rs.getBlob(column); // get blob
+
+        if(blob == null) 
+            throw new SQLException("Driver's Blob representation is null!");
+        
+        if (blob instanceof oracle.sql.BLOB) { // is it an oracle blob?
+            ((oracle.sql.BLOB) blob).putBytes(1, data);
+            return blob;
+        } else {
+            throw new SQLException(
+                    "Driver's Blob representation is of an unsupported type: "
+                            + blob.getClass().getName());
+        }
+    }
 }
 
 // EOF

File quartz_1x/src/java/main/org/quartz/impl/jdbcjobstore/oracle/WebLogicOracleDelegate.java

+/*
+ * Copyright James House (c) 2001-2004
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met: 1.
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *  
+ */
+package org.quartz.impl.jdbcjobstore.oracle;
+
+import org.apache.commons.logging.Log;
+
+import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Handle Blobs correctly when Oracle is being used inside of Weblogic 8.1,
+ * as discussed at: http://edocs.bea.com/wls/docs81/jdbc/thirdparty.html#1043705
+ *  
+ * @see org.quartz.impl.jdbcjobstore.WebLogicDelegate
+ * @author James House
+ * @author Igor Fedulov <a href="mailto:igor@fedulov.com">igor@fedulov.com</a>
+ */
+public class WebLogicOracleDelegate extends OracleDelegate {
+
+    /**
+     * <p>
+     * Create new WebLogicOracleDelegate instance.
+     * </p>
+     * 
+     * @param logger
+     *            the logger to use during execution
+     * @param tablePrefix
+     *            the prefix of all table names
+     */
+    public WebLogicOracleDelegate(Log logger, String tablePrefix,
+            String instanceId) {
+        super(logger, tablePrefix, instanceId);
+    }
+
+    /**
+     * <p>
+     * Create new WebLogicOracleDelegate instance.
+     * </p>
+     * 
+     * @param logger
+     *            the logger to use during execution
+     * @param tablePrefix
+     *            the prefix of all table names
+     * @param useProperties
+     *            use java.util.Properties for storage
+     */
+    public WebLogicOracleDelegate(Log logger, String tablePrefix,
+            String instanceId, Boolean useProperties) {
+        super(logger, tablePrefix, instanceId, useProperties);
+    }
+
+    /**
+     * Check for the Weblogic Blob wrapper, and handle accordingly...
+     */
+    protected Blob writeDataToBlob(ResultSet rs, int column, byte[] data) throws SQLException {
+        Blob blob = rs.getBlob(column);
+        
+        if(blob == null) 
+            throw new SQLException("Driver's Blob representation is null!");
+        
+        // handle thin driver's blob
+        if (blob instanceof weblogic.jdbc.vendor.oracle.OracleThinBlob) { 
+            ((weblogic.jdbc.vendor.oracle.OracleThinBlob) blob).putBytes(1, data);
+            return blob;
+        }
+        // (more slowly) handle blob for wrappers of other variations of drivers...
+        else if(blob.getClass().getPackage().getName().startsWith("weblogic.")) { 
+            try {
+                // try to find putBytes method...
+                Method m = blob.getClass().getMethod("putBytes", new Class[] {long.class, byte[].class});
+                m.invoke(blob, new Object[] {new Long(1), data});
+            } catch (Exception e) {
+                throw new SQLException("Unable to find putBytes(long,byte[]) method on blob: " + e);
+            }
+            return blob;
+        }
+        else {
+            return super.writeDataToBlob(rs, column, data);
+        }
+    }
+}

File quartz_1x/src/java/main/org/quartz/jobs/ee/ejb/EJBInvokerJob.java

             params.put(Context.PROVIDER_URL, providerUrl);
         }
 
+        if (params.size() == 0)
+        {
+            return new InitialContext();
+        }
+        else
+        {
         return new InitialContext(params);
     }
+    }    
 }

File quartz_1x/src/java/main/org/quartz/simpl/RAMJobStore.java

      * </p>
      */
     public void releaseAcquiredTrigger(SchedulingContext ctxt, Trigger trigger) {
+        synchronized (triggerLock) {
         TriggerWrapper tw = (TriggerWrapper) triggersByFQN.get(TriggerWrapper
                 .getTriggerNameKey(trigger));
         if (tw != null && tw.state != TriggerWrapper.STATE_COMPLETE
                 && tw.state != TriggerWrapper.STATE_PAUSED) {
             tw.state = TriggerWrapper.STATE_WAITING;
-            synchronized (triggerLock) {
                 timeTriggers.add(tw);
             }
         }
     public TriggerFiredBundle triggerFired(SchedulingContext ctxt,
             Trigger trigger) {
 
+        synchronized (triggerLock) {
         TriggerWrapper tw = (TriggerWrapper) triggersByFQN.get(TriggerWrapper
                 .getTriggerNameKey(trigger));
         // was the trigger deleted since being acquired?
         JobDetail job = bndle.getJobDetail();
 
         if (job.isStateful()) {
-            synchronized (triggerLock) {
                 ArrayList trigs = getTriggerWrappersForJob(job.getName(), job
                         .getGroup());
                 Iterator itr = trigs.iterator();
                     timeTriggers.remove(ttw);
                 }
                 blockedJobs.add(JobWrapper.getJobNameKey(job));
-            }
         } else if (tw.trigger.getNextFireTime() != null) {
             synchronized (triggerLock) {
                 timeTriggers.add(tw);
 
         return bndle;
     }
+    }
 
     /**
      * <p>
      */
     public void triggeredJobComplete(SchedulingContext ctxt, Trigger trigger,
             JobDetail jobDetail, int triggerInstCode) {
+
+        synchronized (triggerLock) {
+
         String jobKey = JobWrapper.getJobNameKey(jobDetail.getName(), jobDetail
                 .getGroup());
         JobWrapper jw = (JobWrapper) jobsByFQN.get(jobKey);
                 JobDataMap newData = jobDetail.getJobDataMap();
                 if (newData != null) newData.clearDirtyFlag();
                 jd.setJobDataMap(newData);
-                synchronized (triggerLock) {
                     blockedJobs.remove(JobWrapper.getJobNameKey(jd));
                     ArrayList trigs = getTriggerWrappersForJob(jd.getName(), jd
                             .getGroup());
                     }
                 }
             }
-        }
         else { // even if it was deleted, there may be cleanup to do
             blockedJobs.remove(JobWrapper.getJobNameKey(jobDetail));
         }
             }
             else if (triggerInstCode == Trigger.INSTRUCTION_SET_TRIGGER_COMPLETE) {
                 tw.state = TriggerWrapper.STATE_COMPLETE;
-                synchronized (triggerLock) {
                     timeTriggers.remove(tw);
-                }
             } else if (triggerInstCode == Trigger.INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE) {
-                synchronized (triggerLock) {
                     ArrayList tws = getTriggerWrappersForJob(trigger
                             .getJobName(), trigger.getJobGroup());
                     Iterator itr = tws.iterator();
         int comp = trig1.trigger.compareTo(trig2.trigger);
 
         if (comp == 0)
-                return trig1.trigger.hashCode() - trig2.trigger.hashCode();
+            return trig1.trigger.getFullName().compareTo(trig2.trigger.getFullName());
 
         return comp;
     }

File quartz_1x/src/java/main/org/quartz/xml/JobSchedulingDataProcessor.java

 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
+
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.commons.beanutils.ConversionException;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.quartz.SimpleTrigger;
-import org.quartz.impl.StdSchedulerFactory;
 import org.quartz.Trigger;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
+
 /**
  * Parses an XML file that declares Jobs and their schedules (Triggers).
  * 
 
     protected Map scheduledJobs = new HashMap();
 
+    protected List jobsToSchedule = new LinkedList();
+    protected List calsToSchedule = new LinkedList();
+
     protected Collection validationExceptions = new ArrayList();
     
     protected Digester digester;
     
     private boolean overWriteExistingJobs = true;
     
+    private ThreadLocal schedLocal = new ThreadLocal();
+    
     /*
      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      * 
         ConvertUtils.register(new TimeZoneConverter(), TimeZone.class);
         
         digester.addSetProperties(TAG_QUARTZ, TAG_OVERWRITE_EXISTING_JOBS, "overWriteExistingJobs");
-        digester.addRuleSet(new CalendarRuleSet(TAG_QUARTZ + "/" + TAG_CALENDAR, "addCalendar"));
+        digester.addRuleSet(new CalendarRuleSet(TAG_QUARTZ + "/" + TAG_CALENDAR, "addCalendarToSchedule"));
         digester.addRuleSet(new CalendarRuleSet("*/" + TAG_BASE_CALENDAR, "setBaseCalendar"));
         digester.addObjectCreate(TAG_QUARTZ + "/" + TAG_JOB, JobSchedulingBundle.class);
         digester.addObjectCreate(TAG_QUARTZ + "/" + TAG_JOB + "/" + TAG_JOB_DETAIL, JobDetail.class);
         digester.addBeanPropertySetter(TAG_QUARTZ + "/" + TAG_JOB + "/" + TAG_TRIGGER + "/" + TAG_CRON + "/" + TAG_CRON_EXPRESSION, "cronExpression");
         digester.addBeanPropertySetter(TAG_QUARTZ + "/" + TAG_JOB + "/" + TAG_TRIGGER + "/" + TAG_CRON + "/" + TAG_TIME_ZONE, "timeZone");
         digester.addSetNext(TAG_QUARTZ + "/" + TAG_JOB + "/" + TAG_TRIGGER + "/" + TAG_CRON, "addTrigger");
-        digester.addSetNext(TAG_QUARTZ + "/" + TAG_JOB, "scheduleJob");
+        digester.addSetNext(TAG_QUARTZ + "/" + TAG_JOB, "addJobToSchedule");
     }
 
     /**
      *          meta data file name.
      */
     public void processFile(String fileName) throws Exception {
-        processFile(fileName, null);
+        processFile(fileName, fileName);
     }
 
     /**
         clearValidationExceptions();
 
         scheduledJobs.clear();
+        jobsToSchedule.clear();
+        calsToSchedule.clear();
 
         getLog().info("Parsing XML file: " + fileName +
                       " with systemId: " + systemId +
     }
 
     /**
-     * Process the xml file in the default location, and schedule all of the
+     * Process the xml file in the given location, and schedule all of the
      * jobs defined within it.
      * 
      * @param fileName
      */
     public void processFileAndScheduleJobs(String fileName, Scheduler sched,
             boolean overWriteExistingJobs) throws Exception {
-        processFile(fileName, null);
+        schedLocal.set(sched);
+        try {
+            processFile(fileName, fileName);
         scheduleJobs(getScheduledJobs(), sched, overWriteExistingJobs);
+        } finally {
+            schedLocal.set(null);
+        }
     }
 
     /**
             boolean overWriteExistingJobs) throws Exception {
         getLog().info("Scheduling " + jobBundles.size() + " parsed jobs.");
 
-        Iterator itr = jobBundles.values().iterator();
+        Iterator itr = calsToSchedule.iterator();
+        while (itr.hasNext()) {
+            CalendarBundle bndle = (CalendarBundle) itr.next();
+            addCalendar(sched, bndle);
+        }
+
+        itr = jobsToSchedule.iterator();
         while (itr.hasNext()) {
             JobSchedulingBundle bndle = (JobSchedulingBundle) itr.next();
             scheduleJob(bndle, sched, overWriteExistingJobs);
      */
     public void scheduleJob(JobSchedulingBundle job)
         throws SchedulerException {
-        scheduleJob(job, StdSchedulerFactory.getDefaultScheduler(), getOverWriteExistingJobs());
+        scheduleJob(job, (Scheduler) schedLocal.get(), getOverWriteExistingJobs());
+    }
+
+    
+    public void addJobToSchedule(JobSchedulingBundle job)
+    {
+        jobsToSchedule.add(job);
+    }
+
+    public void addCalendarToSchedule(CalendarBundle cal)
+    {
+        calsToSchedule.add(cal);
     }
 
     /**
      * @throws SchedulerException if the Calendar cannot be added to the Scheduler, or
      *              there is an internal Scheduler error.
      */
-    public void addCalendar(CalendarBundle calendarBundle) throws SchedulerException {
-        StdSchedulerFactory.getDefaultScheduler().addCalendar(
+    public void addCalendar(Scheduler sched, CalendarBundle calendarBundle) throws SchedulerException {
+        sched.addCalendar(
             calendarBundle.getCalendarName(),
             calendarBundle.getCalendar(),
             calendarBundle.getReplace(),