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