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