/*==========================================================================*\ | $Id: BatchHandlerManager.java,v 1.3 2010/10/15 00:39:16 stedwar2 Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2008 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.batchprocessor; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Constructor; import org.apache.log4j.Logger; import org.webcat.core.Application; import org.webcat.core.Subsystem; import org.webcat.core.SubsystemManager; import org.webcat.core.WCProperties; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eoaccess.EOUtilities; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSData; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation.NSPropertyListSerialization; //------------------------------------------------------------------------- /** * <p> * A singleton that manages the batch handlers registered by each subsystem. * In order that subsystems do not need to depend on the BatchProcessor * subsystem directly, there is not a formal interface that a batch handler * must implement. Instead, the class registered as a batch handler for a * specific entity must implement a constructor with the following signature: * </p> * <dl> * <dt>SomeBatchHandler(WCProperties properies, File workingDir)</dt> * <dd><code>properties</code> represents the batch properties file. * <code>workingDir</code> is the working directory of the batch job, where * files can be copied/stored if necessary.</dd> * <p> * A new instance of the handler class is instantiated for each batch job, so * it may safely retain state if it wishes. The class may implement the * following methods (all are optional). The type <code>T</code> in the * parameter lists is the strongly-typed object of the appropriate entity type; * for example, if the handler is for Submission objects, then <code>T</code> * would be the class <code>Submission</code>. * </p> * <dl> * <dt>boolean shouldProcessItem(T item)</dt> * <dd>Gives a batch handler an opportunity to skip an item if it is malformed * in some way.</dd> * <dt>void setUpItem(T item)</dt> * <dd>Performs any set-up actions required to process this item in the batch, * such as copying files to the working area or writing properties into the * properties file.</dd> * <dt>void tearDownItem(T item)</dt> * <dd>Performs any necessary cleanup from the setUpItem method.</dd> * </dl> * * @author Tony Allevato * @author Last changed by $Author: stedwar2 $ * @version $Revision: 1.3 $, $Date: 2010/10/15 00:39:16 $ */ public class BatchHandlerManager { //~ Constructors .......................................................... // ---------------------------------------------------------- private BatchHandlerManager() { handlers = new NSMutableDictionary<String, Class<?>>(); SubsystemManager subsystemManager = Application.wcApplication().subsystemManager(); for (Subsystem subsystem : subsystemManager.subsystems()) { try { loadHandlersFromSubsystem(subsystem); } catch (IOException e) { log.warn("Error loading batch handlers from subsystem " + subsystem.name(), e); } } } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Gets the single instance of the BatchInjectionManager class. * * @return the instance */ public static BatchHandlerManager getInstance() { if (instance == null) { instance = new BatchHandlerManager(); } return instance; } // ---------------------------------------------------------- public BatchHandlerProxy createHandler(String entityName, EOEditingContext ec, WCProperties properties, File workingDir) { Class<?> handlerClass = handlers.objectForKey(entityName); EOEntity entity = EOUtilities.entityNamed(ec, entityName); Class<?> entityClass = null; try { entityClass = Class.forName(entity.className()); } catch (ClassNotFoundException e) { log.error("Could not find class for entity named " + entityName + "; this should not happen."); return null; } return new BatchHandlerProxy(handlerClass, entityClass, properties, workingDir); } // ---------------------------------------------------------- private void loadHandlersFromSubsystem(Subsystem subsystem) throws IOException { File file = new File(subsystem.myResourcesDir(), BATCH_HANDLERS_PLIST_FILENAME); if (!file.exists()) { return; } @SuppressWarnings("unchecked") NSDictionary<String, Object> plist = (NSDictionary<String, Object>) NSPropertyListSerialization.propertyListFromData( new NSData(new FileInputStream(file), 0), "UTF-8"); for (String entityName : plist.allKeys()) { String handlerClassName = (String) plist.objectForKey(entityName); Class<?> handlerClass = null; try { handlerClass = Class.forName(handlerClassName); } catch (ClassNotFoundException e) { log.error("Could not find the class " + handlerClassName); } if (handlerClass != null) { try { getHandlerConstructor(handlerClass); handlers.setObjectForKey(handlerClass, entityName); } catch (Exception e) { log.error("The class " + handlerClassName + " does not implement a constructor with the " + "signature (WCProperties, WCFile), or it is not " + "accessible."); } } } } // ---------------------------------------------------------- /*package*/ static Constructor<?> getHandlerConstructor( Class<?> handlerClass ) throws SecurityException, NoSuchMethodException { return handlerClass.getConstructor(WCProperties.class, File.class); } //~ Static/instance variables ............................................. private static BatchHandlerManager instance; private NSMutableDictionary<String, Class<?>> handlers; private static final String BATCH_HANDLERS_PLIST_FILENAME = "BatchHandlers.plist"; private static final Logger log = Logger.getLogger( BatchHandlerManager.class); }