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.model;
018
019import java.util.List;
020import javax.xml.bind.annotation.XmlAccessType;
021import javax.xml.bind.annotation.XmlAccessorType;
022import javax.xml.bind.annotation.XmlTransient;
023import javax.xml.bind.annotation.XmlType;
024
025import org.apache.camel.AsyncCallback;
026import org.apache.camel.Exchange;
027import org.apache.camel.Processor;
028import org.apache.camel.processor.loadbalancer.LoadBalancer;
029import org.apache.camel.spi.RouteContext;
030import org.apache.camel.util.IntrospectionSupport;
031import org.apache.camel.util.ObjectHelper;
032
033/**
034 * Represents an XML <loadBalancer/> element
035 */
036@XmlType(name = "loadBalancer")
037@XmlAccessorType(XmlAccessType.FIELD)
038public class LoadBalancerDefinition extends IdentifiedType implements LoadBalancer {
039    @XmlTransient
040    private LoadBalancer loadBalancer;
041    @XmlTransient
042    private String loadBalancerTypeName;
043
044    public LoadBalancerDefinition() {
045    }
046
047    public LoadBalancerDefinition(LoadBalancer loadBalancer) {
048        this.loadBalancer = loadBalancer;
049    }
050
051    protected LoadBalancerDefinition(String loadBalancerTypeName) {
052        this.loadBalancerTypeName = loadBalancerTypeName;
053    }
054
055    public static LoadBalancer getLoadBalancer(RouteContext routeContext, LoadBalancerDefinition type, String ref) {
056        if (type == null) {
057            ObjectHelper.notNull(ref, "ref or loadBalancer");
058            LoadBalancer loadBalancer = routeContext.mandatoryLookup(ref, LoadBalancer.class);
059            if (loadBalancer instanceof LoadBalancerDefinition) {
060                type = (LoadBalancerDefinition) loadBalancer;
061            } else {
062                return loadBalancer;
063            }
064        }
065        return type.getLoadBalancer(routeContext);
066    }
067
068
069    /**
070     * Sets a named property on the data format instance using introspection
071     */
072    protected void setProperty(Object bean, String name, Object value) {
073        try {
074            IntrospectionSupport.setProperty(bean, name, value);
075        } catch (Exception e) {
076            throw new IllegalArgumentException("Failed to set property " + name + " on " + bean + ". Reason: " + e, e);
077        }
078    }
079
080    /**
081     * Allows derived classes to customize the load balancer
082     */
083    protected void configureLoadBalancer(LoadBalancer loadBalancer) {
084    }
085
086    public LoadBalancer getLoadBalancer(RouteContext routeContext) {
087        if (loadBalancer == null) {
088            loadBalancer = createLoadBalancer(routeContext);
089            ObjectHelper.notNull(loadBalancer, "loadBalancer");
090            configureLoadBalancer(loadBalancer);
091        }
092        return loadBalancer;
093    }
094
095    /**
096     * Factory method to create the load balancer instance
097     */
098    protected LoadBalancer createLoadBalancer(RouteContext routeContext) {
099        if (loadBalancerTypeName != null) {
100            Class<?> type = routeContext.getCamelContext().getClassResolver().resolveClass(loadBalancerTypeName);
101            if (type == null) {
102                throw new IllegalArgumentException("Cannot find class: " + loadBalancerTypeName + " in the classpath");
103            }
104            return (LoadBalancer) ObjectHelper.newInstance(type);
105        }
106        return null;
107    }
108
109
110    public void addProcessor(Processor processor) {
111        ObjectHelper.notNull(loadBalancer, "loadBalancer", this);
112        loadBalancer.addProcessor(processor);
113    }
114
115    public List<Processor> getProcessors() {
116        ObjectHelper.notNull(loadBalancer, "loadBalancer", this);
117        return loadBalancer.getProcessors();
118    }
119
120    public void removeProcessor(Processor processor) {
121        ObjectHelper.notNull(loadBalancer, "loadBalancer", this);
122        loadBalancer.removeProcessor(processor);
123    }
124
125    public void process(Exchange exchange) throws Exception {
126        ObjectHelper.notNull(loadBalancer, "loadBalancer", this);
127        loadBalancer.process(exchange);
128    }
129
130    public boolean process(Exchange exchange, final AsyncCallback callback) {
131        ObjectHelper.notNull(loadBalancer, "loadBalancer");
132        return loadBalancer.process(exchange, new AsyncCallback() {
133            public void done(boolean doneSync) {
134                // only handle the async case
135                if (doneSync) {
136                    return;
137                } else {
138                    callback.done(false);
139                }
140            }
141        });
142    }
143
144    @Override
145    public String toString() {
146        if (loadBalancer != null) {
147            return loadBalancer.toString();
148        } else {
149            return loadBalancerTypeName;
150        }
151    }
152}