001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.scheduling.quartz;
018:
019: import org.quartz.SchedulerContext;
020: import org.quartz.spi.TriggerFiredBundle;
021:
022: import org.springframework.beans.BeanWrapper;
023: import org.springframework.beans.BeanWrapperImpl;
024: import org.springframework.beans.MutablePropertyValues;
025:
026: /**
027: * Subclass of {@link AdaptableJobFactory} that also supports Spring-style
028: * dependency injection on bean properties. This is essentially the direct
029: * equivalent of Spring's {@link QuartzJobBean} in the shape of a
030: * Quartz 1.5 {@link org.quartz.spi.JobFactory}.
031: *
032: * <p>Applies scheduler context, job data map and trigger data map entries
033: * as bean property values. If no matching bean property is found, the entry
034: * is by default simply ignored. This is analogous to QuartzJobBean's behavior.
035: *
036: * @author Juergen Hoeller
037: * @since 2.0
038: * @see SchedulerFactoryBean#setJobFactory
039: * @see QuartzJobBean
040: */
041: public class SpringBeanJobFactory extends AdaptableJobFactory implements
042: SchedulerContextAware {
043:
044: private String[] ignoredUnknownProperties;
045:
046: private SchedulerContext schedulerContext;
047:
048: /**
049: * Specify the unknown properties (not found in the bean) that should be ignored.
050: * <p>Default is <code>null</code>, indicating that all unknown properties
051: * should be ignored. Specify an empty array to throw an exception in case
052: * of any unknown properties, or a list of property names that should be
053: * ignored if there is no corresponding property found on the particular
054: * job class (all other unknown properties will still trigger an exception).
055: */
056: public void setIgnoredUnknownProperties(
057: String[] ignoredUnknownProperties) {
058: this .ignoredUnknownProperties = ignoredUnknownProperties;
059: }
060:
061: public void setSchedulerContext(SchedulerContext schedulerContext) {
062: this .schedulerContext = schedulerContext;
063: }
064:
065: /**
066: * Create the job instance, populating it with property values taken
067: * from the scheduler context, job data map and trigger data map.
068: */
069: protected Object createJobInstance(TriggerFiredBundle bundle) {
070: BeanWrapper bw = new BeanWrapperImpl(bundle.getJobDetail()
071: .getJobClass());
072: if (isEligibleForPropertyPopulation(bw.getWrappedInstance())) {
073: MutablePropertyValues pvs = new MutablePropertyValues();
074: if (this .schedulerContext != null) {
075: pvs.addPropertyValues(this .schedulerContext);
076: }
077: pvs
078: .addPropertyValues(bundle.getJobDetail()
079: .getJobDataMap());
080: pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());
081: if (this .ignoredUnknownProperties != null) {
082: for (int i = 0; i < this .ignoredUnknownProperties.length; i++) {
083: String propName = this .ignoredUnknownProperties[i];
084: if (pvs.contains(propName)
085: && !bw.isWritableProperty(propName)) {
086: pvs.removePropertyValue(propName);
087: }
088: }
089: bw.setPropertyValues(pvs);
090: } else {
091: bw.setPropertyValues(pvs, true);
092: }
093: }
094: return bw.getWrappedInstance();
095: }
096:
097: /**
098: * Return whether the given job object is eligible for having
099: * its bean properties populated.
100: * <p>The default implementation ignores {@link QuartzJobBean} instances,
101: * which will inject bean properties themselves.
102: * @param jobObject the job object to introspect
103: * @see QuartzJobBean
104: */
105: protected boolean isEligibleForPropertyPopulation(Object jobObject) {
106: return (!(jobObject instanceof QuartzJobBean));
107: }
108:
109: }
|