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            // need to start endpoint before we create producer
113            ServiceHelper.startService(endpoint);
114            producer = endpoint.createProducer();
115            // add and start producer
116            getCamelContext().addService(producer, true, true);
117            Class<?> clazz = blueprintContainer.loadClass(getServiceInterface());
118            serviceProxy = ProxyHelper.createProxy(endpoint, bind, producer, clazz);
119        } catch (Exception e) {
120            throw new FailedToCreateProducerException(endpoint, e);
121        }
122    }
123
124    public void destroy() throws Exception {
125        // we let CamelContext manage the lifecycle of the producer and shut it down when Camel stops
126    }
127
128    public String getServiceUrl() {
129        return serviceUrl;
130    }
131
132    public void setServiceUrl(String serviceUrl) {
133        this.serviceUrl = serviceUrl;
134    }
135
136    public String getServiceRef() {
137        return serviceRef;
138    }
139
140    public void setServiceRef(String serviceRef) {
141        this.serviceRef = serviceRef;
142    }
143
144    public Boolean getBinding() {
145        return binding;
146    }
147
148    public void setBinding(Boolean binding) {
149        this.binding = binding;
150    }
151
152    public String getServiceInterface() {
153        return serviceInterface;
154    }
155
156    public void setServiceInterface(String serviceInterface) {
157        this.serviceInterface = serviceInterface;
158    }
159
160    public Endpoint getEndpoint() {
161        return endpoint;
162    }
163
164    public void setEndpoint(Endpoint endpoint) {
165        this.endpoint = endpoint;
166    }
167
168    public Producer getProducer() {
169        return producer;
170    }
171
172    public void setProducer(Producer producer) {
173        this.producer = producer;
174    }
175
176    public ExtendedBlueprintContainer getBlueprintContainer() {
177        return blueprintContainer;
178    }
179
180    public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
181        this.blueprintContainer = blueprintContainer;
182    }
183
184}