001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.servicemix.jbi.container;
018:
019: import java.lang.reflect.Method;
020: import java.util.Iterator;
021: import java.util.LinkedHashMap;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Properties;
025:
026: import javax.jbi.JBIException;
027: import javax.jbi.component.Component;
028:
029: import org.apache.servicemix.components.util.ComponentAdaptor;
030: import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
031: import org.apache.xbean.spring.context.impl.NamespaceHelper;
032: import org.springframework.beans.BeanUtils;
033: import org.springframework.beans.BeansException;
034: import org.springframework.beans.factory.BeanFactory;
035: import org.springframework.beans.factory.BeanFactoryAware;
036: import org.springframework.beans.factory.DisposableBean;
037: import org.springframework.beans.factory.InitializingBean;
038: import org.springframework.context.ApplicationContext;
039: import org.springframework.context.ApplicationContextAware;
040: import org.springframework.core.io.support.PropertiesLoaderUtils;
041: import org.springframework.util.ClassUtils;
042:
043: /**
044: * An enhanced JBI container which adds some Spring helper methods for
045: * easier configuration through spring's XML configuration file.
046: *
047: * @org.apache.xbean.XBean element="container" rootElement="true"
048: * description="The ServiceMix JBI Container"
049: *
050: * @version $Revision: 594535 $
051: */
052: public class SpringJBIContainer extends JBIContainer implements
053: InitializingBean, DisposableBean, BeanFactoryAware,
054: ApplicationContextAware {
055:
056: private String[] componentNames;
057: private ActivationSpec[] activationSpecs;
058: private BeanFactory beanFactory;
059: private ApplicationContext applicationContext;
060: private String[] deployArchives;
061: private DeploySupport[] deployments;
062: private Map components;
063: private Map endpoints;
064: private Runnable onShutDown;
065:
066: public void afterPropertiesSet() throws Exception {
067: init();
068:
069: // lets iterate through all the component names and register them
070: if (componentNames != null) {
071: for (int i = 0; i < componentNames.length; i++) {
072: String componentName = componentNames[i];
073: activateComponent(new ActivationSpec(componentName,
074: lookupBean(componentName)));
075: }
076: }
077:
078: if (activationSpecs != null) {
079: for (int i = 0; i < activationSpecs.length; i++) {
080: ActivationSpec activationSpec = activationSpecs[i];
081: activateComponent(activationSpec);
082: }
083: }
084:
085: if (deployArchives != null) {
086: for (int i = 0; i < deployArchives.length; i++) {
087: String archive = deployArchives[i];
088: installArchive(archive);
089: }
090: }
091:
092: if (components != null) {
093: for (Iterator it = components.entrySet().iterator(); it
094: .hasNext();) {
095: Map.Entry e = (Map.Entry) it.next();
096: if (!(e.getKey() instanceof String)) {
097: throw new JBIException(
098: "Component must have a non null string name");
099: }
100: if (!(e.getValue() instanceof Component)) {
101: throw new JBIException(
102: "Component is not a known component");
103: }
104: String name = (String) e.getKey();
105: activateComponent((Component) e.getValue(), name);
106: getComponent(name).init();
107: }
108: }
109:
110: if (endpoints != null) {
111: initEndpoints();
112: }
113:
114: if (deployments != null) {
115: for (DeploySupport deployment : deployments) {
116: deployment.deploy(this );
117: }
118: }
119:
120: start();
121: }
122:
123: private void initEndpoints() throws Exception {
124: if (components == null) {
125: components = new LinkedHashMap();
126: }
127: Class componentClass = Class
128: .forName("org.apache.servicemix.common.DefaultComponent");
129: Class endpointClass = Class
130: .forName("org.apache.servicemix.common.Endpoint");
131: Method addEndpointMethod = componentClass.getDeclaredMethod(
132: "addEndpoint", new Class[] { endpointClass });
133: addEndpointMethod.setAccessible(true);
134: Method getEndpointClassesMethod = componentClass
135: .getDeclaredMethod("getEndpointClasses", null);
136: getEndpointClassesMethod.setAccessible(true);
137: for (Iterator it = endpoints.entrySet().iterator(); it
138: .hasNext();) {
139: Map.Entry e = (Map.Entry) it.next();
140: String key = (String) e.getKey();
141: List l = (List) e.getValue();
142: for (Iterator itEp = l.iterator(); itEp.hasNext();) {
143: Object endpoint = itEp.next();
144: Component c = null;
145: if (key.length() > 0) {
146: Component comp = (Component) components.get(key);
147: if (comp == null) {
148: throw new JBIException(
149: "Could not find component '" + key
150: + "' specified for endpoint");
151: }
152: c = comp;
153: } else {
154: for (Iterator itCmp = components.values()
155: .iterator(); itCmp.hasNext();) {
156: Component comp = (Component) itCmp.next();
157: Class[] endpointClasses = (Class[]) getEndpointClassesMethod
158: .invoke(comp, null);
159: if (isKnownEndpoint(endpoint, endpointClasses)) {
160: c = comp;
161: break;
162: }
163: }
164: if (c == null) {
165: c = getComponentForEndpoint(
166: getEndpointClassesMethod, endpoint);
167: if (c == null) {
168: throw new JBIException(
169: "Unable to find a component for endpoint class: "
170: + endpoint.getClass());
171: }
172: }
173: }
174: addEndpointMethod.invoke(c, new Object[] { endpoint });
175: }
176: }
177: }
178:
179: private Component getComponentForEndpoint(
180: Method getEndpointClassesMethod, Object endpoint)
181: throws Exception {
182: Properties namespaces = PropertiesLoaderUtils
183: .loadAllProperties("META-INF/spring.handlers");
184: for (Iterator itNs = namespaces.keySet().iterator(); itNs
185: .hasNext();) {
186: String namespaceURI = (String) itNs.next();
187: String uri = NamespaceHelper
188: .createDiscoveryPathName(namespaceURI);
189: Properties props = PropertiesLoaderUtils
190: .loadAllProperties(uri);
191: String compClassName = props.getProperty("component");
192: if (compClassName != null) {
193: Class compClass = ClassUtils.forName(compClassName);
194: Component comp = (Component) BeanUtils
195: .instantiateClass(compClass);
196: Class[] endpointClasses = (Class[]) getEndpointClassesMethod
197: .invoke(comp, null);
198: if (isKnownEndpoint(endpoint, endpointClasses)) {
199: String name = chooseComponentName(comp);
200: activateComponent(comp, name);
201: components.put(name, comp);
202: return comp;
203: }
204: }
205: }
206: return null;
207: }
208:
209: private String chooseComponentName(Object c) {
210: String className = c.getClass().getName();
211: if (className.startsWith("org.apache.servicemix.")) {
212: int idx1 = className.lastIndexOf('.');
213: int idx0 = className.lastIndexOf('.', idx1 - 1);
214: String name = "servicemix-"
215: + className.substring(idx0 + 1, idx1);
216: if (registry.getComponent(name) == null) {
217: return name;
218: }
219: }
220: return createComponentID();
221: }
222:
223: private boolean isKnownEndpoint(Object endpoint,
224: Class[] knownClasses) {
225: if (knownClasses != null) {
226: for (int i = 0; i < knownClasses.length; i++) {
227: if (knownClasses[i].isInstance(endpoint)) {
228: return true;
229: }
230: }
231: }
232: return false;
233: }
234:
235: public void stop() throws JBIException {
236: if (beanFactory instanceof DisposableBean) {
237: DisposableBean disposable = (DisposableBean) beanFactory;
238: try {
239: disposable.destroy();
240: } catch (Exception e) {
241: throw new JBIException(
242: "Failed to dispose of the Spring BeanFactory due to: "
243: + e, e);
244: }
245: }
246: super .stop();
247: }
248:
249: /**
250: * Returns the compoment or POJO registered with the given component ID.
251: *
252: * @param id
253: * @return the Component
254: */
255: public Object getBean(String id) {
256: ComponentMBeanImpl component = getComponent(id);
257: Object bean = component != null ? component.getComponent()
258: : null;
259: if (bean instanceof ComponentAdaptor) {
260: bean = ((ComponentAdaptor) bean).getLifeCycle();
261: }
262: return bean;
263: }
264:
265: // Properties
266: //-------------------------------------------------------------------------
267: /**
268: * @org.apache.xbean.Property hidden="true"
269: */
270: public BeanFactory getBeanFactory() {
271: return beanFactory;
272: }
273:
274: public void setBeanFactory(BeanFactory beanFactory)
275: throws BeansException {
276: this .beanFactory = beanFactory;
277: }
278:
279: public String[] getComponentNames() {
280: return componentNames;
281: }
282:
283: public void setComponentNames(String[] componentNames) {
284: this .componentNames = componentNames;
285: }
286:
287: public ActivationSpec[] getActivationSpecs() {
288: return activationSpecs;
289: }
290:
291: public void setActivationSpecs(ActivationSpec[] activationSpecs)
292: throws JBIException {
293: this .activationSpecs = activationSpecs;
294: }
295:
296: public String[] getDeployArchives() {
297: return deployArchives;
298: }
299:
300: public void setDeployArchives(String[] deployArchives) {
301: this .deployArchives = deployArchives;
302: }
303:
304: public DeploySupport[] getDeployments() {
305: return deployments;
306: }
307:
308: public void setDeployments(DeploySupport[] deployments) {
309: this .deployments = deployments;
310: }
311:
312: // Implementation methods
313: //-------------------------------------------------------------------------
314: protected Object lookupBean(String componentName) {
315: Object bean = beanFactory.getBean(componentName);
316: if (bean == null) {
317: throw new IllegalArgumentException("Component name: "
318: + componentName
319: + " is not found in the Spring BeanFactory");
320: }
321: return bean;
322: }
323:
324: /**
325: * @return
326: * @org.apache.xbean.Property hidden="true"
327: */
328: public ApplicationContext getApplicationContext() {
329: return applicationContext;
330: }
331:
332: public void setApplicationContext(
333: ApplicationContext applicationContext) {
334: this .applicationContext = applicationContext;
335: }
336:
337: public void destroy() throws Exception {
338: super .shutDown();
339: }
340:
341: public void shutDown() throws JBIException {
342: if (onShutDown != null) {
343: onShutDown.run();
344: } else {
345: //no shutdown handler has been set
346: //shutting down the container ourselves
347: super .shutDown();
348: }
349: }
350:
351: /**
352: * Set a {@link Runnable} which can handle the shutdown of the container
353: *
354: * @param runnable the shutdown handler
355: */
356: public void onShutDown(Runnable runnable) {
357: this .onShutDown = runnable;
358: }
359:
360: /**
361: * @org.apache.xbean.Map flat="true" keyName="name"
362: */
363: public Map getComponents() {
364: return components;
365: }
366:
367: public void setComponents(Map components) {
368: this .components = components;
369: }
370:
371: /**
372: * @org.apache.xbean.Map flat="true" dups="always" keyName="component" defaultKey=""
373: */
374: public Map getEndpoints() {
375: return endpoints;
376: }
377:
378: public void setEndpoints(Map endpoints) {
379: this.endpoints = endpoints;
380: }
381:
382: }
|