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.impl.MainSupport;
028 import org.apache.camel.spring.handler.CamelNamespaceHandler;
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: 758539 $
042 */
043 public class Main extends MainSupport {
044 protected 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 public static void main(String... args) {
094 Main main = new Main();
095 instance = main;
096 main.enableHangupSupport();
097 main.run(args);
098 }
099
100 /**
101 * Returns the currently executing main
102 *
103 * @return the current running instance
104 */
105 public static Main getInstance() {
106 return instance;
107 }
108
109 /**
110 * Enables the hangup support. Gracefully stops by calling stop() on a
111 * Hangup signal.
112 */
113 public void enableHangupSupport() {
114 HangupInterceptor interceptor = new HangupInterceptor(this);
115 Runtime.getRuntime().addShutdownHook(interceptor);
116 }
117
118 @Override
119 public void enableDebug() {
120 super.enableDebug();
121 setParentApplicationContextUri("/META-INF/services/org/apache/camel/spring/debug.xml");
122 }
123
124 @Override
125 public void enableTrace() {
126 super.enableTrace();
127 setParentApplicationContextUri("/META-INF/services/org/apache/camel/spring/trace.xml");
128 }
129
130 // Properties
131 // -------------------------------------------------------------------------
132 public AbstractApplicationContext getApplicationContext() {
133 return applicationContext;
134 }
135
136 public void setApplicationContext(AbstractApplicationContext applicationContext) {
137 this.applicationContext = applicationContext;
138 }
139
140 public String getApplicationContextUri() {
141 return applicationContextUri;
142 }
143
144 public void setApplicationContextUri(String applicationContextUri) {
145 this.applicationContextUri = applicationContextUri;
146 }
147
148 public String getFileApplicationContextUri() {
149 return fileApplicationContextUri;
150 }
151
152 public void setFileApplicationContextUri(String fileApplicationContextUri) {
153 this.fileApplicationContextUri = fileApplicationContextUri;
154 }
155
156 public AbstractApplicationContext getParentApplicationContext() {
157 if (parentApplicationContext == null) {
158 if (parentApplicationContextUri != null) {
159 parentApplicationContext = new ClassPathXmlApplicationContext(parentApplicationContextUri);
160 parentApplicationContext.start();
161 }
162 }
163 return parentApplicationContext;
164 }
165
166 public void setParentApplicationContext(AbstractApplicationContext parentApplicationContext) {
167 this.parentApplicationContext = parentApplicationContext;
168 }
169
170 public String getParentApplicationContextUri() {
171 return parentApplicationContextUri;
172 }
173
174 public void setParentApplicationContextUri(String parentApplicationContextUri) {
175 this.parentApplicationContextUri = parentApplicationContextUri;
176 }
177
178 // Implementation methods
179 // -------------------------------------------------------------------------
180
181 @Override
182 protected void doStart() throws Exception {
183 super.doStart();
184 if (applicationContext == null) {
185 applicationContext = createDefaultApplicationContext();
186 }
187 LOG.debug("Starting Spring ApplicationContext: " + applicationContext.getId());
188 applicationContext.start();
189
190 postProcessContext();
191 }
192
193 protected void doStop() throws Exception {
194 super.doStop();
195 if (applicationContext != null) {
196 LOG.debug("Stopping Spring ApplicationContext: " + applicationContext.getId());
197 applicationContext.close();
198 }
199 }
200
201 protected ProducerTemplate findOrCreateCamelTemplate() {
202 String[] names = getApplicationContext().getBeanNamesForType(ProducerTemplate.class);
203 if (names != null && names.length > 0) {
204 return (ProducerTemplate) getApplicationContext().getBean(names[0], ProducerTemplate.class);
205 }
206 for (CamelContext camelContext : getCamelContexts()) {
207 return camelContext.createProducerTemplate();
208 }
209 throw new IllegalArgumentException("No CamelContexts are available so cannot create a ProducerTemplate!");
210 }
211
212 protected AbstractApplicationContext createDefaultApplicationContext() {
213 // file based
214 if (getFileApplicationContextUri() != null) {
215 String[] args = getFileApplicationContextUri().split(";");
216
217 ApplicationContext parentContext = getParentApplicationContext();
218 if (parentContext != null) {
219 return new FileSystemXmlApplicationContext(args, parentContext);
220 } else {
221 return new FileSystemXmlApplicationContext(args);
222 }
223 }
224
225 // default to classpath based
226 String[] args = getApplicationContextUri().split(";");
227 ApplicationContext parentContext = getParentApplicationContext();
228 if (parentContext != null) {
229 return new ClassPathXmlApplicationContext(args, parentContext);
230 } else {
231 return new ClassPathXmlApplicationContext(args);
232 }
233 }
234
235 @SuppressWarnings("unchecked")
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 }