/** * Copyright 2011 meltmedia * * 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 org.xchain.framework.quartz; import java.util.HashMap; import javax.xml.namespace.QName; import org.apache.commons.jxpath.JXPathContext; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobDataMap; import org.xchain.Command; import org.xchain.CatalogNotFoundException; import org.xchain.CommandNotFoundException; import org.xchain.framework.factory.CatalogFactory; import org.xchain.framework.jxpath.QNameVariables; /** * <p>A Quartz job that executes an XChain command. This job takes takes the following entries in the <job-data-map>:</p> * <table border="1"> * <tr> * <th align="left">Key</th> * <th align="left">Type</th> * <th align="left">Description</th> * </tr> * <tr> * <td>catalog-system-id</td> * <td>URL</td> * <td>The URL of the catalog that contains the command.</td> * </tr> * <tr> * <td>command-name</td> * <td>QName</td> * <td>The QName of the command to execute. See the {@link javax.xml.namespace.QName#valueOf(String)} method for the format of this field.</td> * </tr> * </table> * * <p>Example Configuration:<p/> * <pre> * <job-detail> * <name>JOB_NAME</name> * <group>JOB_GROUP</group> * <description>JOB_DESCRIPTION</description> * <job-class>org.xchain.framework.quartz.CommandJob</job-class> * <job-data-map allows-transient-data="false"> * <entry> * <key>catalog-system-id</key> * <value>URL</value> * </entry> * <entry> * <key>command-name</key> * <value>{NAMESPACE_URI}LOCAL_NAME</value> * </entry> * </job-data-map> * </job-detail> * </pre> * * @author Christian Trimble * * @see javax.xml.namespace.QName#valueOf(String) */ public class CommandJob extends ThreadLifecycleJob { /** * <p>The key of the job data map entry for the command name.</p> */ public static final String COMMAND_NAME = "command-name"; /** * <p>The key of the job data map entry for the catalog system id.</p> */ public static final String CATALOG_SYSTEM_ID = "catalog-system-id"; /** * <p>Loads the job specified in the job data map and executes it.</p> * @param jobContext the context of the job execution. */ public void executeInThreadLifecycle( JobExecutionContext jobContext ) throws JobExecutionException { JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap(); String catalogName = getCatalogSystemId(jobContext); QName commandName = getCommandName(jobContext); Command command = getCommand(catalogName, commandName); JXPathContext commandContext = createJXPathContext( jobContext ); try { command.execute(commandContext); } catch( Exception e ) { throw new JobExecutionException("The command '"+commandName+"' in the catalog '"+catalogName+"' threw an exception.", e); } } /** * <p>Creates a JXPathContext for a JobExecutionContext.</p> * @param jobContext the job execution context for which the jxpath context will be created. * @return the JXPathContext created for the job execution context. */ private JXPathContext createJXPathContext( JobExecutionContext jobContext ) { JXPathContext commandContext = JXPathContext.newContext( new HashMap() ); ((QNameVariables)commandContext.getVariables()).declareVariable( new QName( Constants.LIFECYCLE_URI, Constants.JOB_EXECUTION_CONTEXT ), jobContext ); return commandContext; } /** * <p>Gets the command name out of the JobExecutionContext's JobDataMap.</p> */ private QName getCommandName( JobExecutionContext jobContext ) throws JobExecutionException { JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap(); // get the name of the command. String commandNameString = dataMap.getString(COMMAND_NAME); QName commandName = null; if( commandNameString == null ) { throw new JobExecutionException("The command name was not specified in the job data map key 'command'."); } try { commandName = QName.valueOf(commandNameString); } catch( Exception e ) { throw new JobExecutionException("The command name '"+commandNameString+"' is not a valid QName.", e); } return commandName; } /** * <p>Gets the catalog name from the JobExecutionContext's JobDataMap.</p> */ private String getCatalogSystemId( JobExecutionContext jobContext ) throws JobExecutionException { JobDataMap dataMap = jobContext.getJobDetail().getJobDataMap(); // get the name of the catalog. String catalogName = dataMap.getString(CATALOG_SYSTEM_ID); if( catalogName == null ) { throw new JobExecutionException("The catalog name was not specifed in the job data map key 'catalog'."); } return catalogName; } /** * <p>Gets the command for the catalog name and command name.</p> */ private Command getCommand( String catalogName, QName commandName ) throws JobExecutionException { Command command = null; try { command = CatalogFactory.getInstance().getCatalog(catalogName).getCommand(commandName); } catch( CatalogNotFoundException catalogNotFound ) { throw new JobExecutionException("The catalog '"+catalogName+"' could not be found.", catalogNotFound ); } catch( CommandNotFoundException commandNotFound ) { throw new JobExecutionException("The command '"+commandName+"' in the catalog '"+catalogName+"' could not be found.", commandNotFound); } catch( Exception e ) { throw new JobExecutionException("The command '"+commandName+"' in the catalog '"+catalogName+"' could not be loaded, due to an exception.", e); } return command; } }