/************************************************************************* * * 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.management.runtime.messaging.MessageDestinationControl; import flex.management.runtime.messaging.services.messaging.SubscriptionManagerControl; import flex.management.runtime.messaging.services.messaging.ThrottleManagerControl; import flex.messaging.config.ConfigMap; import flex.messaging.config.ConfigurationException; import flex.messaging.config.DestinationSettings; import flex.messaging.config.NetworkSettings; import flex.messaging.config.ServerSettings; import flex.messaging.config.ThrottleSettings; import flex.messaging.log.Log; import flex.messaging.log.LogCategories; import flex.messaging.services.MessageService; import flex.messaging.services.Service; import flex.messaging.services.messaging.MessagingConstants; import flex.messaging.services.messaging.RemoteSubscriptionManager; import flex.messaging.services.messaging.SubscriptionManager; import flex.messaging.services.messaging.ThrottleManager; /** * A logical reference to a MessageDestination. * * @author neville */ public class MessageDestination extends FactoryDestination { static final long serialVersionUID = -2016911808141319012L; /** Log category for <code>MessageDestination</code>. */ public static final String LOG_CATEGORY = LogCategories.SERVICE_MESSAGE; // Errors private static final int UNSUPPORTED_POLICY = 10124; // Destination properties private ServerSettings serverSettings; // Destination internal private SubscriptionManager subscriptionManager; private RemoteSubscriptionManager remoteSubscriptionManager; private ThrottleManager throttleManager; private MessageDestinationControl controller; // -------------------------------------------------------------------------- // // Constructor // // -------------------------------------------------------------------------- /** * Constructs an unmanaged <code>MessageDestination</code> instance. */ public MessageDestination() { this(false); } /** * Constructs a <code>MessageDestination</code> with the indicated management. * * @param enableManagement * <code>true</code> if the <code>MessageDestination</code> is manageable; otherwise <code>false</code>. */ public MessageDestination(boolean enableManagement) { super(enableManagement); serverSettings = new ServerSettings(); // Managers subscriptionManager = new SubscriptionManager(this); remoteSubscriptionManager = new RemoteSubscriptionManager(this); throttleManager = new ThrottleManager(); } // -------------------------------------------------------------------------- // // Initialize, validate, start, and stop methods. // // -------------------------------------------------------------------------- /** * Initializes the <code>MessageDestination</code> with the properties. If subclasses override, they must call <code>super.initialize()</code>. * * @param id * The id of the destination. * @param properties * Properties for the <code>MessageDestination</code>. */ @Override public void initialize(String id, ConfigMap properties) { super.initialize(id, properties); if (properties == null || properties.size() == 0) return; // Network properties network(properties); // Server properties server(properties); } /** * This method first calls stop on its superclass and then cleans up the SubscriptionManager. */ @Override public void stop() { // Stop all the managers first. subscriptionManager.stop(); remoteSubscriptionManager.stop(); throttleManager.stop(); super.stop(); } // -------------------------------------------------------------------------- // // Public Getters and Setters for Destination properties // // -------------------------------------------------------------------------- /** * Sets the <code>NetworkSettings</code> of the <code>MessageDestination</code>. * * @param networkSettings * The <code>NetworkSettings</code> of the <code>MessageDestination</code> */ @Override public void setNetworkSettings(NetworkSettings networkSettings) { super.setNetworkSettings(networkSettings); // Set throttle and subscription manager settings if needed if (networkSettings.getThrottleSettings() != null) { ThrottleSettings settings = networkSettings.getThrottleSettings(); settings.setDestinationName(getId()); throttleManager.setThrottleSettings(settings); } if (networkSettings.getSubscriptionTimeoutMinutes() > 0) { long subscriptionTimeoutMillis = networkSettings.getSubscriptionTimeoutMinutes() * 60 * 1000; // Convert to millis. subscriptionManager.setSubscriptionTimeoutMillis(subscriptionTimeoutMillis); } } /** * Returns the <code>ServerSettings</code> of the <code>MessageDestination</code>. * * @return The <code>ServerSettings</code> of the <code>MessageDestination</code>. */ public ServerSettings getServerSettings() { return serverSettings; } /** * Sets the <code>ServerSettings</code> of the <code>MessageDestination</code>. * * @param serverSettings * The <code>ServerSettings</code> of the <code>MessageDestination</code> */ public void setServerSettings(ServerSettings serverSettings) { this.serverSettings = serverSettings; } /** * Casts the <code>Service</code> into <code>MessageService</code> and calls super.setService. * * @param service * The <code>Service</code> managing this <code>Destination</code>. */ @Override public void setService(Service service) { MessageService messageService = (MessageService) service; super.setService(messageService); } // -------------------------------------------------------------------------- // // Other public APIs // // -------------------------------------------------------------------------- /** @exclude */ public SubscriptionManager getSubscriptionManager() { return subscriptionManager; } /** @exclude */ public RemoteSubscriptionManager getRemoteSubscriptionManager() { return remoteSubscriptionManager; } /** @exclude */ public ThrottleManager getThrottleManager() { return throttleManager; } /** @exclude **/ @Override public boolean equals(Object o) { if (o instanceof Destination) { Destination d = (Destination) o; if (d != null && d.getServiceType().equals(getServiceType()) && d.getId().equals(getId())) { return true; } } return false; } /** @exclude **/ @Override public int hashCode() { return (getServiceType() == null ? 0 : getServiceType().hashCode()) * 100003 + (getId() == null ? 0 : getId().hashCode()); } /** @exclude **/ @Override public String toString() { return getServiceType() + "#" + getId(); } // -------------------------------------------------------------------------- // // Protected/private APIs // // -------------------------------------------------------------------------- protected void network(ConfigMap properties) { ConfigMap network = properties.getPropertyAsMap(NetworkSettings.NETWORK_ELEMENT, null); if (network != null) { // Get implementation specific network settings, including subclasses! NetworkSettings ns = getNetworkSettings(); // Subscriber timeout; first check for subscription-timeout-minutes and fallback to legacy session-timeout. int useLegacyPropertyToken = -999999; int subscriptionTimeoutMinutes = network.getPropertyAsInt(NetworkSettings.SUBSCRIPTION_TIMEOUT_MINUTES, useLegacyPropertyToken); if (subscriptionTimeoutMinutes == useLegacyPropertyToken) subscriptionTimeoutMinutes = network.getPropertyAsInt(NetworkSettings.SESSION_TIMEOUT, NetworkSettings.DEFAULT_TIMEOUT); ns.setSubscriptionTimeoutMinutes(subscriptionTimeoutMinutes); // Throttle Settings throttle(ns.getThrottleSettings(), network); setNetworkSettings(ns); } } protected void throttle(ThrottleSettings ts, ConfigMap network) { ConfigMap inbound = network.getPropertyAsMap(ThrottleSettings.ELEMENT_INBOUND, null); if (inbound != null) { int policy = getPolicyFromThrottleSettings(inbound); ts.setInboundPolicy(policy); int destFreq = inbound.getPropertyAsInt(ThrottleSettings.ELEMENT_DEST_FREQ, 0); ts.setIncomingDestinationFrequency(destFreq); int clientFreq = inbound.getPropertyAsInt(ThrottleSettings.ELEMENT_CLIENT_FREQ, 0); ts.setIncomingClientFrequency(clientFreq); } ConfigMap outbound = network.getPropertyAsMap(ThrottleSettings.ELEMENT_OUTBOUND, null); if (outbound != null) { int policy = getPolicyFromThrottleSettings(outbound); ts.setOutboundPolicy(policy); int destFreq = outbound.getPropertyAsInt(ThrottleSettings.ELEMENT_DEST_FREQ, 0); ts.setOutgoingDestinationFrequency(destFreq); int clientFreq = outbound.getPropertyAsInt(ThrottleSettings.ELEMENT_CLIENT_FREQ, 0); ts.setOutgoingClientFrequency(clientFreq); } } private int getPolicyFromThrottleSettings(ConfigMap settings) { String policyString = settings.getPropertyAsString(ThrottleSettings.ELEMENT_POLICY, null); int policy = ThrottleSettings.POLICY_NONE; if (policyString == null) return policy; try { policy = ThrottleSettings.parsePolicy(policyString); if (policy == ThrottleSettings.POLICY_REPLACE) { if (Log.isWarn()) { Log.getLogger(getLogCategory()).warn("Throttle outbound policy '{0}' found on message destination '{1}'." + " The '{0}' throttle outbound policy has been deprecated. Please remove it from your configuration file.", new Object[] { "REPLACE", id }); } } } catch (ConfigurationException exception) { ConfigurationException ce = new ConfigurationException(); ce.setMessage(UNSUPPORTED_POLICY, new Object[] { getId(), policyString }); throw ce; } return policy; } protected void server(ConfigMap properties) { ConfigMap server = properties.getPropertyAsMap(DestinationSettings.SERVER_ELEMENT, null); if (server != null) { int max = server.getPropertyAsInt(MessagingConstants.MAX_CACHE_SIZE_ELEMENT, MessagingConstants.DEFAULT_MAX_CACHE_SIZE); serverSettings.setMaxCacheSize(max); long ttl = server.getPropertyAsLong(MessagingConstants.TIME_TO_LIVE_ELEMENT, -1); serverSettings.setMessageTTL(ttl); boolean durable = server.getPropertyAsBoolean(MessagingConstants.IS_DURABLE_ELEMENT, false); serverSettings.setDurable(durable); boolean allowSubtopics = server.getPropertyAsBoolean(MessagingConstants.ALLOW_SUBTOPICS_ELEMENT, false); serverSettings.setAllowSubtopics(allowSubtopics); String subtopicSeparator = server.getPropertyAsString(MessagingConstants.SUBTOPIC_SEPARATOR_ELEMENT, MessagingConstants.DEFAULT_SUBTOPIC_SEPARATOR); serverSettings.setSubtopicSeparator(subtopicSeparator); String routingMode = server.getPropertyAsString(MessagingConstants.CLUSTER_MESSAGE_ROUTING, "server-to-server"); serverSettings.setBroadcastRoutingMode(routingMode); } } /** * Returns the log category of the <code>MessageDestination</code>. * * @return The log category of the component. */ @Override protected String getLogCategory() { return LOG_CATEGORY; } /** * Invoked automatically to allow the <code>MessageDestination</code> to setup its corresponding MBean control. * * @param service * The <code>Service</code> that manages this <code>MessageDestination</code>. */ @Override protected void setupDestinationControl(Service service) { controller = new MessageDestinationControl(this, service.getControl()); controller.register(); setControl(controller); setupThrottleManagerControl(controller); setupSubscriptionManagerControl(controller); } private void setupThrottleManagerControl(MessageDestinationControl destinationControl) { ThrottleManagerControl throttleManagerControl = new ThrottleManagerControl(getThrottleManager(), destinationControl); throttleManagerControl.register(); getThrottleManager().setControl(throttleManagerControl); getThrottleManager().setManaged(true); destinationControl.setThrottleManager(throttleManagerControl.getObjectName()); } private void setupSubscriptionManagerControl(MessageDestinationControl destinationControl) { SubscriptionManagerControl subscriptionManagerControl = new SubscriptionManagerControl(getSubscriptionManager(), destinationControl); subscriptionManagerControl.register(); getSubscriptionManager().setControl(subscriptionManagerControl); getSubscriptionManager().setManaged(true); destinationControl.setSubscriptionManager(subscriptionManagerControl.getObjectName()); } }