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 }