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, EventListener[] listeners, BaseSystemService[] services) {
059 this.service = new QName("http://servicemix.apache.org/lwcontainer", "extra");
060 this.endpoint = idGenerator.generateSanitizedId();
061 this.components = components;
062 this.endpoints = endpoints;
063 this.listeners = listeners;
064 this.services = services;
065 }
066
067 public void activate() throws Exception {
068 if (components != null) {
069 for (Iterator it = components.entrySet().iterator(); it.hasNext();) {
070 Map.Entry e = (Map.Entry) it.next();
071 if (!(e.getKey() instanceof String)) {
072 throw new JBIException("Component must have a non null string name");
073 }
074 if (!(e.getValue() instanceof Component)) {
075 throw new JBIException("Component is not a known component");
076 }
077 String name = (String) e.getKey();
078 getContainer().activateComponent((Component) e.getValue(), name);
079 getContainer().getComponent(name).init();
080 }
081 }
082
083 if (endpoints != null) {
084 initEndpoints();
085 }
086 if (listeners != null) {
087 for (int i = 0; i < listeners.length; i++) {
088 getContainer().addListener(listeners[i]);
089 }
090 }
091 if (services != null) {
092 for (int i = 0; i < services.length; i++) {
093 services[i].init(getContainer());
094 services[i].start();
095 }
096 }
097 }
098
099 public void deactivate() throws Exception {
100 // Remove endpoints
101 if (endpoints != null) {
102 for (Iterator it = endpoints.entrySet().iterator(); it.hasNext();) {
103 Map.Entry e = (Map.Entry) it.next();
104 List l = (List) e.getValue();
105 for (Iterator itEp = l.iterator(); itEp.hasNext();) {
106 Object endpoint = itEp.next();
107 Component c = endpointToComponent.remove(endpoint);
108 ((DefaultComponent) c).removeEndpoint((Endpoint) endpoint);
109 }
110 }
111 }
112 // Deactivate components
113 if (components != null) {
114 for (Iterator it = components.entrySet().iterator(); it.hasNext();) {
115 Map.Entry e = (Map.Entry) it.next();
116 String name = (String) e.getKey();
117 getContainer().deactivateComponent(name);
118 }
119 }
120 // Remove listeners
121 if (listeners != null) {
122 for (int i = 0; i < listeners.length; i++) {
123 getContainer().removeListener(listeners[i]);
124 }
125 }
126 // Remove services
127 if (services != null) {
128 for (int i = 0; i < services.length; i++) {
129 services[i].stop();
130 services[i].shutDown();
131 }
132 }
133 }
134
135 public ExchangeProcessor getProcessor() {
136 return null;
137 }
138
139 public MessageExchange.Role getRole() {
140 return null;
141 }
142
143 private void initEndpoints() throws Exception {
144 if (components == null) {
145 components = new LinkedHashMap();
146 }
147 Method getEndpointClassesMethod = DefaultComponent.class.getDeclaredMethod("getEndpointClasses", null);
148 getEndpointClassesMethod.setAccessible(true);
149 for (Iterator it = endpoints.entrySet().iterator(); it.hasNext();) {
150 Map.Entry e = (Map.Entry) it.next();
151 String key = (String) e.getKey();
152 List l = (List) e.getValue();
153 for (Iterator itEp = l.iterator(); itEp.hasNext();) {
154 Object endpoint = itEp.next();
155 Component c = null;
156 if (key.length() > 0) {
157 Component comp = (Component) components.get(key);
158 if (comp == null) {
159 throw new JBIException("Could not find component '" + key + "' specified for endpoint");
160 }
161 c = comp;
162 } else {
163 for (Iterator itCmp = components.values().iterator(); itCmp.hasNext();) {
164 Component comp = (Component) itCmp.next();
165 Class[] endpointClasses = (Class[]) getEndpointClassesMethod.invoke(comp, null);
166 if (isKnownEndpoint(endpoint, endpointClasses)) {
167 c = comp;
168 break;
169 }
170 }
171 if (c == null) {
172 c = getComponentForEndpoint(getEndpointClassesMethod, endpoint);
173 if (c == null) {
174 throw new JBIException("Unable to find a component for endpoint class: " + endpoint.getClass());
175 }
176 }
177 }
178 ((DefaultComponent) c).addEndpoint((Endpoint) endpoint);
179 endpointToComponent.put(endpoint, c);
180 }
181 }
182 }
183
184 private Component getComponentForEndpoint(Method getEndpointClassesMethod, Object endpoint) throws Exception {
185 Properties namespaces = PropertiesLoaderUtils.loadAllProperties("META-INF/spring.handlers");
186 for (Iterator itNs = namespaces.keySet().iterator(); itNs.hasNext();) {
187 String namespaceURI = (String) itNs.next();
188 String uri = NamespaceHelper.createDiscoveryPathName(namespaceURI);
189 Properties props = PropertiesLoaderUtils.loadAllProperties(uri);
190 String compClassName = props.getProperty("component");
191 if (compClassName != null) {
192 Class compClass = ClassUtils.forName(compClassName);
193 Component comp = (Component) BeanUtils.instantiateClass(compClass);
194 Class[] endpointClasses = (Class[]) getEndpointClassesMethod.invoke(comp, null);
195 if (isKnownEndpoint(endpoint, endpointClasses)) {
196 String name = chooseComponentName(comp);
197 getContainer().activateComponent(comp, name);
198 components.put(name, comp);
199 return comp;
200 }
201 }
202 }
203 return null;
204 }
205
206 private String chooseComponentName(Object c) {
207 String className = c.getClass().getName();
208 if (className.startsWith("org.apache.servicemix.")) {
209 int idx1 = className.lastIndexOf('.');
210 int idx0 = className.lastIndexOf('.', idx1 - 1);
211 String name = "servicemix-" + className.substring(idx0 + 1, idx1);
212 return name + "-" + createComponentID();
213 }
214 return createComponentID();
215 }
216
217 private boolean isKnownEndpoint(Object endpoint, Class[] knownClasses) {
218 if (knownClasses != null) {
219 for (int i = 0; i < knownClasses.length; i++) {
220 if (knownClasses[i].isInstance(endpoint)) {
221 return true;
222 }
223 }
224 }
225 return false;
226 }
227
228 private JBIContainer getContainer() {
229 ComponentContext context = getServiceUnit().getComponent().getComponentContext();
230 if (context instanceof ComponentContextImpl) {
231 return ((ComponentContextImpl) context).getContainer();
232 }
233 throw new IllegalStateException("LwContainer component can only be deployed in ServiceMix");
234 }
235
236 protected String createComponentID() {
237 return idGenerator.generateId();
238 }
239
240 }