001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
003     * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
004     * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
005     * License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     */
013    package org.apache.camel.component.jbi;
014    
015    import org.apache.camel.CamelContext;
016    import org.apache.camel.Component;
017    import org.apache.camel.Endpoint;
018    import org.apache.camel.Exchange;
019    import org.apache.camel.FailedToCreateProducerException;
020    import org.apache.camel.Processor;
021    import org.apache.servicemix.common.BaseServiceUnitManager;
022    import org.apache.servicemix.common.DefaultComponent;
023    import org.apache.servicemix.common.Deployer;
024    import org.apache.servicemix.id.IdGenerator;
025    import org.apache.servicemix.jbi.resolver.URIResolver;
026    import org.apache.servicemix.jbi.util.IntrospectionSupport;
027    import org.apache.servicemix.jbi.util.URISupport;
028    
029    import javax.jbi.servicedesc.ServiceEndpoint;
030    import javax.xml.namespace.QName;
031    import java.net.URI;
032    import java.net.URISyntaxException;
033    import java.util.ArrayList;
034    import java.util.List;
035    import java.util.Map;
036    import java.util.concurrent.ScheduledExecutorService;
037    import java.util.concurrent.ScheduledThreadPoolExecutor;
038    
039    /**
040     * Deploys the camel endpoints within JBI
041     *
042     * @version $Revision: 426415 $
043     */
044    public class CamelJbiComponent extends DefaultComponent implements Component<Exchange> {
045        private JbiBinding binding;
046        private CamelContext camelContext;
047        private ScheduledExecutorService executorService;
048        private IdGenerator idGenerator;
049        protected CamelSpringDeployer deployer;
050    
051        /* (non-Javadoc)
052        * @see org.servicemix.common.BaseComponent#createServiceUnitManager()
053        */
054        public BaseServiceUnitManager createServiceUnitManager() {
055            Deployer[] deployers = new Deployer[]{new CamelSpringDeployer(this)};
056            return new BaseServiceUnitManager(this, deployers);
057        }
058    
059        /**
060         * @return List of endpoints
061         * @see org.apache.servicemix.common.DefaultComponent#getConfiguredEndpoints()
062         */
063        @Override
064        protected List<CamelJbiEndpoint> getConfiguredEndpoints() {
065            List<CamelJbiEndpoint> answer = new ArrayList<CamelJbiEndpoint>();
066            return answer;
067        }
068    
069        /**
070         * @return Class[]
071         * @see org.apache.servicemix.common.DefaultComponent#getEndpointClasses()
072         */
073        @Override
074        protected Class[] getEndpointClasses() {
075            return new Class[]{CamelJbiEndpoint.class};
076        }
077    
078        /**
079         * @return the binding
080         */
081        public JbiBinding getBinding() {
082            if (binding == null) {
083                binding = new JbiBinding();
084            }
085            return binding;
086        }
087    
088        /**
089         * @param binding the binding to set
090         */
091        public void setBinding(JbiBinding binding) {
092            this.binding = binding;
093        }
094    
095        @Override
096        protected String[] getEPRProtocols() {
097            return new String[]{"camel"};
098        }
099    
100        protected org.apache.servicemix.common.Endpoint getResolvedEPR(ServiceEndpoint ep) throws Exception {
101            CamelJbiEndpoint endpoint = createEndpoint(ep);
102            endpoint.activate();
103            return endpoint;
104        }
105    
106        public CamelJbiEndpoint createEndpoint(ServiceEndpoint ep) throws URISyntaxException {
107            URI uri = new URI(ep.getEndpointName());
108            Map map = URISupport.parseQuery(uri.getQuery());
109            String camelUri = uri.getSchemeSpecificPart();
110            Endpoint camelEndpoint = getCamelContext().getEndpoint(camelUri);
111            Processor processor = createCamelProcessor(camelEndpoint);
112            CamelJbiEndpoint endpoint = new CamelJbiEndpoint(getServiceUnit(), camelEndpoint, getBinding(), processor);
113    
114            IntrospectionSupport.setProperties(endpoint, map);
115    
116            // TODO
117            //endpoint.setRole(MessageExchange.Role.PROVIDER);
118    
119            return endpoint;
120        }
121    
122        // Resolve Camel Endpoints
123        //-------------------------------------------------------------------------
124        public Endpoint<Exchange> createEndpoint(String uri) {
125            if (uri.startsWith("jbi:")) {
126                uri = uri.substring("jbi:".length());
127                return new JbiEndpoint(this, uri);
128            }
129            return null;
130        }
131    
132        public CamelContext getCamelContext() {
133            return camelContext;
134        }
135    
136        public void setCamelContext(CamelContext camelContext) {
137            this.camelContext = camelContext;
138        }
139    
140        public ScheduledExecutorService getExecutorService() {
141            if (executorService == null) {
142                executorService = new ScheduledThreadPoolExecutor(5);
143            }
144            return executorService;
145        }
146    
147        /**
148         * Activating a JBI endpoint created by a camel consumer.
149         *
150         * @returns a JBI endpoint created for the given Camel endpoint
151         */
152        public CamelJbiEndpoint activateJbiEndpoint(Endpoint camelEndpoint, Processor processor) throws Exception {
153            CamelJbiEndpoint jbiEndpoint = createJbiEndpointFromCamel(camelEndpoint, processor);
154    
155            // the following method will activate the new dynamic JBI endpoint
156            if (deployer != null) {
157                // lets add this to the current service unit being deployed
158                deployer.addService(jbiEndpoint);
159            }
160            else {
161                addEndpoint(jbiEndpoint);
162            }
163            return jbiEndpoint;
164        }
165    
166        public void deactivateJbiEndpoint(CamelJbiEndpoint jbiEndpoint) throws Exception {
167            // this will be done by the ServiceUnit
168            //jbiEndpoint.deactivate();
169        }
170    
171        protected CamelJbiEndpoint createJbiEndpointFromCamel(Endpoint camelEndpoint, Processor processor) {
172            CamelJbiEndpoint jbiEndpoint;
173            String endpointUri = camelEndpoint.getEndpointUri();
174            if (camelEndpoint instanceof JbiEndpoint) {
175                QName service = null;
176                String endpoint = null;
177                if (endpointUri.startsWith("name:")) {
178                    endpoint = endpointUri.substring("name:".length());
179                    service = CamelJbiEndpoint.SERVICE_NAME;
180                }
181                else if (endpointUri.startsWith("endpoint:")) {
182                    String uri = endpointUri.substring("endpoint:".length());
183                    // lets decode "serviceNamespace sep serviceName sep endpointName
184                    String[] parts;
185                    try {
186                        parts = URIResolver.split3(uri);
187                    }
188                    catch (IllegalArgumentException e) {
189                        throw new IllegalArgumentException("Expected syntax jbi:endpoint:[serviceNamespace][sep][serviceName][sep][endpointName] where sep = '/' or ':' depending on the serviceNamespace, but was given: " + endpointUri + ". Cause: " + e, e);
190                    }
191                    service = new QName(parts[0], parts[1]);
192                    endpoint = parts[2];
193                }
194                else if (endpointUri.startsWith("service:")) {
195                    String uri = endpointUri.substring("service:".length());
196                    // lets decode "serviceNamespace sep serviceName
197                    String[] parts;
198                    try {
199                        parts = URIResolver.split2(uri);
200                    }
201                    catch (IllegalArgumentException e) {
202                        throw new IllegalArgumentException("Expected syntax jbi:endpoint:[serviceNamespace][sep][serviceName] where sep = '/' or ':' depending on the serviceNamespace, but was given: " + endpointUri + ". Cause: " + e, e);
203                    }
204                    service = new QName(parts[0], parts[1]);
205                    endpoint = createEndpointName();
206                }
207                else {
208                    throw new IllegalArgumentException("Expected syntax jbi:endpoint:[serviceNamespace][sep][serviceName][sep][endpointName] or  jbi:service:[serviceNamespace][sep][serviceName or jbi:name:[endpointName] but was given: " + endpointUri);
209                }
210                jbiEndpoint = new CamelJbiEndpoint(getServiceUnit(), service, endpoint, camelEndpoint, getBinding(), processor);
211            }
212            else {
213                jbiEndpoint = new CamelJbiEndpoint(getServiceUnit(), camelEndpoint, getBinding(), processor);
214            }
215            return jbiEndpoint;
216        }
217    
218        protected String createEndpointName() {
219            if (idGenerator == null) {
220                idGenerator = new IdGenerator("camel");
221            }
222            return idGenerator.generateSanitizedId();
223        }
224    
225        /**
226         * Returns a JBI endpoint created for the given Camel endpoint
227         */
228        public CamelJbiEndpoint createJbiEndpointFromCamel(Endpoint camelEndpoint) {
229            Processor processor = createCamelProcessor(camelEndpoint);
230            return createJbiEndpointFromCamel(camelEndpoint, processor);
231        }
232    
233        protected Processor createCamelProcessor(Endpoint camelEndpoint) {
234            Processor processor = null;
235            try {
236                processor = camelEndpoint.createProducer();
237            }
238            catch (Exception e) {
239                throw new FailedToCreateProducerException(camelEndpoint, e);
240            }
241            return processor;
242        }
243    
244        /**
245         * Should we expose the Camel JBI onto the NMR.
246         * <p/>
247         * We may wish to add some policy stuff etc.
248         *
249         * @param endpoint the camel endpoint
250         * @return true if the endpoint should be exposed in the NMR
251         */
252        public boolean isEndpointExposedOnNmr(Endpoint endpoint) {
253            // TODO we should only expose consuming endpoints
254            return !(endpoint instanceof JbiEndpoint);
255        }
256    }