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.COMPILE )
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
95
96 @Parameter( property = "maven.tomcat.backgroundProcessorDelay", defaultValue = "-1" )
97 protected int backgroundProcessorDelay = -1;
98
99
100
101
102 @Component
103 private ClassLoaderEntriesCalculator classLoaderEntriesCalculator;
104
105
106
107
108
109
110 @Parameter( property = "maven.tomcat.addWarDependenciesInClassloader", defaultValue = "true" )
111 private boolean addWarDependenciesInClassloader;
112
113
114
115
116
117
118 @Parameter( property = "maven.tomcat.useTestClasspath", defaultValue = "false" )
119 private boolean useTestClasspath;
120
121
122
123
124
125
126 @Parameter( alias = "additionalClassesDirs" )
127 private List<String> additionalClasspathDirs;
128
129 @Component( role = MavenFileFilter.class, hint = "default" )
130 private MavenFileFilter mavenFileFilter;
131
132
133
134
135 @Override
136 protected File getDocBase()
137 {
138 return warSourceDirectory;
139 }
140
141
142
143
144 @Override
145 protected File getContextFile()
146 throws MojoExecutionException
147 {
148 File temporaryContextFile = null;
149
150
151
152
153
154
155 FileReader fr = null;
156 FileWriter fw = null;
157 StringWriter sw = new StringWriter();
158 try
159 {
160 temporaryContextFile = File.createTempFile( "tomcat-maven-plugin", "temp-ctx-file" );
161 temporaryContextFile.deleteOnExit();
162
163
164 if ( contextFile != null && contextFile.exists() )
165 {
166 MavenFileFilterRequest mavenFileFilterRequest = new MavenFileFilterRequest();
167 mavenFileFilterRequest.setFrom( contextFile );
168 mavenFileFilterRequest.setTo( temporaryContextFile );
169 mavenFileFilterRequest.setMavenProject( project );
170 mavenFileFilterRequest.setMavenSession( session );
171 mavenFileFilterRequest.setFiltering( true );
172
173 mavenFileFilter.copyFile( mavenFileFilterRequest );
174
175 fr = new FileReader( temporaryContextFile );
176 Xpp3Dom xpp3Dom = Xpp3DomBuilder.build( fr );
177 xpp3Dom.setAttribute( "backgroundProcessorDelay", Integer.toString( backgroundProcessorDelay ) );
178 xpp3Dom.setAttribute( "reloadable", Boolean.toString( isContextReloadable() ) );
179 fw = new FileWriter( temporaryContextFile );
180 Xpp3DomWriter.write( fw, xpp3Dom );
181 Xpp3DomWriter.write( sw, xpp3Dom );
182 getLog().debug( " generated context file " + sw.toString() );
183 }
184 else
185 {
186 if ( contextReloadable )
187 {
188
189 StringBuilder sb = new StringBuilder( "<Context " ).append( "backgroundProcessorDelay=\"" ).append(
190 Integer.toString( backgroundProcessorDelay ) ).append( "\"" ).append(
191 " reloadable=\"" + Boolean.toString( isContextReloadable() ) + "\"/>" );
192
193 getLog().debug( " generated context file " + sb.toString() );
194
195 fw.write( sb.toString() );
196 }
197 else
198 {
199
200 return null;
201 }
202 }
203 }
204 catch ( IOException e )
205 {
206 getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
207 throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
208 }
209 catch ( XmlPullParserException e )
210 {
211 getLog().error( "error creating fake context.xml : " + e.getMessage(), e );
212 throw new MojoExecutionException( "error creating fake context.xml : " + e.getMessage(), e );
213 }
214 catch ( MavenFilteringException e )
215 {
216 getLog().error( "error filtering context.xml : " + e.getMessage(), e );
217 throw new MojoExecutionException( "error filtering context.xml : " + e.getMessage(), e );
218 }
219 finally
220 {
221 IOUtil.close( fw );
222 IOUtil.close( fr );
223 IOUtil.close( sw );
224 }
225
226 return temporaryContextFile;
227 }
228
229
230
231
232
233
234 @Override
235 protected WebappLoader createWebappLoader()
236 throws IOException, MojoExecutionException
237 {
238 WebappLoader loader = super.createWebappLoader();
239 if ( useSeparateTomcatClassLoader )
240 {
241 loader.setDelegate( delegate );
242 }
243
244 try
245 {
246 ClassLoaderEntriesCalculatorRequest request =
247 new ClassLoaderEntriesCalculatorRequest().setDependencies( dependencies ).setLog(
248 getLog() ).setMavenProject( project ).setAddWarDependenciesInClassloader(
249 addWarDependenciesInClassloader ).setUseTestClassPath( useTestClasspath );
250 ClassLoaderEntriesCalculatorResult classLoaderEntriesCalculatorResult =
251 classLoaderEntriesCalculator.calculateClassPathEntries( request );
252 List<String> classLoaderEntries = classLoaderEntriesCalculatorResult.getClassPathEntries();
253 final List<File> tmpDirectories = classLoaderEntriesCalculatorResult.getTmpDirectories();
254
255 Runtime.getRuntime().addShutdownHook( new Thread()
256 {
257 @Override
258 public void run()
259 {
260 for ( File tmpDir : tmpDirectories )
261 {
262 try
263 {
264 FileUtils.deleteDirectory( tmpDir );
265 }
266 catch ( IOException e )
267 {
268
269 }
270 }
271 }
272 } );
273
274 if ( classLoaderEntries != null )
275 {
276 for ( String classLoaderEntry : classLoaderEntries )
277 {
278 loader.addRepository( classLoaderEntry );
279 }
280 }
281
282 if ( additionalClasspathDirs != null && !additionalClasspathDirs.isEmpty() )
283 {
284 for ( String additionalClasspathDir : additionalClasspathDirs )
285 {
286 if ( StringUtils.isNotBlank( additionalClasspathDir ) )
287 {
288 File file = new File( additionalClasspathDir );
289 if ( file.exists() )
290 {
291 String fileUri = file.toURI().toString();
292 getLog().debug( "add file:" + fileUri + " as a additionalClasspathDir" );
293 loader.addRepository( fileUri );
294 }
295 }
296 }
297 }
298 }
299 catch ( TomcatRunException e )
300 {
301 throw new MojoExecutionException( e.getMessage(), e );
302 }
303
304 return loader;
305 }
306 }