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 */
017package org.apache.camel.blueprint;
018
019import java.util.Set;
020import javax.xml.bind.annotation.XmlAccessType;
021import javax.xml.bind.annotation.XmlAccessorType;
022import javax.xml.bind.annotation.XmlAttribute;
023import javax.xml.bind.annotation.XmlRootElement;
024import javax.xml.bind.annotation.XmlTransient;
025
026import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
027import org.apache.camel.CamelContext;
028import org.apache.camel.Endpoint;
029import org.apache.camel.FailedToCreateProducerException;
030import org.apache.camel.Producer;
031import org.apache.camel.component.bean.ProxyHelper;
032import org.apache.camel.core.xml.AbstractCamelFactoryBean;
033import org.apache.camel.util.ServiceHelper;
034
035/**
036 * A factory to create a Proxy to a a Camel Pojo Endpoint.
037 */
038@XmlRootElement(name = "proxy")
039@XmlAccessorType(XmlAccessType.FIELD)
040public class CamelProxyFactoryBean extends AbstractCamelFactoryBean<Object> {
041
042    @XmlAttribute
043    private String serviceUrl;
044    @XmlAttribute
045    private String serviceRef;
046    @XmlAttribute
047    private String serviceInterface;
048    @XmlAttribute
049    private Boolean binding;
050    @XmlTransient
051    private Endpoint endpoint;
052    @XmlTransient
053    private Object serviceProxy;
054    @XmlTransient
055    private Producer producer;
056    @XmlTransient
057    private ExtendedBlueprintContainer blueprintContainer;
058
059    public Object getObject() {
060        return serviceProxy;
061    }
062
063    public Class<Object> getObjectType() {
064        return Object.class;
065    }
066
067    protected CamelContext getCamelContextWithId(String camelContextId) {
068        if (blueprintContainer != null) {
069            return (CamelContext) blueprintContainer.getComponentInstance(camelContextId);
070        }
071        return null;
072    }
073
074    @Override
075    protected CamelContext discoverDefaultCamelContext() {
076        if (blueprintContainer != null) {
077            Set<String> ids = BlueprintCamelContextLookupHelper.lookupBlueprintCamelContext(blueprintContainer);
078            if (ids.size() == 1) {
079                // there is only 1 id for a BlueprintCamelContext so fallback and use this
080                return getCamelContextWithId(ids.iterator().next());
081            }
082        }
083        return null;
084    }
085
086    public void afterPropertiesSet() throws Exception {
087        if (endpoint == null) {
088            getCamelContext();
089            if (getServiceUrl() == null && getServiceRef() == null) {
090                throw new IllegalArgumentException("serviceUrl or serviceRef must be specified.");
091            }
092            if (getServiceInterface() == null) {
093                throw new IllegalArgumentException("serviceInterface must be specified.");
094            }
095
096            // lookup endpoint or we have the url for it
097            if (getServiceRef() != null) {
098                endpoint = getCamelContext().getRegistry().lookupByNameAndType(getServiceRef(), Endpoint.class);
099            } else {
100                endpoint = getCamelContext().getEndpoint(getServiceUrl());
101            }
102
103            if (endpoint == null) {
104                throw new IllegalArgumentException("Could not resolve endpoint: " + getServiceUrl());
105            }
106        }
107
108        // binding is enabled by default
109        boolean bind = getBinding() != null ? getBinding() : true;
110
111        try {
112            producer = endpoint.createProducer();
113            ServiceHelper.startService(producer);
114            Class<?> clazz = blueprintContainer.loadClass(getServiceInterface());
115            serviceProxy = ProxyHelper.createProxy(endpoint, bind, producer, clazz);
116        } catch (Exception e) {
117            throw new FailedToCreateProducerException(endpoint, e);
118        }
119    }
120
121    public void destroy() throws Exception {
122        ServiceHelper.stopService(producer);
123    }
124
125    public String getServiceUrl() {
126        return serviceUrl;
127    }
128
129    public void setServiceUrl(String serviceUrl) {
130        this.serviceUrl = serviceUrl;
131    }
132
133    public String getServiceRef() {
134        return serviceRef;
135    }
136
137    public void setServiceRef(String serviceRef) {
138        this.serviceRef = serviceRef;
139    }
140
141    public Boolean getBinding() {
142        return binding;
143    }
144
145    public void setBinding(Boolean binding) {
146        this.binding = binding;
147    }
148
149    public String getServiceInterface() {
150        return serviceInterface;
151    }
152
153    public void setServiceInterface(String serviceInterface) {
154        this.serviceInterface = serviceInterface;
155    }
156
157    public Endpoint getEndpoint() {
158        return endpoint;
159    }
160
161    public void setEndpoint(Endpoint endpoint) {
162        this.endpoint = endpoint;
163    }
164
165    public Producer getProducer() {
166        return producer;
167    }
168
169    public void setProducer(Producer producer) {
170        this.producer = producer;
171    }
172
173    public ExtendedBlueprintContainer getBlueprintContainer() {
174        return blueprintContainer;
175    }
176
177    public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
178        this.blueprintContainer = blueprintContainer;
179    }
180
181}