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.guice.maven;
018
019 import java.io.File;
020 import java.lang.reflect.InvocationTargetException;
021 import java.lang.reflect.Method;
022 import java.net.MalformedURLException;
023 import java.net.URL;
024 import java.net.URLClassLoader;
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.List;
028
029 import org.apache.maven.plugin.MojoExecutionException;
030 import org.codehaus.mojo.exec.AbstractExecMojo;
031
032 /**
033 * Runs a Camel using the
034 * <code>jndi.properties</code> file on the classpath to
035 * way to <a href="http://camel.apache.org/guice.html">bootstrap via Guice</a>
036 *
037 * @goal embedded
038 * @requiresDependencyResolution runtime
039 * @execute phase="test-compile"
040 */
041 public class EmbeddedMojo extends AbstractExecMojo {
042
043 /**
044 * The duration to run the application for which by default is in milliseconds.
045 * A value <= 0 will run forever.
046 * Adding a s indicates seconds - eg "5s" means 5 seconds.
047 *
048 * @parameter expression="-1"
049 * @readonly
050 */
051 protected String duration;
052
053 /**
054 * The DOT File name used to generate the DOT diagram of the route definitions
055 *
056 * @parameter expression="${project.build.directory}/site/cameldoc/routes.dot"
057 * @readonly
058 */
059 protected String outputDirectory;
060
061 /**
062 * Allows the DOT file generation to be disabled
063 *
064 * @parameter expression="true"
065 * @readonly
066 */
067 protected boolean dotEnabled;
068
069 /**
070 * Allows the routes from multiple contexts to be aggregated into one DOT file (in addition to the individual files)
071 *
072 * @parameter expression="false"
073 * @readonly
074 */
075 protected boolean dotAggregationEnabled;
076
077 /**
078 * Project classpath.
079 *
080 * @parameter expression="${project.testClasspathElements}"
081 * @required
082 * @readonly
083 */
084 private List classpathElements;
085
086 /**
087 * The main class to execute.
088 *
089 * @parameter expression="${camel.mainClass}"
090 * default-value="org.apache.camel.guice.Main"
091 * @required
092 */
093 private String mainClass;
094
095 /**
096 * This method will run the mojo
097 */
098 public void execute() throws MojoExecutionException {
099 try {
100 executeWithoutWrapping();
101 } catch (Exception e) {
102 throw new MojoExecutionException("Failed: " + e, e);
103 }
104 }
105
106 public void executeWithoutWrapping() throws MalformedURLException, ClassNotFoundException,
107 NoSuchMethodException, IllegalAccessException, MojoExecutionException {
108 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
109 try {
110 ClassLoader newLoader = createClassLoader(null);
111 Thread.currentThread().setContextClassLoader(newLoader);
112 runCamel(newLoader);
113 } finally {
114 Thread.currentThread().setContextClassLoader(oldClassLoader);
115 }
116 }
117
118 // Properties
119 //-------------------------------------------------------------------------
120
121 /**
122 * Getter for property output directory.
123 *
124 * @return The value of output directory.
125 */
126 public String getOutputDirectory() {
127 return outputDirectory;
128 }
129
130 /**
131 * Setter for the output directory.
132 *
133 * @param inOutputDirectory The value of output directory.
134 */
135 public void setOutputDirectory(String inOutputDirectory) {
136 this.outputDirectory = inOutputDirectory;
137 }
138
139 public List getClasspathElements() {
140 return classpathElements;
141 }
142
143 public void setClasspathElements(List classpathElements) {
144 this.classpathElements = classpathElements;
145 }
146
147 public boolean isDotEnabled() {
148 return dotEnabled;
149 }
150
151 public void setDotEnabled(boolean dotEnabled) {
152 this.dotEnabled = dotEnabled;
153 }
154
155 public String getDuration() {
156 return duration;
157 }
158
159 public void setDuration(String duration) {
160 this.duration = duration;
161 }
162
163 public boolean isDotAggregationEnabled() {
164 return dotAggregationEnabled;
165 }
166
167 public void setDotAggregationEnabled(boolean dotAggregationEnabled) {
168 this.dotAggregationEnabled = dotAggregationEnabled;
169 }
170
171 public String getMainClass() {
172 return mainClass;
173 }
174
175 public void setMainClass(String mainClass) {
176 this.mainClass = mainClass;
177 }
178
179 // Implementation methods
180 //-------------------------------------------------------------------------
181
182 protected void runCamel(ClassLoader newLoader) throws ClassNotFoundException, NoSuchMethodException,
183 IllegalAccessException, MojoExecutionException {
184
185 getLog().debug("Running Camel in: " + newLoader);
186 Class<?> type = newLoader.loadClass(mainClass);
187 Method method = type.getMethod("main", String[].class);
188 String[] arguments = createArguments();
189 getLog().debug("Starting the Camel Main with arguments: " + Arrays.asList(arguments));
190
191 try {
192 method.invoke(null, new Object[] {arguments});
193 } catch (InvocationTargetException e) {
194 Throwable t = e.getTargetException();
195 throw new MojoExecutionException("Failed: " + t, t);
196 }
197 }
198
199 protected String[] createArguments() {
200
201 ArrayList<String> args = new ArrayList<String>(5);
202 if (isDotEnabled()) {
203 args.add("-outdir");
204 args.add(getOutputDirectory());
205 }
206
207 if (isDotAggregationEnabled()) {
208 args.add("-aggregate-dot");
209 args.add("true");
210 }
211
212 args.add("-duration");
213 args.add(getDuration());
214
215 return args.toArray(new String[0]);
216 }
217
218 public ClassLoader createClassLoader(ClassLoader parent) throws MalformedURLException {
219 getLog().debug("Using classpath: " + classpathElements);
220
221 int size = classpathElements.size();
222 URL[] urls = new URL[size];
223 for (int i = 0; i < size; i++) {
224 String name = (String) classpathElements.get(i);
225 File file = new File(name);
226 urls[i] = file.toURL();
227 getLog().debug("URL: " + urls[i]);
228 }
229 URLClassLoader loader = new URLClassLoader(urls, parent);
230 return loader;
231 }
232 }