| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 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 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 id the factory id |
| * @param properties Properties for the <code>FactoryDestination</code>. |
| */ |
| 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(); |
| |
| if (factory != null) |
| factory.initialize(getId(), factoryProperties); |
| } |
| |
| /** |
| * Verifies that the <code>FactoryDestination</code> is in valid state before |
| * it is started. |
| */ |
| 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. |
| * @return FlexFactory the FlexFactory object |
| */ |
| 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 the FlexFactory object |
| */ |
| 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. |
| * @return FactoryInstance current FactoryInstance object |
| */ |
| 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 the 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 the source string |
| */ |
| 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 |
| */ |
| public void stop() |
| { |
| if (isStarted()) |
| { |
| super.stop(); |
| // destroy factory instance to free up resources |
| if (factory != null && (factory instanceof DestructibleFlexFactory)) |
| ((DestructibleFlexFactory)factory).destroyFactoryInstance(factoryInstance); |
| } |
| else |
| { |
| super.stop(); |
| } |
| } |
| } |