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.spring;
018    
019    import java.util.HashMap;
020    import java.util.LinkedList;
021    import java.util.Map;
022    import java.util.Set;
023    import javax.xml.bind.JAXBException;
024    
025    import org.apache.camel.CamelContext;
026    import org.apache.camel.ProducerTemplate;
027    import org.apache.camel.spring.handler.CamelNamespaceHandler;
028    import org.apache.camel.util.MainSupport;
029    import org.apache.camel.view.ModelFileGenerator;
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.springframework.context.ApplicationContext;
033    import org.springframework.context.support.AbstractApplicationContext;
034    import org.springframework.context.support.ClassPathXmlApplicationContext;
035    import org.springframework.context.support.FileSystemXmlApplicationContext;
036    
037    /**
038     * A command line tool for booting up a CamelContext using an optional Spring
039     * ApplicationContext
040     *
041     * @version $Revision: 735424 $
042     */
043    public class Main extends MainSupport {
044        private static Main instance;
045    
046        private String applicationContextUri = "META-INF/spring/*.xml";
047        private String fileApplicationContextUri;
048        private AbstractApplicationContext applicationContext;
049        private AbstractApplicationContext parentApplicationContext;
050        private String parentApplicationContextUri;
051    
052        public Main() {
053    
054            addOption(new ParameterOption("ac", "applicationContext",
055                    "Sets the classpath based spring ApplicationContext", "applicationContext") {
056                protected void doProcess(String arg, String parameter, LinkedList<String> remainingArgs) {
057                    setApplicationContextUri(parameter);
058                }
059            });
060    
061            addOption(new ParameterOption("fa", "fileApplicationContext",
062                    "Sets the filesystem based spring ApplicationContext", "fileApplicationContext") {
063                protected void doProcess(String arg, String parameter, LinkedList<String> remainingArgs) {
064                    setFileApplicationContextUri(parameter);
065                }
066            });
067    
068        }
069        
070        /**
071         * A class for intercepting the hang up signal and do a graceful shutdown of
072         * the Camel.
073         */
074        private class HangupInterceptor extends Thread {
075            Log log = LogFactory.getLog(this.getClass());
076            Main mainInstance;
077    
078            public HangupInterceptor(Main main) {
079                mainInstance = main;
080            }
081    
082            @Override
083            public void run() {
084                log.info("Recieved hang up - stopping the main instance.");
085                try {
086                    mainInstance.stop();
087                } catch (Exception ex) {
088                    log.warn(ex);
089                }
090            }
091        }
092    
093    
094        public static void main(String... args) {
095            Main main = new Main();
096            instance = main;
097            main.enableHangupSupport();
098            main.run(args);
099        }
100    
101        /**
102         * Returns the currently executing main
103         *
104         * @return the current running instance
105         */
106        public static Main getInstance() {
107            return instance;
108        }
109        
110        /**
111         * Enables the hangup support. Gracefully stops by calling stop() on a
112         * Hangup signal.
113         */
114        public void enableHangupSupport() {
115            HangupInterceptor interceptor = new HangupInterceptor(this);
116            Runtime.getRuntime().addShutdownHook(interceptor);
117        }
118    
119        @Override
120        public void enableDebug() {
121            super.enableDebug();
122            setParentApplicationContextUri("/META-INF/services/org/apache/camel/spring/debug.xml");
123        }
124    
125        @Override
126        public void enableTrace() {
127            super.enableTrace();
128            setParentApplicationContextUri("/META-INF/services/org/apache/camel/spring/trace.xml");
129        }
130    
131        // Properties
132        // -------------------------------------------------------------------------
133        public AbstractApplicationContext getApplicationContext() {
134            return applicationContext;
135        }
136    
137        public void setApplicationContext(AbstractApplicationContext applicationContext) {
138            this.applicationContext = applicationContext;
139        }
140    
141        public String getApplicationContextUri() {
142            return applicationContextUri;
143        }
144    
145        public void setApplicationContextUri(String applicationContextUri) {
146            this.applicationContextUri = applicationContextUri;
147        }
148    
149        public String getFileApplicationContextUri() {
150            return fileApplicationContextUri;
151        }
152    
153        public void setFileApplicationContextUri(String fileApplicationContextUri) {
154            this.fileApplicationContextUri = fileApplicationContextUri;
155        }
156    
157        public AbstractApplicationContext getParentApplicationContext() {
158            if (parentApplicationContext == null) {
159                if (parentApplicationContextUri != null) {
160                    parentApplicationContext = new ClassPathXmlApplicationContext(parentApplicationContextUri);
161                    parentApplicationContext.start();
162                }
163            }
164            return parentApplicationContext;
165        }
166    
167        public void setParentApplicationContext(AbstractApplicationContext parentApplicationContext) {
168            this.parentApplicationContext = parentApplicationContext;
169        }
170    
171        public String getParentApplicationContextUri() {
172            return parentApplicationContextUri;
173        }
174    
175        public void setParentApplicationContextUri(String parentApplicationContextUri) {
176            this.parentApplicationContextUri = parentApplicationContextUri;
177        }
178    
179        // Implementation methods
180        // -------------------------------------------------------------------------
181    
182        @Override
183        protected void doStart() throws Exception {
184            super.doStart();
185            if (applicationContext == null) {
186                applicationContext = createDefaultApplicationContext();
187            }
188            LOG.debug("Starting Spring ApplicationContext: " + applicationContext.getId());
189            applicationContext.start();
190    
191            postProcessContext();
192        }
193    
194        protected void doStop() throws Exception {
195            super.doStop();
196            if (applicationContext != null) {
197                LOG.debug("Stopping Spring ApplicationContext: " + applicationContext.getId());
198                applicationContext.close();
199            }
200        }
201    
202        protected ProducerTemplate findOrCreateCamelTemplate() {
203            String[] names = getApplicationContext().getBeanNamesForType(ProducerTemplate.class);
204            if (names != null && names.length > 0) {
205                return (ProducerTemplate) getApplicationContext().getBean(names[0], ProducerTemplate.class);
206            }
207            for (CamelContext camelContext : getCamelContexts()) {
208                return camelContext.createProducerTemplate();
209            }
210            throw new IllegalArgumentException("No CamelContexts are available so cannot create a ProducerTemplate!");
211        }
212    
213        protected AbstractApplicationContext createDefaultApplicationContext() {
214            // file based
215            if (getFileApplicationContextUri() != null) {
216                String[] args = getFileApplicationContextUri().split(";");
217    
218                ApplicationContext parentContext = getParentApplicationContext();
219                if (parentContext != null) {
220                    return new FileSystemXmlApplicationContext(args, parentContext);
221                } else {
222                    return new FileSystemXmlApplicationContext(args);
223                }
224            }
225    
226            // default to classpath based
227            String[] args = getApplicationContextUri().split(";");
228            ApplicationContext parentContext = getParentApplicationContext();
229            if (parentContext != null) {
230                return new ClassPathXmlApplicationContext(args, parentContext);
231            } else {
232                return new ClassPathXmlApplicationContext(args);
233            }
234        }
235    
236        protected Map<String, CamelContext> getCamelContextMap() {
237            Map<String, SpringCamelContext> map = applicationContext.getBeansOfType(SpringCamelContext.class);
238            Set<Map.Entry<String, SpringCamelContext>> entries = map.entrySet();
239            Map<String, CamelContext> answer = new HashMap<String, CamelContext>();
240            for (Map.Entry<String, SpringCamelContext> entry : entries) {
241                String name = entry.getKey();
242                CamelContext camelContext = entry.getValue();
243                answer.put(name, camelContext);
244            }
245            return answer;
246        }
247    
248        protected ModelFileGenerator createModelFileGenerator() throws JAXBException {
249            return new ModelFileGenerator(new CamelNamespaceHandler().getJaxbContext());
250        }
251    }