/************************************************************************* * * ADOBE CONFIDENTIAL __________________ * * [2002] - [2007] Adobe Systems Incorporated All Rights Reserved. * * NOTICE: All information contained herein is, and remains the property of Adobe Systems Incorporated and its suppliers, if any. The intellectual and technical concepts contained herein are * proprietary to Adobe Systems Incorporated and its suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law. Dissemination of * this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from Adobe Systems Incorporated. **************************************************************************/ package flex.messaging; import flex.messaging.config.ConfigMap; import flex.messaging.config.ConfigurationException; import flex.messaging.log.Log; public abstract class FactoryDestination extends Destination { /** * */ private static final long serialVersionUID = 1L; private static final String FACTORY = "factory"; private static final String DEFAULT_FACTORY = "java"; // Errors private static int INVALID_FACTORY = 11103; private static int FACTORY_CANNOT_BE_RETURNED = 11118; // FactoryDestination's properties private FlexFactory factory; private String source; private String scope = FlexFactory.SCOPE_REQUEST; // FactoryDestination internal private String factoryId = DEFAULT_FACTORY; private FactoryInstance factoryInstance; private ConfigMap factoryProperties; // -------------------------------------------------------------------------- // // Constructor // // -------------------------------------------------------------------------- /** * Constructs an unmanaged <code>FactoryDestination</code> instance. */ public FactoryDestination() { this(false); } /** * Constructs a <code>FactoryDestination</code> with the indicated management. * * @param enableManagement * <code>true</code> if the <code>FactoryDestination</code> is manageable; otherwise <code>false</code>. */ public FactoryDestination(boolean enableManagement) { super(enableManagement); } // -------------------------------------------------------------------------- // // Initialize, validate, start, and stop methods. // // -------------------------------------------------------------------------- /** * Initializes the <code>FactoryDestination</code> with the properties. * * @param properties * Properties for the <code>FactoryDestination</code>. */ @Override public void initialize(String id, ConfigMap properties) { super.initialize(id, properties); if (properties == null || properties.size() == 0) return; // Need to cache this for later. TODO: We shouldn't need to do this. factoryProperties = properties; factoryId = properties.getPropertyAsString(FACTORY, factoryId); scope = properties.getPropertyAsString(FlexFactory.SCOPE, scope); source = properties.getPropertyAsString(FlexFactory.SOURCE, source); if (source == null) source = getId(); } /** * Verifies that the <code>FactoryDestination</code> is in valid state before it is started. */ @Override protected void validate() { if (isValid()) return; super.validate(); if (factory == null) { if (factoryId == null) { factoryId = DEFAULT_FACTORY; } MessageBroker broker = getService().getMessageBroker(); FlexFactory f = broker.getFactory(factoryId); if (f == null) { ConfigurationException ex = new ConfigurationException(); ex.setMessage(INVALID_FACTORY, new Object[] { getId(), factoryId }); throw ex; } factory = f; } if (scope == null) scope = FlexFactory.SCOPE_REQUEST; if (source == null) source = getId(); } // -------------------------------------------------------------------------- // // Public Getters and Setters for Destination properties // // -------------------------------------------------------------------------- /** * Returns the factory of the <code>FactoryDestination</code>. Before a valid <code>FlexFactory</code> can be returned, <code>MessageBroker</code> and hence <code>Service</code> of the * <code>Destination</code> has to be set. */ public FlexFactory getFactory() { if (factory == null) { if (factoryId == null) { factoryId = DEFAULT_FACTORY; } if (getService() == null) { // Factory cannot be returned without ''{0}'' set. ConfigurationException ex = new ConfigurationException(); ex.setMessage(FACTORY_CANNOT_BE_RETURNED, new Object[] { "Service" }); throw ex; } if (getService().getMessageBroker() == null) { // Factory cannot be returned without ''{0}'' set. ConfigurationException ex = new ConfigurationException(); ex.setMessage(FACTORY_CANNOT_BE_RETURNED, new Object[] { "MessageBroker" }); throw ex; } MessageBroker broker = getService().getMessageBroker(); FlexFactory f = broker.getFactory(factoryId); if (f == null) { ConfigurationException ex = new ConfigurationException(); ex.setMessage(INVALID_FACTORY, new Object[] { getId(), factoryId }); throw ex; } factory = f; } return factory; } /** * Sets the factory of the <code>FactoryDestination</code>. <code>MessageBroker</code> has to know the factory before it can be assigned to the destination. * * @param id * The id of the factory. */ public void setFactory(String id) { if (isStarted()) { MessageBroker broker = getService().getMessageBroker(); FlexFactory factory = broker.getFactory(id); if (factory == null) { ConfigurationException ex = new ConfigurationException(); ex.setMessage(INVALID_FACTORY, new Object[] { getId(), factory }); throw ex; } setFactory(factory); } factoryId = id; } /** * Sets the factory of the <code>FactoryDestination</code>. * * @param factory */ public void setFactory(FlexFactory factory) { this.factory = factory; } /** * Returns the <code>FactoryInstance</code>. <code>FactoryInstance</code> stores configuration state used for retrieving an instance from the factory. This needs to be called after calling * <code>setSource</code> and <code>setScope</code> methods. * */ public FactoryInstance getFactoryInstance() { // This is needed for HibernateAssembler return getFactoryInstance(factoryProperties); } /** * Returns a <code>FactoryInstance</code> using the properties passed in. * * @param properties * Properties to be used while creating the <code>FactoryInstance</code>. */ private FactoryInstance getFactoryInstance(ConfigMap properties) { // Automatically create a factory instance if not already set if (factoryInstance == null) factoryInstance = createFactoryInstance(properties); return factoryInstance; } /** * Creates a factory instance using the properties passed in. * * @param properties * Properties to be used while creating the <code>FactoryInstance</code>. */ private FactoryInstance createFactoryInstance(ConfigMap properties) { if (properties == null) properties = new ConfigMap(); properties.put(FlexFactory.SOURCE, source); properties.put(FlexFactory.SCOPE, scope); FactoryInstance factoryInstance = getFactory().createFactoryInstance(getId(), properties); return factoryInstance; } /** * Returns the scope of the <code>FactoryDestination</code>. * * @return scope of the <code>FactoryDestination</code>. */ public String getScope() { return scope; } /** * Sets the scope of the <code>FactoryDestination</code> that is used in <code>FactoryInstance</code> creation. Scope cannot be changed to and from application scope once * <code>FactoryInstance</code> is initialized. * * @param scope */ public void setScope(String scope) { if (factoryInstance != null) { if (FlexFactory.SCOPE_APPLICATION.equals(this.scope) && !FlexFactory.SCOPE_APPLICATION.equals(scope)) { if (Log.isWarn()) Log.getLogger(getLogCategory()).warn("Current scope is " + FlexFactory.SCOPE_APPLICATION + " and it cannot be changed to " + scope + " once factory instance is initialized."); return; } else if (!FlexFactory.SCOPE_APPLICATION.equals(this.scope) && FlexFactory.SCOPE_APPLICATION.equals(scope)) { if (Log.isWarn()) Log.getLogger(getLogCategory()).warn("Current scope is " + this.scope + " and it cannot be changed to " + FlexFactory.SCOPE_APPLICATION + " once factory instance is initialized."); return; } factoryInstance.setScope(scope); } this.scope = scope; } /** * Gets the source of the <code>FactoryDestination</code>. * * @return the source of the <code>FactoryDestination</code>. */ public String getSource() { return source; } /** * Sets the source of the <code>FactoryDestination</code> that is used in <code>FactoryInstance</code> creation. Source cannot be changed once <code>FactoryInstance</code> is initialized and the * scope is application. * * @param source */ public void setSource(String source) { if (factoryInstance != null) { if (FlexFactory.SCOPE_APPLICATION.equals(scope)) { if (Log.isWarn()) Log.getLogger(getLogCategory()).warn("Source of the destination cannot be changed once " + "factory instance is already initialized and it has " + FlexFactory.SCOPE_APPLICATION + " scope"); return; } factoryInstance.setSource(source); } this.source = source; } /** * This method first calls stop on its superclass <code>Destination</code> and then removes any assemblers from the ServletContext or Session that are ready for removal. If an assembler is only * used by a single destination (attribute-id==destination-id) then it is removed. If an assembler is shared across destinations, (attribute-id!=destination-id) then it is only removed if its * reference count (maintained in <code>MessageBroker</code>) is down to zero */ @Override public void stop() { super.stop(); // destroy factory instance to free up resources if (factory != null && (factory instanceof DestructibleFlexFactory)) ((DestructibleFlexFactory) factory).destroyFactoryInstance(factoryInstance); } }