1 package org.apache.tomcat.maven.plugin.tomcat7.run;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.catalina.loader.WebappLoader;
22 import org.apache.commons.io.FileUtils;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.maven.artifact.Artifact;
25 import org.apache.maven.plugin.MojoExecutionException;
26 import org.apache.maven.plugins.annotations.Component;
27 import org.apache.maven.plugins.annotations.Execute;
28 import org.apache.maven.plugins.annotations.LifecyclePhase;
29 import org.apache.maven.plugins.annotations.Mojo;
30 import org.apache.maven.plugins.annotations.Parameter;
31 import org.apache.maven.plugins.annotations.ResolutionScope;
32 import org.apache.maven.shared.filtering.MavenFileFilter;
33 import org.apache.maven.shared.filtering.MavenFileFilterRequest;
34 import org.apache.maven.shared.filtering.MavenFilteringException;
35 import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculator;
36 import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculatorRequest;
37 import org.apache.tomcat.maven.common.run.ClassLoaderEntriesCalculatorResult;
38 import org.apache.tomcat.maven.common.run.TomcatRunException;
39 import org.codehaus.plexus.util.IOUtil;
40 import org.codehaus.plexus.util.xml.Xpp3Dom;
41 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
42 import org.codehaus.plexus.util.xml.Xpp3DomWriter;
43 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
44
45 import java.io.File;
46 import java.io.FileReader;
47 import java.io.FileWriter;
48 import java.io.IOException;
49 import java.io.StringWriter;
50 import java.util.List;
51 import java.util.Set;
52
53
54
55
56
57
58
59 @Mojo( name = "run", requiresDependencyResolution = ResolutionScope.TEST )
60 @Execute( phase = LifecyclePhase.PROCESS_CLASSES )
61 public class RunMojo
62 extends AbstractRunMojo
63 {
64
65
66
67
68
69
70
71
72 @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true )
73 private Set<Artifact> dependencies;
74
75
76
77
78 @Parameter( defaultValue = "${basedir}/src/main/webapp", property = "tomcat.warSourceDirectory" )
79 private File warSourceDirectory;
80
81
82
83
84
85
86
87
88 @Parameter( property = "tomcat.delegate", defaultValue = "true" )
89 private boolean delegate = true;
90
91
92
93
94 @Component
95 private ClassLoaderEntriesCalculator classLoaderEntriesCalculator;
96
97
98
99
100
101
102 @Parameter( property = "maven.tomcat.addWarDependenciesInClassloader", defaultValue = "true" )
103 private boolean addWarDependenciesInClassloader;
104
105
106
107
108
109
110 @Parameter( property = "maven.tomcat.useTestClasspath", defaultValue = "false" )
111 private boolean useTestClasspath;
112
113
114
115
116
117
118 @Parameter( alias = "additionalClassesDirs" )
119 private List<String> additionalClasspathDirs;
120
121
122
123
124 @Override
125 protected File getDocBase()
126 {
127 return warSourceDirectory;
128 }
129
130
131
132
133 @Override
134 protected File getContextFile()
135 throws MojoExecutionException
136 {
137 File temporaryContextFile = null;
138
139
140
141
142
143
144 FileReader fr = null;
145 FileWriter fw = null;
146 StringWriter sw = new StringWriter();
147 try
148 {
149 temporaryContextFile = File.createTempFile( "tomcat-maven-plugin", "temp-ctx-file" );
150 temporaryContextFile.deleteOnExit();
151
152
153 if ( contextFile != null && contextFile.exists() )
154 {
155 MavenFileFilterRequest mavenFileFilterRequest = new MavenFileFilterRequest();
156 mavenFileFilterRequest.setFrom( contextFile );
157 mavenFileFilterRequest.setTo( temporaryContextFile );
158 mavenFileFilterRequest.setMavenProject( project );
159 mavenFileFilterRequest.setMavenSession( session );
160 mavenFileFilterRequest.setFiltering( true );
161
162 mavenFileFilter.copyFile( mavenFileFilterRequest );
163
164 fr = new FileReader( temporaryContextFile );
165 Xpp3Dom xpp3Dom = Xpp3DomBuilder.build( fr );
166 xpp3Dom.setAttribute( "backgroundProcessorDelay", Integer.toString( backgroundProcessorDelay ) );
167 xpp3Dom.setAttribute( "reloadable", Boolean.toString( isContextReloadable() ) );
168 fw = new FileWriter( temporaryContextFile );
169 Xpp3DomWriter.write( fw, xpp3Dom );
170 Xpp3DomWriter.write( sw, xpp3Dom );
171 getLog().debug( " generated context file " + sw.toString() );
172 }
173 else
174 {
175 if ( contextReloadable )
176 {
177
178 StringBuilder sb = new StringBuilder( "<Context " ).append( "backgroundProcessorDelay=\"" ).append(
179 Integer.toString( backgroundProcessorDelay ) ).append( "\"" ).append(
180 " reloadable=\"" + Boolean.toString( isContextReloadable() ) + "\"/>" );
181
182 getLog().debug( " generated context file " + sb.toString() );
183 fw = new FileWriter( temporaryContextFile );
184 fw.write( sb.toString() );
185 }
186 else
187 {
188
189 return null;
190 }
191 }
192 }
193 catch ( IOException e )
194 {
195 getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
196 throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
197 }
198 catch ( XmlPullParserException e )
199 {
200 getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
201 throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
202 }
203 catch ( MavenFilteringException e )
204 {
205 getLog().error( "error filtering context.xml : " + e.getMessage(), e );
206 throw new MojoExecutionException( "error filtering context.xml : " + e.getMessage(), e );
207 }
208 finally
209 {
210 IOUtil.close( fw );
211 IOUtil.close( fr );
212 IOUtil.close( sw );
213 }
214
215 return temporaryContextFile;
216 }
217
218
219
220
221
222
223 @Override
224 protected WebappLoader createWebappLoader()
225 throws IOException, MojoExecutionException
226 {
227 WebappLoader loader = super.createWebappLoader();
228 if ( useSeparateTomcatClassLoader )
229 {
230 loader.setDelegate( delegate );
231 }
232
233 try
234 {
235 ClassLoaderEntriesCalculatorRequest request =
236 new ClassLoaderEntriesCalculatorRequest().setDependencies( dependencies ).setLog(
237 getLog() ).setMavenProject( project ).setAddWarDependenciesInClassloader(
238 addWarDependenciesInClassloader ).setUseTestClassPath( useTestClasspath );
239 ClassLoaderEntriesCalculatorResult classLoaderEntriesCalculatorResult =
240 classLoaderEntriesCalculator.calculateClassPathEntries( request );
241 List<String> classLoaderEntries = classLoaderEntriesCalculatorResult.getClassPathEntries();
242 final List<File> tmpDirectories = classLoaderEntriesCalculatorResult.getTmpDirectories();
243
244 Runtime.getRuntime().addShutdownHook( new Thread()
245 {
246 @Override
247 public void run()
248 {
249 for ( File tmpDir : tmpDirectories )
250 {
251 try
252 {
253 FileUtils.deleteDirectory( tmpDir );
254 }
255 catch ( IOException e )
256 {
257
258 }
259 }
260 }
261 } );
262
263 if ( classLoaderEntries != null )
264 {
265 for ( String classLoaderEntry : classLoaderEntries )
266 {
267 loader.addRepository( classLoaderEntry );
268 }
269 }
270
271 if ( additionalClasspathDirs != null && !additionalClasspathDirs.isEmpty() )
272 {
273 for ( String additionalClasspathDir : additionalClasspathDirs )
274 {
275 if ( StringUtils.isNotBlank( additionalClasspathDir ) )
276 {
277 File file = new File( additionalClasspathDir );
278 if ( file.exists() )
279 {
280 String fileUri = file.toURI().toString();
281 getLog().debug( "add file:" + fileUri + " as a additionalClasspathDir" );
282 loader.addRepository( fileUri );
283 }
284 }
285 }
286 }
287 }
288 catch ( TomcatRunException e )
289 {
290 throw new MojoExecutionException( e.getMessage(), e );
291 }
292
293 return loader;
294 }
295 }