/* * Copyright 2002-2011 the original author or authors. * * 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.springframework.flex.core; import java.util.ArrayList; import java.util.List; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.flex.config.MessageBrokerConfigProcessor; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import flex.messaging.MessageBroker; import flex.messaging.services.Service; import flex.messaging.services.ServiceAdapter; /** * Base {@link MessageBrokerConfigProcessor} implementation for handling automatic {@link Service} registration with the * {@link MessageBroker} * * @author Jeremy Grelle */ public abstract class AbstractServiceConfigProcessor implements MessageBrokerConfigProcessor, BeanFactoryAware { private String defaultAdapterId; private String[] defaultChannels; private BeanFactory beanFactory; public AbstractServiceConfigProcessor() { this.defaultAdapterId = getServiceAdapterId(); } /** * Error checking is done on the started MessageBroker to ensure configuration was successful. * * @see MessageBrokerConfigProcessor#processAfterStartup(MessageBroker) */ public MessageBroker processAfterStartup(MessageBroker broker) { // Eagerly detect possible problems with the Service Service service = broker.getServiceByType(getServiceClassName()); Assert.notNull(service, "The MessageBroker with id '" + broker.getId() + "' does not have a service of type " + getServiceClassName() + " configured."); Assert.isTrue(service.isStarted(), "The Service with id '" + service.getId() + "' of MessageBroker with id '" + broker.getId() + "' was not started as expected."); return broker; } /** * The MessageBroker is checked to see if the Service has already been configured via the BlazeDS XML config. If no * existing Service is found, one will be installed using the defined configuration properties of this class. * * @see MessageBrokerConfigProcessor#processBeforeStartup(MessageBroker) */ public MessageBroker processBeforeStartup(MessageBroker broker) { Service service = broker.getServiceByType(getServiceClassName()); if (service == null) { service = broker.createService(getServiceId(), getServiceClassName()); if (getServiceAdapterId().equals(this.defaultAdapterId)) { service.registerAdapter(getServiceAdapterId(), getServiceAdapterClassName()); } else { Assert.isAssignable(ServiceAdapter.class, this.beanFactory.getType(this.defaultAdapterId), "A custom default adapter id must refer to a valid Spring bean that " + "is a subclass of " + ServiceAdapter.class.getName() + ". "); service.registerAdapter(this.defaultAdapterId, CustomSpringAdapter.class.getName()); } service.setDefaultAdapter(this.defaultAdapterId); if (!ObjectUtils.isEmpty(this.defaultChannels)) { addDefaultChannels(broker, service); } else { findDefaultChannel(broker, service); } } return broker; } /** * * {@inheritDoc} */ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } /** * Set the id for the default adapter to be installed in the {@link Service}. * * @param defaultAdapterId the id to set for the adapter */ public void setDefaultAdapterId(String defaultAdapterId) { this.defaultAdapterId = defaultAdapterId; } /** * Set the ids of the default channels to be set on the {@link Service}. If not set, the application-wide defaults * will be used. If no application-wide defaults can be found, a best guess will be made using the first available * channel with an appropriate endpoint. * * @param defaultChannels the ids of the default channels for the {@link Service} */ public void setDefaultChannels(String[] defaultChannels) { this.defaultChannels = StringUtils.trimArrayElements(defaultChannels); } /** * Find and set an appropriate default channel for the {@link Service} * * @param broker the {@link MessageBroker} that controls the {@link Service} * @param service the service being configured */ protected abstract void findDefaultChannel(MessageBroker broker, Service service); /** * Returns the class name of the default {@link ServiceAdapter} for the {@link Service} * * @return the default adapter class name */ protected abstract String getServiceAdapterClassName(); /** * Returns the default {@link ServiceAdapter} id for the {@link Service} * * @return the default adapter id */ protected abstract String getServiceAdapterId(); /** * Returns the class name of the specific {@link Service} implementation being configured * * @return the service class name */ protected abstract String getServiceClassName(); /** * Returns the default id for the {@link Service} being configured * * @return the default service id */ protected abstract String getServiceId(); /** * Adds the default channels to the {@link Service} being configured. The <code>defaultChannels</code> will be * validated to ensure they exist in the {@link MessageBroker} before they are set. * * @param broker the newly configured MessageBroker * @param remotingService the newly created Service */ private void addDefaultChannels(MessageBroker broker, Service service) { List<String> defaultChannelList = new ArrayList<String>(); for (String channelId : this.defaultChannels) { Assert.isTrue(broker.getChannelIds().contains(channelId), "The channel " + channelId + " is not known to the MessageBroker " + broker.getId() + " and cannot be set as a default channel" + " on the " + getServiceClassName()); defaultChannelList.add(channelId); } service.setDefaultChannels(defaultChannelList); } /** * This is simply a marker to denote that a Spring-managed adapter will be injected at the proper initialization * point. */ protected static final class CustomSpringAdapter { public CustomSpringAdapter() { throw new UnsupportedOperationException("This adapter class should never be instantiated directly by BlazeDS. " + "It is only a placeholder to denote that a Spring-managed adapter should be injected when a Destination is" + "initialized."); } } }