1 | package npanday.plugin.aspx; |
2 | |
3 | /* |
4 | * Licensed to the Apache Software Foundation (ASF) under one |
5 | * or more contributor license agreements. See the NOTICE file |
6 | * distributed with this work for additional information |
7 | * regarding copyright ownership. The ASF licenses this file |
8 | * to you under the Apache License, Version 2.0 (the |
9 | * "License"); you may not use this file except in compliance |
10 | * with the License. You may obtain a copy of the License at |
11 | * |
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * |
14 | * Unless required by applicable law or agreed to in writing, |
15 | * software distributed under the License is distributed on an |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
17 | * KIND, either express or implied. See the License for the |
18 | * specific language governing permissions and limitations |
19 | * under the License. |
20 | */ |
21 | |
22 | import java.io.File; |
23 | import java.io.IOException; |
24 | import java.util.ArrayList; |
25 | import java.util.List; |
26 | |
27 | import npanday.ArtifactType; |
28 | import npanday.PlatformUnsupportedException; |
29 | import npanday.executable.ExecutionException; |
30 | import npanday.executable.compiler.CompilerConfig; |
31 | import npanday.executable.compiler.CompilerExecutable; |
32 | import npanday.executable.compiler.CompilerRequirement; |
33 | import npanday.vendor.VendorFactory; |
34 | import org.apache.maven.plugin.AbstractMojo; |
35 | import org.apache.maven.plugin.MojoExecutionException; |
36 | import org.apache.maven.project.MavenProject; |
37 | import org.codehaus.plexus.util.FileUtils; |
38 | import org.codehaus.plexus.util.StringUtils; |
39 | |
40 | /** |
41 | * Maven Mojo for precompiling ASPx files |
42 | * |
43 | * @goal compile |
44 | * @phase compile |
45 | * @description Maven Mojo for precompiling ASPx files |
46 | */ |
47 | public class AspxCompilerMojo |
48 | extends AbstractMojo |
49 | { |
50 | private static final String DEFAULT_INCLUDES = "**"; //any extension can be made for request handler in ASPX |
51 | |
52 | private static final String DEFAULT_EXCLUDES = "obj/**, target/**, **/*.pdb, **/*.csproj, **/*.vbproj, **/*.suo, **/*.user,pom.xml, **/*.sln,build.log,PrecompiledApp.config,csproj.user,Properties/**,**.releaseBackup,^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/**"; |
53 | |
54 | /** |
55 | * The maven project. |
56 | * |
57 | * @parameter expression="${project}" |
58 | * @required |
59 | */ |
60 | private MavenProject project; |
61 | |
62 | /** |
63 | * The directory for the compiled web application |
64 | * |
65 | * @parameter expression = "${outputDirectory}" default-value = "${project.build.directory}" |
66 | * @required |
67 | */ |
68 | private File outputDirectory; |
69 | |
70 | /** |
71 | * This over-rides the defaultAssemblyPath for the compiler plugin. |
72 | * |
73 | * @parameter expression = "${profileAssemblyPath} |
74 | */ |
75 | private File profileAssemblyPath; |
76 | |
77 | /** |
78 | * The location of the local Maven repository. |
79 | * |
80 | * @parameter expression="${settings.localRepository}" |
81 | */ |
82 | private File localRepository; |
83 | |
84 | /** |
85 | * .NET Language. The default value is <code>ASPX</code>. Not case or white-space sensitive. |
86 | * |
87 | * @parameter expression="${language}" default-value = "ASP" |
88 | * @required |
89 | */ |
90 | private String language; |
91 | |
92 | /** |
93 | * The framework version to compile under: 1.1, 2.0, 3.0 |
94 | * |
95 | * @parameter expression = "${frameworkVersion}" |
96 | */ |
97 | private String frameworkVersion; |
98 | |
99 | /** |
100 | * The profile that the compiler should use to compile classes: FULL, COMPACT, (or a custom one specified in a |
101 | * compiler-plugins.xml). |
102 | * |
103 | * @parameter expression = "${profile}" default-value = "FULL" |
104 | */ |
105 | private String profile; |
106 | |
107 | /** |
108 | * The Vendor for the Compiler. Not case or white-space sensitive. |
109 | * |
110 | * @parameter expression="${vendor}" |
111 | */ |
112 | private String vendor; |
113 | |
114 | /** |
115 | * @parameter expression = "${vendorVersion}" |
116 | */ |
117 | private String vendorVersion; |
118 | |
119 | /** |
120 | * The home directory of your .NET SDK. |
121 | * |
122 | * @parameter expression="${netHome}" |
123 | */ |
124 | private File netHome; |
125 | |
126 | /** |
127 | * Additional compiler commands |
128 | * |
129 | * @parameter expression = "${parameters}" |
130 | */ |
131 | private ArrayList<String> parameters; |
132 | |
133 | /** |
134 | * @component |
135 | */ |
136 | private npanday.executable.NetExecutableFactory netExecutableFactory; |
137 | |
138 | /** |
139 | * @component |
140 | */ |
141 | private npanday.NPandayRepositoryRegistry npandayRegistry; |
142 | |
143 | private File webSourceDirectory; |
144 | |
145 | public void execute() |
146 | throws MojoExecutionException |
147 | { |
148 | long startTime = System.currentTimeMillis(); |
149 | |
150 | webSourceDirectory = new File( project.getBuild().getSourceDirectory() ); |
151 | |
152 | if ( profileAssemblyPath != null && !profileAssemblyPath.exists() ) |
153 | { |
154 | throw new MojoExecutionException( "NPANDAY-900-000: Profile Assembly Path does not exist: Path = " + |
155 | profileAssemblyPath.getAbsolutePath() ); |
156 | } |
157 | |
158 | if ( localRepository == null ) |
159 | { |
160 | localRepository = new File( System.getProperty( "user.home" ), ".m2/repository" ); |
161 | } |
162 | |
163 | File tmpDir; |
164 | try |
165 | { |
166 | tmpDir = getTempDirectory(); |
167 | } |
168 | catch ( IOException e ) |
169 | { |
170 | throw new MojoExecutionException( "Unable to create temporary directory", e ); |
171 | } |
172 | |
173 | // since asp_compiler doesn't have excludes, will just copy web source to temp directory |
174 | File tmpSourceDir = new File( tmpDir, "src" ); |
175 | tmpSourceDir.mkdirs(); |
176 | try |
177 | { |
178 | FileUtils.copyDirectoryStructure( webSourceDirectory, tmpSourceDir ); |
179 | |
180 | // delete target from temp web source |
181 | FileUtils.deleteDirectory( new File( tmpSourceDir, outputDirectory.getName() ) ); |
182 | } |
183 | catch ( IOException e ) |
184 | { |
185 | throw new MojoExecutionException( "Unable to copy directory " + webSourceDirectory.getAbsolutePath() + " to " + |
186 | tmpSourceDir.getAbsolutePath(), e ); |
187 | } |
188 | |
189 | File tmpDestDir = new File( tmpDir, "dest" ); |
190 | tmpDestDir.mkdirs(); |
191 | |
192 | CompilerRequirement compilerRequirement = createCompilerRequirement(); |
193 | |
194 | CompilerConfig compilerConfig = createCompilerConfig( tmpSourceDir.getAbsolutePath(), tmpDestDir.getAbsolutePath() ); |
195 | |
196 | try |
197 | { |
198 | CompilerExecutable compilerExecutable = |
199 | netExecutableFactory.getCompilerExecutableFor( compilerRequirement, compilerConfig, project, |
200 | profileAssemblyPath ); |
201 | |
202 | long startTimeCompile = System.currentTimeMillis(); |
203 | compilerExecutable.execute(); |
204 | long endTimeCompile = System.currentTimeMillis(); |
205 | |
206 | getLog().info( "NPANDAY-000-000: Compile Time = " + ( endTimeCompile - startTimeCompile ) + " ms" ); |
207 | project.getArtifact().setFile( compilerExecutable.getCompiledArtifact() ); |
208 | } |
209 | catch ( PlatformUnsupportedException e ) |
210 | { |
211 | throw new MojoExecutionException( "NPANDAY-900-005: Unsupported Platform: Language = " + language + |
212 | ", Vendor = " + vendor + ", ArtifactType = " + project.getArtifact().getType(), e ); |
213 | } |
214 | catch ( ExecutionException e ) |
215 | { |
216 | throw new MojoExecutionException( "NPANDAY-900-006: Unable to Compile: Language = " + language + |
217 | ", Vendor = " + vendor + ", ArtifactType = " + project.getArtifact().getType() + ", Source Directory = " + |
218 | project.getBuild().getSourceDirectory(), e ); |
219 | } |
220 | |
221 | File webappDir = new File( outputDirectory, project.getArtifactId() ); |
222 | webappDir.mkdirs(); |
223 | |
224 | try |
225 | { |
226 | /* delete the target folder copied by aspnet compiler */ |
227 | /* TODO should be removed since target is deleted */ |
228 | //FileUtils.deleteDirectory( new File( tmpDir, outputDirectory.getName() ) ); |
229 | |
230 | /* keep only the files needed to run the app */ |
231 | List<File> allFiles = FileUtils.getFiles( tmpDestDir, "**", null ); |
232 | List<File> filesToKeep = FileUtils.getFiles( tmpDestDir, DEFAULT_INCLUDES, DEFAULT_EXCLUDES ); |
233 | |
234 | for ( File file : allFiles ) |
235 | { |
236 | if ( !filesToKeep.contains( file ) || "App_global.asax.dll".equals(file.getName()) || "App_global.asax.compiled".equals(file.getName())) |
237 | { |
238 | file.delete(); |
239 | deleteDirectoryIfEmpty( file.getParentFile() ); |
240 | } |
241 | } |
242 | } |
243 | catch ( IOException e ) |
244 | { |
245 | throw new MojoExecutionException( "Unable to delete unneccessary files in temporary directory " + |
246 | tmpDestDir.getAbsolutePath(), e ); |
247 | } |
248 | |
249 | try |
250 | { |
251 | FileUtils.copyDirectoryStructure( tmpDestDir, webappDir ); |
252 | } |
253 | catch ( IOException e ) |
254 | { |
255 | throw new MojoExecutionException( "Unable to copy directory " + tmpDestDir.getAbsolutePath() + " to " + |
256 | webappDir.getAbsolutePath(), e ); |
257 | } |
258 | |
259 | try |
260 | { |
261 | String sourceDirectory = webSourceDirectory.getAbsolutePath(); |
262 | List<File> fileList = FileUtils.getFiles(new File(sourceDirectory), "**/*.asax", null); |
263 | getLog().debug("copy .asax to target file (temp source folder: " + sourceDirectory + ")..."); |
264 | getLog().debug("copy .asax to target file (temp dest folder: " + tmpDestDir + ")..."); |
265 | getLog().debug("copy .asax to target file (file count: " + fileList.size() + ")..."); |
266 | |
267 | for ( File file : fileList ) |
268 | { |
269 | try |
270 | { |
271 | String fileName = file.getAbsolutePath().substring( (int) sourceDirectory.length() ); |
272 | FileUtils.copyFile( new File( file.getAbsolutePath() ), new File( webappDir.getAbsolutePath() + fileName ) ); |
273 | getLog().info("Copying " + fileName.substring(1) + " to " + webappDir.getAbsolutePath() ); |
274 | } |
275 | catch ( IOException e ) |
276 | { |
277 | throw new MojoExecutionException( "Unable to copy asax file " + file.getAbsolutePath() + " to " + |
278 | webappDir.getAbsolutePath(), e ); |
279 | } |
280 | } |
281 | } |
282 | catch ( IOException e ) |
283 | { |
284 | throw new MojoExecutionException( "Unable to retrieve asax file", e ); |
285 | } |
286 | |
287 | // cleanup |
288 | try |
289 | { |
290 | FileUtils.deleteDirectory( tmpDir ); |
291 | } |
292 | catch ( IOException e ) |
293 | { |
294 | getLog().info( "Unable to delete temporary directory " + tmpDir ); |
295 | // temporary files can't be deleted, ignore |
296 | } |
297 | |
298 | long endTime = System.currentTimeMillis(); |
299 | getLog().info( "Mojo Execution Time = " + ( endTime - startTime ) ); |
300 | |
301 | // TODO: remove hardcoded values |
302 | String targetFile = |
303 | project.getBuild().getDirectory() + File.separator + project.getArtifactId() + "-" + project.getVersion() + |
304 | "-dist" + ".zip"; |
305 | getLog().info( "NPANDAY-000-000: Setting the target file: " + targetFile ); |
306 | project.getArtifact().setFile( new File( targetFile ) ); |
307 | |
308 | //Delete Bin Folder |
309 | String binDir = project.getBuild().getSourceDirectory()+File.separator + "Bin"; |
310 | try |
311 | { |
312 | FileUtils.deleteDirectory(binDir); |
313 | getLog().info("Bin folder deleted: " + binDir); |
314 | } |
315 | catch(IOException e) |
316 | { |
317 | getLog().info("Failed to delete Bin folder: " + binDir + " : " + e.getMessage()); |
318 | } |
319 | } |
320 | |
321 | private CompilerConfig createCompilerConfig(String source, String destination) throws MojoExecutionException |
322 | { |
323 | CompilerConfig compilerConfig = (CompilerConfig) CompilerConfig.Factory.createDefaultExecutableConfig(); |
324 | compilerConfig.setLocalRepository( localRepository ); |
325 | compilerConfig.setCommands( getCommands( source, destination ) ); |
326 | |
327 | String artifactTypeName = project.getArtifact().getType(); |
328 | ArtifactType artifactType = ArtifactType.getArtifactTypeForPackagingName( artifactTypeName ); |
329 | if ( artifactType.equals( ArtifactType.NULL ) ) |
330 | { |
331 | throw new MojoExecutionException( "NPANDAY-900-002: Unrecognized artifact type: Language = " + language + |
332 | ", Vendor = " + vendor + ", ArtifactType = " + artifactTypeName ); |
333 | } |
334 | compilerConfig.setArtifactType( artifactType ); |
335 | |
336 | return compilerConfig; |
337 | } |
338 | |
339 | private CompilerRequirement createCompilerRequirement() throws MojoExecutionException |
340 | { |
341 | CompilerRequirement compilerRequirement = CompilerRequirement.Factory.createDefaultCompilerRequirement(); |
342 | compilerRequirement.setLanguage( language ); |
343 | compilerRequirement.setFrameworkVersion( frameworkVersion ); |
344 | compilerRequirement.setProfile( profile ); |
345 | compilerRequirement.setVendorVersion( vendorVersion ); |
346 | try |
347 | { |
348 | if ( vendor != null ) |
349 | { |
350 | compilerRequirement.setVendor( VendorFactory.createVendorFromName( vendor ) ); |
351 | } |
352 | } |
353 | catch ( PlatformUnsupportedException e ) |
354 | { |
355 | throw new MojoExecutionException( "NPANDAY-900-001: Unknown Vendor: Vendor = " + vendor, e ); |
356 | } |
357 | |
358 | return compilerRequirement; |
359 | } |
360 | |
361 | private List<String> getCommands( String sourceDir, String outputDir ) |
362 | throws MojoExecutionException |
363 | { |
364 | if ( parameters == null ) |
365 | { |
366 | parameters = new ArrayList<String>(); |
367 | } |
368 | |
369 | parameters.add( "-v" ); |
370 | parameters.add( " /" + project.getArtifactId() ); |
371 | parameters.add( "-p" ); |
372 | parameters.add( sourceDir ); |
373 | parameters.add( "-u" ); |
374 | parameters.add( "-f" ); |
375 | parameters.add( outputDir ); |
376 | parameters.add( "-nologo" ); |
377 | parameters.add( "-fixednames" ); |
378 | |
379 | return parameters; |
380 | } |
381 | |
382 | private File getTempDirectory() |
383 | throws IOException |
384 | { |
385 | File tempFile = File.createTempFile( "maven-aspx-plugin-", "" ); |
386 | File tmpDir = new File( tempFile.getParentFile(), tempFile.getName() ); |
387 | tempFile.delete(); |
388 | tmpDir.mkdir(); |
389 | return tmpDir; |
390 | } |
391 | |
392 | private void deleteDirectoryIfEmpty( File directory ) |
393 | { |
394 | if ( directory.listFiles().length == 0 ) |
395 | { |
396 | directory.delete(); |
397 | deleteDirectoryIfEmpty( directory.getParentFile() ); |
398 | } |
399 | } |
400 | |
401 | } |