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