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.lwcontainer;
018:
019: import java.lang.reflect.Method;
020: import java.util.EventListener;
021: import java.util.IdentityHashMap;
022: import java.util.Iterator;
023: import java.util.LinkedHashMap;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Properties;
027:
028: import javax.jbi.JBIException;
029: import javax.jbi.component.Component;
030: import javax.jbi.component.ComponentContext;
031: import javax.jbi.messaging.MessageExchange;
032: import javax.xml.namespace.QName;
033:
034: import org.apache.servicemix.common.DefaultComponent;
035: import org.apache.servicemix.common.Endpoint;
036: import org.apache.servicemix.common.ExchangeProcessor;
037: import org.apache.servicemix.id.IdGenerator;
038: import org.apache.servicemix.jbi.container.JBIContainer;
039: import org.apache.servicemix.jbi.framework.ComponentContextImpl;
040: import org.apache.servicemix.jbi.management.BaseSystemService;
041: import org.apache.xbean.spring.context.impl.NamespaceHelper;
042: import org.springframework.beans.BeanUtils;
043: import org.springframework.core.io.support.PropertiesLoaderUtils;
044: import org.springframework.util.ClassUtils;
045:
046: /**
047: * Fake endpoint that hold components, endpoints, listeners and services.
048: */
049: public class LwContainerExtra extends Endpoint {
050:
051: private Map components;
052: private Map endpoints;
053: private EventListener[] listeners;
054: private BaseSystemService[] services;
055: private IdGenerator idGenerator = new IdGenerator();
056: private Map<Object, Component> endpointToComponent = new IdentityHashMap<Object, Component>();
057:
058: public LwContainerExtra(Map components, Map endpoints,
059: EventListener[] listeners, BaseSystemService[] services) {
060: this .service = new QName(
061: "http://servicemix.apache.org/lwcontainer", "extra");
062: this .endpoint = idGenerator.generateSanitizedId();
063: this .components = components;
064: this .endpoints = endpoints;
065: this .listeners = listeners;
066: this .services = services;
067: }
068:
069: public void activate() throws Exception {
070: if (components != null) {
071: for (Iterator it = components.entrySet().iterator(); it
072: .hasNext();) {
073: Map.Entry e = (Map.Entry) it.next();
074: if (!(e.getKey() instanceof String)) {
075: throw new JBIException(
076: "Component must have a non null string name");
077: }
078: if (!(e.getValue() instanceof Component)) {
079: throw new JBIException(
080: "Component is not a known component");
081: }
082: String name = (String) e.getKey();
083: getContainer().activateComponent(
084: (Component) e.getValue(), name);
085: getContainer().getComponent(name).init();
086: }
087: }
088:
089: if (endpoints != null) {
090: initEndpoints();
091: }
092: if (listeners != null) {
093: for (int i = 0; i < listeners.length; i++) {
094: getContainer().addListener(listeners[i]);
095: }
096: }
097: if (services != null) {
098: for (int i = 0; i < services.length; i++) {
099: services[i].init(getContainer());
100: services[i].start();
101: }
102: }
103: }
104:
105: public void deactivate() throws Exception {
106: // Remove endpoints
107: if (endpoints != null) {
108: for (Iterator it = endpoints.entrySet().iterator(); it
109: .hasNext();) {
110: Map.Entry e = (Map.Entry) it.next();
111: List l = (List) e.getValue();
112: for (Iterator itEp = l.iterator(); itEp.hasNext();) {
113: Object endpoint = itEp.next();
114: Component c = endpointToComponent.remove(endpoint);
115: ((DefaultComponent) c)
116: .removeEndpoint((Endpoint) endpoint);
117: }
118: }
119: }
120: // Deactivate components
121: if (components != null) {
122: for (Iterator it = components.entrySet().iterator(); it
123: .hasNext();) {
124: Map.Entry e = (Map.Entry) it.next();
125: String name = (String) e.getKey();
126: getContainer().deactivateComponent(name);
127: }
128: }
129: // Remove listeners
130: if (listeners != null) {
131: for (int i = 0; i < listeners.length; i++) {
132: getContainer().removeListener(listeners[i]);
133: }
134: }
135: // Remove services
136: if (services != null) {
137: for (int i = 0; i < services.length; i++) {
138: services[i].stop();
139: services[i].shutDown();
140: }
141: }
142: }
143:
144: public ExchangeProcessor getProcessor() {
145: return null;
146: }
147:
148: public MessageExchange.Role getRole() {
149: return null;
150: }
151:
152: private void initEndpoints() throws Exception {
153: if (components == null) {
154: components = new LinkedHashMap();
155: }
156: Method getEndpointClassesMethod = DefaultComponent.class
157: .getDeclaredMethod("getEndpointClasses", null);
158: getEndpointClassesMethod.setAccessible(true);
159: for (Iterator it = endpoints.entrySet().iterator(); it
160: .hasNext();) {
161: Map.Entry e = (Map.Entry) it.next();
162: String key = (String) e.getKey();
163: List l = (List) e.getValue();
164: for (Iterator itEp = l.iterator(); itEp.hasNext();) {
165: Object endpoint = itEp.next();
166: Component c = null;
167: if (key.length() > 0) {
168: Component comp = (Component) components.get(key);
169: if (comp == null) {
170: throw new JBIException(
171: "Could not find component '" + key
172: + "' specified for endpoint");
173: }
174: c = comp;
175: } else {
176: for (Iterator itCmp = components.values()
177: .iterator(); itCmp.hasNext();) {
178: Component comp = (Component) itCmp.next();
179: Class[] endpointClasses = (Class[]) getEndpointClassesMethod
180: .invoke(comp, null);
181: if (isKnownEndpoint(endpoint, endpointClasses)) {
182: c = comp;
183: break;
184: }
185: }
186: if (c == null) {
187: c = getComponentForEndpoint(
188: getEndpointClassesMethod, endpoint);
189: if (c == null) {
190: throw new JBIException(
191: "Unable to find a component for endpoint class: "
192: + endpoint.getClass());
193: }
194: }
195: }
196: ((DefaultComponent) c).addEndpoint((Endpoint) endpoint);
197: endpointToComponent.put(endpoint, c);
198: }
199: }
200: }
201:
202: private Component getComponentForEndpoint(
203: Method getEndpointClassesMethod, Object endpoint)
204: throws Exception {
205: Properties namespaces = PropertiesLoaderUtils
206: .loadAllProperties("META-INF/spring.handlers");
207: for (Iterator itNs = namespaces.keySet().iterator(); itNs
208: .hasNext();) {
209: String namespaceURI = (String) itNs.next();
210: String uri = NamespaceHelper
211: .createDiscoveryPathName(namespaceURI);
212: Properties props = PropertiesLoaderUtils
213: .loadAllProperties(uri);
214: String compClassName = props.getProperty("component");
215: if (compClassName != null) {
216: Class compClass = ClassUtils.forName(compClassName);
217: Component comp = (Component) BeanUtils
218: .instantiateClass(compClass);
219: Class[] endpointClasses = (Class[]) getEndpointClassesMethod
220: .invoke(comp, null);
221: if (isKnownEndpoint(endpoint, endpointClasses)) {
222: String name = chooseComponentName(comp);
223: getContainer().activateComponent(comp, name);
224: components.put(name, comp);
225: return comp;
226: }
227: }
228: }
229: return null;
230: }
231:
232: private String chooseComponentName(Object c) {
233: String className = c.getClass().getName();
234: if (className.startsWith("org.apache.servicemix.")) {
235: int idx1 = className.lastIndexOf('.');
236: int idx0 = className.lastIndexOf('.', idx1 - 1);
237: String name = "servicemix-"
238: + className.substring(idx0 + 1, idx1);
239: return name + "-" + createComponentID();
240: }
241: return createComponentID();
242: }
243:
244: private boolean isKnownEndpoint(Object endpoint,
245: Class[] knownClasses) {
246: if (knownClasses != null) {
247: for (int i = 0; i < knownClasses.length; i++) {
248: if (knownClasses[i].isInstance(endpoint)) {
249: return true;
250: }
251: }
252: }
253: return false;
254: }
255:
256: private JBIContainer getContainer() {
257: ComponentContext context = getServiceUnit().getComponent()
258: .getComponentContext();
259: if (context instanceof ComponentContextImpl) {
260: return ((ComponentContextImpl) context).getContainer();
261: }
262: throw new IllegalStateException(
263: "LwContainer component can only be deployed in ServiceMix");
264: }
265:
266: protected String createComponentID() {
267: return idGenerator.generateId();
268: }
269:
270: }
|