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