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.ArrayList;
020 import java.util.Arrays;
021 import java.util.LinkedList;
022 import java.util.List;
023 import java.util.concurrent.CountDownLatch;
024 import java.util.concurrent.atomic.AtomicBoolean;
025
026 import org.apache.camel.impl.ServiceSupport;
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029
030 import org.springframework.context.support.AbstractApplicationContext;
031 import org.springframework.context.support.ClassPathXmlApplicationContext;
032
033 /**
034 * A command line tool for booting up a CamelContext using an optional Spring
035 * ApplicationContext
036 *
037 * @version $Revision: $
038 */
039 public class Main extends ServiceSupport {
040 private static final Log LOG = LogFactory.getLog(Main.class);
041 private String applicationContextUri = "META-INF/spring/*.xml";
042 private AbstractApplicationContext applicationContext;
043 private List<Option> options = new ArrayList<Option>();
044 private CountDownLatch latch = new CountDownLatch(1);
045 private AtomicBoolean completed = new AtomicBoolean(false);
046
047 public Main() {
048 addOption(new Option("h", "help", "Displays the help screen") {
049 protected void doProcess(String arg, LinkedList<String> remainingArgs) {
050 showOptions();
051 completed();
052 }
053 });
054
055 addOption(new ParameterOption("a", "applicationContext", "Sets the classpath based pring ApplicationContext", "applicationContext") {
056 protected void doProcess(String arg, String parameter, LinkedList<String> remainingArgs) {
057 setApplicationContextUri(parameter);
058 }
059 });
060 }
061
062 public static void main(String[] args) {
063 Main main = new Main();
064 main.run(args);
065 }
066
067 /**
068 * Parses the command line arguments then runs the program
069 */
070 public void run(String[] args) {
071 parseArguments(args);
072 run();
073 }
074
075 /**
076 * Runs this process with the given arguments
077 */
078 public void run() {
079 if (!completed.get()) {
080 try {
081 start();
082 waitUntilCompleted();
083 stop();
084 } catch (Exception e) {
085 LOG.error("Failed: " + e, e);
086 }
087 }
088 }
089
090 /**
091 * Marks this process as being completed
092 */
093 public void completed() {
094 completed.set(true);
095 latch.countDown();
096 }
097
098 /**
099 * Displays the command line options
100 */
101 public void showOptions() {
102 System.out.println("Apache Camel Runner takes the following options");
103 System.out.println();
104
105 for (Option option : options) {
106 System.out.println(" " + option.getAbbreviation() + " or " + option.getFullName() + " = " + option.getDescription());
107 }
108 }
109
110 /**
111 * Parses the commandl ine arguments
112 */
113 public void parseArguments(String[] arguments) {
114 LinkedList<String> args = new LinkedList<String>(Arrays.asList(arguments));
115
116 boolean valid = true;
117 while (!args.isEmpty()) {
118 String arg = args.removeFirst();
119
120 boolean handled = false;
121 for (Option option : options) {
122 if (option.processOption(arg, args)) {
123 handled = true;
124 break;
125 }
126 }
127 if (!handled) {
128 System.out.println("Unknown option: " + arg);
129 System.out.println();
130 valid = false;
131 break;
132 }
133 }
134 if (!valid) {
135 showOptions();
136 completed();
137 }
138 }
139
140 public void addOption(Option option) {
141 options.add(option);
142 }
143
144 public abstract class Option {
145 private String abbreviation;
146 private String fullName;
147 private String description;
148
149 protected Option(String abbreviation, String fullName, String description) {
150 this.abbreviation = "-" + abbreviation;
151 this.fullName = "-" + fullName;
152 this.description = description;
153 }
154
155 public boolean processOption(String arg, LinkedList<String> remainingArgs) {
156 if (arg.equalsIgnoreCase(abbreviation) || fullName.startsWith(arg)) {
157 doProcess(arg, remainingArgs);
158 return true;
159 }
160 return false;
161 }
162
163 public String getAbbreviation() {
164 return abbreviation;
165 }
166
167 public String getDescription() {
168 return description;
169 }
170
171 public String getFullName() {
172 return fullName;
173 }
174
175 protected abstract void doProcess(String arg, LinkedList<String> remainingArgs);
176 }
177
178 public abstract class ParameterOption extends Option {
179 private String parameterName;
180
181 protected ParameterOption(String abbreviation, String fullName, String description, String parameterName) {
182 super(abbreviation, fullName, description);
183 this.parameterName = parameterName;
184 }
185
186 protected void doProcess(String arg, LinkedList<String> remainingArgs) {
187 if (remainingArgs.isEmpty()) {
188 System.err.println("Expected fileName for ");
189 showOptions();
190 completed();
191 } else {
192 String parameter = remainingArgs.removeFirst();
193 doProcess(arg, parameter, remainingArgs);
194 }
195 }
196
197 protected abstract void doProcess(String arg, String parameter, LinkedList<String> remainingArgs);
198 }
199
200 // Properties
201 // -------------------------------------------------------------------------
202 public AbstractApplicationContext getApplicationContext() {
203 return applicationContext;
204 }
205
206 public void setApplicationContext(AbstractApplicationContext applicationContext) {
207 this.applicationContext = applicationContext;
208 }
209
210 public String getApplicationContextUri() {
211 return applicationContextUri;
212 }
213
214 public void setApplicationContextUri(String applicationContextUri) {
215 this.applicationContextUri = applicationContextUri;
216 }
217
218 // Implementation methods
219 // -------------------------------------------------------------------------
220 protected void doStart() throws Exception {
221 LOG.info("Apache Camel " + getVersion() + " starting");
222 if (applicationContext == null) {
223 applicationContext = createDefaultApplicationContext();
224 }
225 applicationContext.start();
226 }
227
228 protected AbstractApplicationContext createDefaultApplicationContext() {
229 return new ClassPathXmlApplicationContext(getApplicationContextUri());
230 }
231
232 protected void doStop() throws Exception {
233 LOG.info("Apache Camel terminating");
234
235 if (applicationContext != null) {
236 applicationContext.close();
237 }
238 }
239
240 protected void waitUntilCompleted() {
241 while (!completed.get()) {
242 try {
243 latch.await();
244 } catch (InterruptedException e) {
245 // ignore
246 }
247 }
248 }
249
250 protected String getVersion() {
251 Package aPackage = Package.getPackage("org.apache.camel");
252 if (aPackage != null) {
253 String version = aPackage.getImplementationVersion();
254 if (version == null) {
255 version = aPackage.getSpecificationVersion();
256 if (version == null) {
257 version = "";
258 }
259 }
260 return version;
261 }
262 return "";
263 }
264 }