|
@@ -1,1214 +1,1030 @@ |
1 |
|
- |
package com.esotericsoftware.scar; |
2 |
|
- |
|
3 |
|
- |
import org.litesoft.logger.*; |
4 |
|
- |
|
5 |
|
- |
import com.esotericsoftware.filesystem.*; |
6 |
|
- |
import com.esotericsoftware.scar.support.*; |
7 |
|
- |
import com.esotericsoftware.utils.*; |
8 |
|
- |
|
9 |
|
- |
import javax.tools.*; |
10 |
|
- |
import java.io.*; |
11 |
|
- |
import java.util.*; |
12 |
|
- |
import java.util.jar.*; |
13 |
|
- |
import java.util.zip.*; |
14 |
|
- |
|
15 |
|
- |
/** |
16 |
|
- |
* Generic Data structure that contains information needed to perform tasks. |
17 |
|
- |
*/ |
18 |
|
- |
@SuppressWarnings("UnusedDeclaration") |
19 |
|
- |
public class Project extends ProjectParameters |
20 |
|
- |
{ |
21 |
|
- |
private static final String JAVA_SOURCE_TARGET_VERSION = "1.7"; |
22 |
|
- |
|
23 |
|
- |
protected static final Logger LOGGER = LoggerFactory.getLogger( Project.class ); |
24 |
|
- |
|
25 |
|
- |
private static final String META_INF_MANIFEST_MF = "META-INF/MANIFEST.MF"; |
26 |
|
- |
|
27 |
|
- |
private static final String VERSIONED_URL_PATTERN_PREFIX = "<url-pattern>/v"; |
28 |
|
- |
private static final String VERSIONED_SCRIPT_PREFIX = "<script src='v"; |
29 |
|
- |
private static final String VERSIONED_SCRIPT_SUFFIX = ".nocache.js'></script>"; |
30 |
|
- |
private static final String VERSIONED_MODULE_PREFIX = "<module rename-to=\"v"; |
31 |
|
- |
private static final String VERSIONED_MODULE_SUFFIX = "\">"; |
32 |
|
- |
private static final String JAVA_HOME = "JAVA_HOME"; |
33 |
|
- |
|
34 |
|
- |
public Project( ProjectParameters pParameters ) |
35 |
|
- |
{ |
36 |
|
- |
super( pParameters.validate() ); |
37 |
|
- |
applyDefaults(); |
38 |
|
- |
} |
39 |
|
- |
|
40 |
|
- |
public String getSourceJavaVersion() |
41 |
|
- |
{ |
42 |
|
- |
return JAVA_SOURCE_TARGET_VERSION; |
43 |
|
- |
} |
44 |
|
- |
|
45 |
|
- |
public String getTargetJavaVersion() |
46 |
|
- |
{ |
47 |
|
- |
return JAVA_SOURCE_TARGET_VERSION; |
48 |
|
- |
} |
49 |
|
- |
|
50 |
|
- |
protected void packageClean() |
51 |
|
- |
{ |
52 |
|
- |
delete( getPhoneGapDirPath() ); |
53 |
|
- |
delete( getAppDirPath() ); |
54 |
|
- |
delete( getOneJarPath() ); |
55 |
|
- |
delete( getWarPath() ); |
56 |
|
- |
} |
57 |
|
- |
|
58 |
|
- |
protected boolean packageIt() |
59 |
|
- |
{ |
60 |
|
- |
return phoneGapDir() | appDir() | oneJAR() | war(); // Note: SINGLE '|' ORs to force full execution! |
61 |
|
- |
} |
62 |
|
- |
|
63 |
|
- |
/** |
64 |
|
- |
* Unzips all JARs in the classpath and creates a single JAR containing those files and this Project's JAR (which MUST exist). |
65 |
|
- |
* The manifest from the project's JAR is used. Putting everything into a single JAR makes it harder to see what libraries are |
66 |
|
- |
* being used, but makes it easier for end users to distribute the application. |
67 |
|
- |
* <p/> |
68 |
|
- |
* Note: Files with the same path in different JARs will be overwritten. Files in the project's JAR will never be overwritten, |
69 |
|
- |
* but may overwrite other files. |
70 |
|
- |
* |
71 |
|
- |
* @param pExcludeJARs The names of any JARs to exclude. |
72 |
|
- |
* |
73 |
|
- |
* @return True if the "OneJAR" was created / updated or false if no OneJar is NOT requested for this project or it was not needed. |
74 |
|
- |
*/ |
75 |
|
- |
public boolean oneJAR( String... pExcludeJARs ) |
76 |
|
- |
{ |
77 |
|
- |
File zOneJarPath = getOneJarPathFile(); |
78 |
|
- |
|
79 |
|
- |
if ( zOneJarPath == null ) |
80 |
|
- |
{ |
81 |
|
- |
return false; |
82 |
|
- |
} |
83 |
|
- |
|
84 |
|
- |
File zJarPath = getJarPathFile(); |
85 |
|
- |
if ( !zJarPath.isFile() ) |
86 |
|
- |
{ |
87 |
|
- |
throw new IllegalStateException( "One JAR: " + this + " requested, BUT NO jar File produced at: " + zJarPath.getPath() ); |
88 |
|
- |
} |
89 |
|
- |
|
90 |
|
- |
if ( zOneJarPath.isFile() && (zOneJarPath.lastModified() >= zJarPath.lastModified()) ) |
91 |
|
- |
{ |
92 |
|
- |
progress( "One JAR: " + this + " NOT Needed!" ); |
93 |
|
- |
return false; |
94 |
|
- |
} |
95 |
|
- |
|
96 |
|
- |
Paths zClasspath = classpath(); |
97 |
|
- |
if ( zClasspath.isEmpty() ) |
98 |
|
- |
{ |
99 |
|
- |
progress( "One JAR: " + this + " No supporting Jars! Simply Copying to: " + zOneJarPath.getPath() ); |
100 |
|
- |
copyFile( zJarPath, zOneJarPath ); |
101 |
|
- |
return true; |
102 |
|
- |
} |
103 |
|
- |
progress( "One JAR: " + this ); |
104 |
|
- |
|
105 |
|
- |
File zOnejarDir = mkdir( new File( path( "$target$/onejar/" ) ) ); |
106 |
|
- |
|
107 |
|
- |
List<String> zExcludeJARs = Arrays.asList( pExcludeJARs ); |
108 |
|
- |
for ( File jarFile : zClasspath.getFiles() ) // All our Class Path (dependant) JARS |
109 |
|
- |
{ |
110 |
|
- |
if ( !zExcludeJARs.contains( jarFile.getName() ) ) |
111 |
|
- |
{ |
112 |
|
- |
unzip( jarFile, zOnejarDir ); |
113 |
|
- |
} |
114 |
|
- |
} |
115 |
|
- |
|
116 |
|
- |
unzip( zJarPath, zOnejarDir ); // Our Jar! - Our Manifest will be "the" Manifest !!!!!! Need to remove class PATH! |
117 |
|
- |
innerJar( "'ONE' JAR", zOneJarPath.getPath(), new Paths( zOnejarDir.getPath() ) ); |
118 |
|
- |
return true; |
119 |
|
- |
} |
120 |
|
- |
|
121 |
|
- |
/** |
122 |
|
- |
* Collects the distribution files using the "dist" property, the project's JAR file, and everything on the project's classpath |
123 |
|
- |
* (including dependency project classpaths) and places them into the specified directory. This is also done for depenency projects, |
124 |
|
- |
* recursively. This is everything the application needs to be run from JAR files. |
125 |
|
- |
* |
126 |
|
- |
* @return True if the PhoneGapDir was populated or false if no distribution (App Dir) is requested for this project. |
127 |
|
- |
*/ |
128 |
|
- |
public boolean phoneGapDir() |
129 |
|
- |
{ |
130 |
|
- |
String zPhoneGapDir = getPhoneGapDirPath(); |
131 |
|
- |
if ( zPhoneGapDir == null ) |
132 |
|
- |
{ |
133 |
|
- |
return false; |
134 |
|
- |
} |
135 |
|
- |
Paths zPaths = new Paths( getGWTwarPath(), "**.js", "**.gif" ); |
136 |
|
- |
zPaths.add( getDist() ); |
137 |
|
- |
|
138 |
|
- |
File zPhoneGapDirFile = new File( zPhoneGapDir ); |
139 |
|
- |
if ( zPhoneGapDirFile.exists() ) |
140 |
|
- |
{ |
141 |
|
- |
if ( zPhoneGapDirFile.lastModified() >= zPaths.getGreatestLastModified() ) |
142 |
|
- |
{ |
143 |
|
- |
progress( "PhoneGapDir: " + this + " NOT Needed!" ); |
144 |
|
- |
return false; |
145 |
|
- |
} |
146 |
|
- |
delete( zPhoneGapDirFile ); |
147 |
|
- |
} |
148 |
|
- |
|
149 |
|
- |
progress( "PhoneGapDir: " + this + " -> " + zPhoneGapDir ); |
150 |
|
- |
String distDir = mkdir( zPhoneGapDir ); // Give it a new Timestamp |
151 |
|
- |
zPaths.copyTo( distDir ); |
152 |
|
- |
return true; |
153 |
|
- |
} |
154 |
|
- |
|
155 |
|
- |
/** |
156 |
|
- |
* Collects the distribution files using the "dist" property, the project's JAR file, and everything on the project's classpath |
157 |
|
- |
* (including dependency project classpaths) and places them into the specified directory. This is also done for depenency projects, |
158 |
|
- |
* recursively. This is everything the application needs to be run from JAR files. |
159 |
|
- |
* |
160 |
|
- |
* @return True if the AppDir was populated or false if no distribution (App Dir) is requested for this project. |
161 |
|
- |
*/ |
162 |
|
- |
public boolean appDir() |
163 |
|
- |
{ |
164 |
|
- |
String zAppDir = getAppDirPath(); |
165 |
|
- |
if ( zAppDir == null ) |
166 |
|
- |
{ |
167 |
|
- |
return false; |
168 |
|
- |
} |
169 |
|
- |
File zJarPath = getJarPathFile(); |
170 |
|
- |
if ( !zJarPath.isFile() ) |
171 |
|
- |
{ |
172 |
|
- |
progress( "AppDir: " + this + " BUT NO jar File produced at: " + zJarPath.getPath() ); |
173 |
|
- |
return false; |
174 |
|
- |
} |
175 |
|
- |
Paths zPaths = new Paths(); |
176 |
|
- |
addDependantProjectsDistPaths( zPaths ); |
177 |
|
- |
zPaths.add( classpath() ); |
178 |
|
- |
zPaths.add( FilePath.canonicalize( getJarPathFile() ) ); |
179 |
|
- |
|
180 |
|
- |
File zAppDirFile = new File( zAppDir ); |
181 |
|
- |
if ( zAppDirFile.exists() ) |
182 |
|
- |
{ |
183 |
|
- |
if ( zAppDirFile.lastModified() >= zPaths.getGreatestLastModified() ) |
184 |
|
- |
{ |
185 |
|
- |
progress( "AppDir: " + this + " NOT Needed!" ); |
186 |
|
- |
return false; |
187 |
|
- |
} |
188 |
|
- |
delete( zAppDirFile ); |
189 |
|
- |
} |
190 |
|
- |
|
191 |
|
- |
progress( "AppDir: " + this + " -> " + zAppDir ); |
192 |
|
- |
String distDir = mkdir( zAppDir ); // Give it a new Timestamp |
193 |
|
- |
zPaths.copyTo( distDir ); |
194 |
|
- |
return true; |
195 |
|
- |
} |
196 |
|
- |
|
197 |
|
- |
/** |
198 |
|
- |
* Produce either a 'war' directory or a '.war' file, in theory ready to deploy to a servlet/web container. |
199 |
|
- |
* |
200 |
|
- |
* @return true if the 'war' was created. |
201 |
|
- |
*/ |
202 |
|
- |
public boolean war() |
203 |
|
- |
{ |
204 |
|
- |
String zWar = getWar(); |
205 |
|
- |
if ( zWar == null ) |
206 |
|
- |
{ |
207 |
|
- |
return false; |
208 |
|
- |
} |
209 |
|
- |
File zJarPath = getJarPathFile(); |
210 |
|
- |
if ( !zJarPath.isFile() ) |
211 |
|
- |
{ |
212 |
|
- |
progress( "WAR: " + this + " BUT NO jar File produced at: " + zJarPath.getPath() ); |
213 |
|
- |
return false; |
214 |
|
- |
} |
215 |
|
- |
|
216 |
|
- |
Paths zDistPaths = new Paths(); |
217 |
|
- |
addDependantProjectsDistPaths( zDistPaths ); |
218 |
|
- |
if ( null != getGWT() ) |
219 |
|
- |
{ |
220 |
|
- |
zDistPaths.add( new Paths( getGWTwarPath() ) ); |
221 |
|
- |
} |
222 |
|
- |
|
223 |
|
- |
Paths zClassPath = new Paths(); |
224 |
|
- |
zClassPath.add( FilePath.canonical( getGWTatDir(), GWT_SERVLET ) ); |
225 |
|
- |
zClassPath.add( classpath() ); |
226 |
|
- |
zClassPath.add( FilePath.canonicalize( getJarPathFile() ) ); |
227 |
|
- |
|
228 |
|
- |
File zWarPathFile = getWarPathFile(); |
229 |
|
- |
if ( zWarPathFile.exists() ) |
230 |
|
- |
{ |
231 |
|
- |
long zWarLastModified = zWarPathFile.lastModified(); |
232 |
|
- |
if ( (zWarLastModified >= zClassPath.getGreatestLastModified()) && (zWarLastModified >= zDistPaths.getGreatestLastModified()) ) |
233 |
|
- |
{ |
234 |
|
- |
progress( "WAR: " + this + " NOT Needed!" ); |
235 |
|
- |
return false; |
236 |
|
- |
} |
237 |
|
- |
delete( zWarPathFile ); |
238 |
|
- |
} |
239 |
|
- |
|
240 |
|
- |
boolean zWarIt = zWar.endsWith( ".war" ); |
241 |
|
- |
|
242 |
|
- |
File zWarDir = zWarPathFile; |
243 |
|
- |
if ( zWarIt ) |
244 |
|
- |
{ |
245 |
|
- |
zWarDir = new File( path( "$target$/war/" ) ); |
246 |
|
- |
delete( zWarDir ); |
247 |
|
- |
} |
248 |
|
- |
|
249 |
|
- |
progress( "WAR: " + this + " -> " + zWarDir.getPath() ); |
250 |
|
- |
|
251 |
|
- |
File zWarDirLibPath = new File( zWarDir, "WEB-INF/lib" ); |
252 |
|
- |
mkdir( zWarDirLibPath ); |
253 |
|
- |
|
254 |
|
- |
zDistPaths.copyTo( zWarDir.getPath() ); |
255 |
|
- |
zClassPath.copyTo( zWarDirLibPath.getPath() ); |
256 |
|
- |
|
257 |
|
- |
if ( zWarIt ) |
258 |
|
- |
{ |
259 |
|
- |
innerJar( "WAR", zWarPathFile.getPath(), new Paths( zWarDir.getPath() ) ); |
260 |
|
- |
} |
261 |
|
- |
return true; |
262 |
|
- |
} |
263 |
|
- |
|
264 |
|
- |
/** |
265 |
|
- |
* Computes the classpath for all the dependencies of the specified project, recursively. |
266 |
|
- |
*/ |
267 |
|
- |
protected void addDependantProjectsDistPaths( Paths pPathsToAddTo ) |
268 |
|
- |
{ |
269 |
|
- |
for ( Project zProject : mDependantProjects ) |
270 |
|
- |
{ |
271 |
|
- |
zProject.addDependantProjectsDistPaths( pPathsToAddTo ); |
272 |
|
- |
} |
273 |
|
- |
pPathsToAddTo.add( getDist() ); |
274 |
|
- |
} |
275 |
|
- |
|
276 |
|
- |
protected boolean GWTcompileIt() |
277 |
|
- |
{ |
278 |
|
- |
String[] args = // |
279 |
|
- |
{ // |
280 |
|
- |
getPathJavaJRE(), // |
281 |
|
- |
"-Xmx" + getGWTmx(), // |
282 |
|
- |
"-cp", // |
283 |
|
- |
buildGWTcompileClassPath(), // |
284 |
|
- |
"com.google.gwt.dev.Compiler", // |
285 |
|
- |
"-logLevel", // |
286 |
|
- |
getGWTlogging(), // |
287 |
|
- |
"-war", // |
288 |
|
- |
getGWTwarPath(), // |
289 |
|
- |
"-style", // |
290 |
|
- |
getGWTstyle(), // |
291 |
|
- |
getGWT() // |
292 |
|
- |
}; |
293 |
|
- |
|
294 |
|
- |
Utils.shell( args ); |
295 |
|
- |
return true; |
296 |
|
- |
} |
297 |
|
- |
|
298 |
|
- |
private String buildGWTcompileClassPath() |
299 |
|
- |
{ |
300 |
|
- |
Paths zGWTclassPath = new Paths(); |
301 |
|
- |
File zGWTatDir = getGWTatDir(); |
302 |
|
- |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_DEV ) ); |
303 |
|
- |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_USER ) ); |
304 |
|
- |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_VALIDATION ) ); |
305 |
|
- |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_VALIDATION_SOURCE ) ); |
306 |
|
- |
if ( mSources ) |
307 |
|
- |
{ |
308 |
|
- |
zGWTclassPath.add( FilePath.canonicalize( getJarPathFile() ) ); |
309 |
|
- |
} |
310 |
|
- |
zGWTclassPath.add( classpath() ); |
311 |
|
- |
return zGWTclassPath.toString( File.pathSeparator ); |
312 |
|
- |
} |
313 |
|
- |
|
314 |
|
- |
protected String getPathJavaJRE() |
315 |
|
- |
{ |
316 |
|
- |
File zJavaHomeDir = assertIsDirectory( JAVA_HOME, new File( assertNotEmpty( JAVA_HOME, System.getenv( JAVA_HOME ) ) ) ); |
317 |
|
- |
File zJavaDir = new File( zJavaHomeDir, "jre/bin" ); |
318 |
|
- |
if ( !zJavaDir.isDirectory() ) |
319 |
|
- |
{ |
320 |
|
- |
if ( !(zJavaDir = new File( zJavaHomeDir, "bin" )).isDirectory() ) |
321 |
|
- |
{ |
322 |
|
- |
throw new IllegalStateException( "Unable to find JAVA_HOME bin directory under: " + zJavaHomeDir ); |
323 |
|
- |
} |
324 |
|
- |
} |
325 |
|
- |
File zJavaExecutable = new File( zJavaDir, isWindows ? "java.exe" : "java" ); |
326 |
|
- |
if ( zJavaExecutable.isFile() ) |
327 |
|
- |
{ |
328 |
|
- |
return getCanonicalFile( zJavaExecutable ).getPath(); |
329 |
|
- |
} |
330 |
|
- |
throw new IllegalStateException( "Unable to find JAVA_HOME based executable at: " + zJavaExecutable ); |
331 |
|
- |
} |
332 |
|
- |
|
333 |
|
- |
protected File getGeneratedGWT_nocache_jsFile() |
334 |
|
- |
{ |
335 |
|
- |
String zGWTxmlRelativeFilePath = getGWT().replace( '.', '/' ) + ".gwt.xml"; // e.g. org.litesoft.sandbox.csapp.CSapp |
336 |
|
- |
File zFound = getGeneratedGWT_nocache_jsFile( zGWTxmlRelativeFilePath, getSource() ); |
337 |
|
- |
if ( zFound == null ) |
338 |
|
- |
{ |
339 |
|
- |
if ( null == (zFound = getGeneratedGWT_nocache_jsFile( zGWTxmlRelativeFilePath, getResources() )) ) |
340 |
|
- |
{ |
341 |
|
- |
throw new IllegalArgumentException( "Unable to locate GWT module file: " + getGWT() ); |
342 |
|
- |
} |
343 |
|
- |
} |
344 |
|
- |
return zFound; |
345 |
|
- |
} |
346 |
|
- |
|
347 |
|
- |
private File getGeneratedGWT_nocache_jsFile( String pGWTxmlRelativeFilePath, Paths pPaths ) |
348 |
|
- |
{ |
349 |
|
- |
RootedPaths[] zRootedPaths = pPaths.getRootedPaths(); |
350 |
|
- |
for ( RootedPaths zPath : zRootedPaths ) |
351 |
|
- |
{ |
352 |
|
- |
File zFile = new File( zPath.getCanonicalRootDirectory(), pGWTxmlRelativeFilePath ); |
353 |
|
- |
if ( zFile.isFile() ) |
354 |
|
- |
{ |
355 |
|
- |
String moduleName = extractModuleNameFrom( getGWT(), fileContents( zFile ) ); |
356 |
|
- |
return new File( getGWTwarPath(), moduleName + "/" + moduleName + ".nocache.js" ); |
357 |
|
- |
} |
358 |
|
- |
} |
359 |
|
- |
return null; |
360 |
|
- |
} |
361 |
|
- |
|
362 |
|
- |
private String extractModuleNameFrom( String pGWTmoduleReference, String pGWTmoduleFileContents ) |
363 |
|
- |
{ |
364 |
|
- |
int at = pGWTmoduleFileContents.indexOf( " rename-to" ); |
365 |
|
- |
if ( at != -1 ) // . . . . . . . . . . . .01234567890 |
366 |
|
- |
{ |
367 |
|
- |
int upTo = pGWTmoduleFileContents.indexOf( '>', at += 10 ); |
368 |
|
- |
if ( upTo != -1 ) |
369 |
|
- |
{ |
370 |
|
- |
String stuff = pGWTmoduleFileContents.substring( at, upTo ).trim(); |
371 |
|
- |
if ( stuff.startsWith( "=" ) ) |
372 |
|
- |
{ |
373 |
|
- |
if ( (stuff = stuff.substring( 1 ).trim()).length() > 2 ) |
374 |
|
- |
{ |
375 |
|
- |
char c = stuff.charAt( 0 ); |
376 |
|
- |
if ( (c == '"') || (c == '\'') ) |
377 |
|
- |
{ |
378 |
|
- |
if ( -1 != (at = stuff.indexOf( c, 1 )) ) |
379 |
|
- |
{ |
380 |
|
- |
return stuff.substring( 1, at ); |
381 |
|
- |
} |
382 |
|
- |
} |
383 |
|
- |
} |
384 |
|
- |
} |
385 |
|
- |
} |
386 |
|
- |
} |
387 |
|
- |
String s = "." + pGWTmoduleReference; |
388 |
|
- |
return s.substring( s.lastIndexOf( '.' ) + 1 ); |
389 |
|
- |
} |
390 |
|
- |
|
391 |
|
- |
protected boolean needToCompileGWT() |
392 |
|
- |
{ |
393 |
|
- |
File zGeneratedGWT_nocache_jsFile = getGeneratedGWT_nocache_jsFile(); |
394 |
|
- |
return needToBuild( ((zGeneratedGWT_nocache_jsFile != null) && zGeneratedGWT_nocache_jsFile.isFile()) ? |
395 |
|
- |
zGeneratedGWT_nocache_jsFile.lastModified() : forceBuildLastModified() ); |
396 |
|
- |
} |
397 |
|
- |
|
398 |
|
- |
public boolean GWTcompile() |
399 |
|
- |
{ |
400 |
|
- |
String zGWT = getGWT(); |
401 |
|
- |
if ( zGWT == null ) |
402 |
|
- |
{ |
403 |
|
- |
return false; |
404 |
|
- |
} |
405 |
|
- |
if ( !needToCompileGWT() ) |
406 |
|
- |
{ |
407 |
|
- |
progress( "GWT Compile: " + this + " NOT Needed!" ); |
408 |
|
- |
return false; |
409 |
|
- |
} |
410 |
|
- |
progress( "GWT Compile: " + this ); |
411 |
|
- |
return GWTcompileIt(); |
412 |
|
- |
} |
413 |
|
- |
|
414 |
|
- |
/** |
415 |
|
- |
* Assert that this project is currently a 'Versioned' GWT project, and then rev the version number by 1 |
416 |
|
- |
*/ |
417 |
|
- |
public void versionGWT() |
418 |
|
- |
{ |
419 |
|
- |
File zWarWebXmlFile = new File( mCanonicalProjectDir, "war/WEB-INF/web.xml" ); |
420 |
|
- |
String zWarWebXml = fileContents( assertIsFile( "web.xml", zWarWebXmlFile ) ); |
421 |
|
- |
|
422 |
|
- |
int zCurVersion = extractVersionFromUrlPattern( zWarWebXml ); |
423 |
|
- |
|
424 |
|
- |
String zWarResourceRelativePathCurrent = "warResources/v" + zCurVersion; |
425 |
|
- |
|
426 |
|
- |
File zIndexHtmlFile = new File( mCanonicalProjectDir, zWarResourceRelativePathCurrent + "/index.html" ); |
427 |
|
- |
String zIndexHtml = assertVersionedIndexHtml( zIndexHtmlFile, zCurVersion ); |
428 |
|
- |
|
429 |
|
- |
List<File> zVersionedGwtXmlFiles = findVersionedGwtXmlFiles( zCurVersion ); |
430 |
|
- |
|
431 |
|
- |
int zNewVersion = zCurVersion + 1; |
432 |
|
- |
|
433 |
|
- |
String zWarResourceRelativePathNew = "warResources/v" + zNewVersion; |
434 |
|
- |
if ( new File( mCanonicalProjectDir, zWarResourceRelativePathNew ).exists() ) |
435 |
|
- |
{ |
436 |
|
- |
throw new IllegalStateException( "Project already contains a 'warResources/v" + zNewVersion + "' directory?" ); |
437 |
|
- |
} |
438 |
|
- |
|
439 |
|
- |
progress( "versionGWT: " + this + " | " + zCurVersion + " -> " + (zCurVersion + 1) ); |
440 |
|
- |
progress( " " + zWarWebXmlFile.getPath() ); |
441 |
|
- |
progress( " " + zIndexHtmlFile.getPath() ); |
442 |
|
- |
for ( File zFile : zVersionedGwtXmlFiles ) |
443 |
|
- |
{ |
444 |
|
- |
progress( " " + zFile.getPath() ); |
445 |
|
- |
} |
446 |
|
- |
progress( " " + zWarResourceRelativePathCurrent + " -> " + zWarResourceRelativePathNew ); |
447 |
|
- |
|
448 |
|
- |
new Paths( zWarResourceRelativePathCurrent ).copyTo( zWarResourceRelativePathNew ); |
449 |
|
- |
|
450 |
|
- |
updateFileContents( new File( mCanonicalProjectDir, zWarResourceRelativePathNew + "/index.html" ), |
451 |
|
- |
updateVersionedIndexHtml( zIndexHtml, zCurVersion, zNewVersion ) ); |
452 |
|
- |
|
453 |
|
- |
updateFileContents( zWarWebXmlFile, updateVersionedWebXml( zWarWebXml, zCurVersion, zNewVersion ) ); |
454 |
|
- |
|
455 |
|
- |
for ( File zFile : zVersionedGwtXmlFiles ) |
456 |
|
- |
{ |
457 |
|
- |
updateFileContents( zFile, updateVersionedGwtXmlFile( fileContents( zFile ), zCurVersion, zNewVersion ) ); |
458 |
|
- |
} |
459 |
|
- |
// Update/Create the Current Version's redirect JavaScript file |
460 |
|
- |
String zCurPathVersion = "/v" + zCurVersion; |
461 |
|
- |
String redirectScript = "var loc = window.location.href;\n" + // |
462 |
|
- |
"var at = loc.indexOf( '" + zCurPathVersion + "' );\n" + // |
463 |
|
- |
"window.location.href = loc.substring(0, at) + '/v" + zNewVersion + "' + loc.substring(at + " + zCurPathVersion.length() + ");\n"; |
464 |
|
- |
updateFileContents( new File( mCanonicalProjectDir, zWarResourceRelativePathCurrent + "/v" + zCurVersion + ".nocache.js" ), redirectScript ); |
465 |
|
- |
|
466 |
|
- |
// Update the "root" html (if it exists) |
467 |
|
- |
File zRootHtmlFile = new File( mCanonicalProjectDir, "warResources/index.html" ); |
468 |
|
- |
if ( zRootHtmlFile.isFile() ) |
469 |
|
- |
{ |
470 |
|
- |
updateFileContents( zRootHtmlFile, updateRootHTML( fileContents( zRootHtmlFile ), zCurVersion, zNewVersion ) ); |
471 |
|
- |
} |
472 |
|
- |
} |
473 |
|
- |
|
474 |
|
- |
protected String updateRootHTML( String pFileContents, int pCurVersion, int pNewVersion ) |
475 |
|
- |
{ |
476 |
|
- |
// <!DOCTYPE html> |
477 |
|
- |
// <html> |
478 |
|
- |
// <head> |
479 |
|
- |
// <meta http-equiv="Refresh" content="1; url=v1/"> |
480 |
|
- |
// </head> |
481 |
|
- |
// <body> |
482 |
|
- |
// <script>window.location.href = 'v1/';</script> |
483 |
|
- |
// </body> |
484 |
|
- |
// </html> |
485 |
|
- |
String zCurPathVersion = "v" + pCurVersion + "/"; |
486 |
|
- |
String zNewPathVersion = "v" + pNewVersion + "/"; |
487 |
|
- |
for ( int at; -1 != (at = pFileContents.indexOf( zCurPathVersion )); ) |
488 |
|
- |
{ |
489 |
|
- |
pFileContents = pFileContents.substring( 0, at ) + zNewPathVersion + pFileContents.substring( at + zCurPathVersion.length() ); |
490 |
|
- |
} |
491 |
|
- |
return pFileContents; |
492 |
|
- |
} |
493 |
|
- |
|
494 |
|
- |
protected String updateVersionedGwtXmlFile( String pFileContents, int pCurVersion, int pNewVersion ) |
495 |
|
- |
{ |
496 |
|
- |
String zCurVersionedModule = VERSIONED_MODULE_PREFIX + pCurVersion + VERSIONED_MODULE_SUFFIX; |
497 |
|
- |
String zNewVersionedModule = VERSIONED_MODULE_PREFIX + pNewVersion + VERSIONED_MODULE_SUFFIX; |
498 |
|
- |
int at = pFileContents.indexOf( zCurVersionedModule ); |
499 |
|
- |
return pFileContents.substring( 0, at ) + zNewVersionedModule + pFileContents.substring( at + zCurVersionedModule.length() ); |
500 |
|
- |
} |
501 |
|
- |
|
502 |
|
- |
protected List<File> findVersionedGwtXmlFiles( int pVersion ) |
503 |
|
- |
{ |
504 |
|
- |
String zVersionedModule = VERSIONED_MODULE_PREFIX + pVersion + VERSIONED_MODULE_SUFFIX; |
505 |
|
- |
|
506 |
|
- |
ArrayList<File> zVersionedFiles = new ArrayList<File>(); |
507 |
|
- |
|
508 |
|
- |
String zSourceString = get( SOURCE.getName() ) + "|"; |
509 |
|
- |
Paths zGwtXml = new Paths( zSourceString.substring( 0, zSourceString.indexOf( '|' ) ), "**.gwt.xml" ); |
510 |
|
- |
for ( File zFile : zGwtXml.getFiles() ) |
511 |
|
- |
{ |
512 |
|
- |
if ( fileContents( zFile ).contains( zVersionedModule ) ) |
513 |
|
- |
{ |
514 |
|
- |
zVersionedFiles.add( zFile ); |
515 |
|
- |
} |
516 |
|
- |
} |
517 |
|
- |
if ( zVersionedFiles.isEmpty() ) |
518 |
|
- |
{ |
519 |
|
- |
throw new IllegalStateException( |
520 |
|
- |
"Project does not appear to contain a 'gwt.xml' file with the current version module definition of: " + zVersionedModule ); |
521 |
|
- |
} |
522 |
|
- |
return zVersionedFiles; |
523 |
|
- |
} |
524 |
|
- |
|
525 |
|
- |
protected String updateVersionedIndexHtml( String pFileContents, int pCurVersion, int pNewVersion ) |
526 |
|
- |
{ |
527 |
|
- |
String zCurVersionedScript = VERSIONED_SCRIPT_PREFIX + pCurVersion + VERSIONED_SCRIPT_SUFFIX; |
528 |
|
- |
String zNewVersionedScript = VERSIONED_SCRIPT_PREFIX + pNewVersion + VERSIONED_SCRIPT_SUFFIX; |
529 |
|
- |
int at = pFileContents.indexOf( zCurVersionedScript ); |
530 |
|
- |
return pFileContents.substring( 0, at ) + zNewVersionedScript + pFileContents.substring( at + zCurVersionedScript.length() ); |
531 |
|
- |
} |
532 |
|
- |
|
533 |
|
- |
protected String assertVersionedIndexHtml( File pIndexHtmlFile, int pVersion ) |
534 |
|
- |
{ |
535 |
|
- |
String zVersionedScript = VERSIONED_SCRIPT_PREFIX + pVersion + VERSIONED_SCRIPT_SUFFIX; |
536 |
|
- |
|
537 |
|
- |
String zContents = fileContents( assertIsFile( "Versioned index.html", pIndexHtmlFile ) ); |
538 |
|
- |
if ( !zContents.contains( zVersionedScript ) ) |
539 |
|
- |
{ |
540 |
|
- |
throw new IllegalStateException( |
541 |
|
- |
"Project's current versioned index.html file (" + pIndexHtmlFile.getPath() + ") does not contain a 'versioned' script element of: " + |
542 |
|
- |
zVersionedScript ); |
543 |
|
- |
} |
544 |
|
- |
return zContents; |
545 |
|
- |
} |
546 |
|
- |
|
547 |
|
- |
protected String updateVersionedWebXml( String pFileContents, int pCurVersion, int pNewVersion ) |
548 |
|
- |
{ |
549 |
|
- |
String zCurVersionedUrlPattern = VERSIONED_URL_PATTERN_PREFIX + pCurVersion + "/"; |
550 |
|
- |
String zNewVersionedUrlPattern = VERSIONED_URL_PATTERN_PREFIX + pNewVersion + "/"; |
551 |
|
- |
for ( int at; -1 != (at = pFileContents.indexOf( zCurVersionedUrlPattern )); ) |
552 |
|
- |
{ |
553 |
|
- |
pFileContents = pFileContents.substring( 0, at ) + zNewVersionedUrlPattern + pFileContents.substring( at + zCurVersionedUrlPattern.length() ); |
554 |
|
- |
} |
555 |
|
- |
return pFileContents; |
556 |
|
- |
} |
557 |
|
- |
|
558 |
|
- |
protected int extractVersionFromUrlPattern( String pWarWebXml ) |
559 |
|
- |
{ |
560 |
|
- |
for ( int at, from = 0; -1 != (at = pWarWebXml.indexOf( VERSIONED_URL_PATTERN_PREFIX, from )); from = at + 1 ) |
561 |
|
- |
{ |
562 |
|
- |
int slashAt = pWarWebXml.indexOf( '/', at += VERSIONED_URL_PATTERN_PREFIX.length() ); |
563 |
|
- |
if ( slashAt > 0 ) |
564 |
|
- |
{ |
565 |
|
- |
try |
566 |
|
- |
{ |
567 |
|
- |
return Integer.parseInt( pWarWebXml.substring( at, slashAt ) ); |
568 |
|
- |
} |
569 |
|
- |
catch ( NumberFormatException acceptable ) |
570 |
|
- |
{ |
571 |
|
- |
// path starts w/ a 'v' but is not of pattern "v####" |
572 |
|
- |
} |
573 |
|
- |
} |
574 |
|
- |
} |
575 |
|
- |
throw new IllegalStateException( "Project's war/WEB-INF/web.xml does not appear to contain a 'versioned' <url-pattern>." ); |
576 |
|
- |
} |
577 |
|
- |
|
578 |
|
- |
/** |
579 |
|
- |
* Executes the buildDependencies, clean, compile, jar, [GWTcompile], and then "packageIt" utility methods. |
580 |
|
- |
*/ |
581 |
|
- |
public synchronized boolean build() |
582 |
|
- |
{ |
583 |
|
- |
if ( mBuilt ) |
584 |
|
- |
{ |
585 |
|
- |
return false; |
586 |
|
- |
} |
587 |
|
- |
mBuilt = true; |
588 |
|
- |
mSources = !getSource().isEmpty(); |
589 |
|
- |
boolean zAnythingBuilt = false; |
590 |
|
- |
boolean zBuildIt; |
591 |
|
- |
try |
592 |
|
- |
{ |
593 |
|
- |
zBuildIt = buildDependencies() || needToBuild(); |
594 |
|
- |
} |
595 |
|
- |
catch ( RuntimeException e ) |
596 |
|
- |
{ |
597 |
|
- |
progress( "Build: " + this ); |
598 |
|
- |
throw e; |
599 |
|
- |
} |
600 |
|
- |
if ( !zBuildIt ) |
601 |
|
- |
{ |
602 |
|
- |
progress( "Build: " + this + " NOT Needed!" ); |
603 |
|
- |
} |
604 |
|
- |
else |
605 |
|
- |
{ |
606 |
|
- |
progress( "Build: " + this ); |
607 |
|
- |
clean(); |
608 |
|
- |
if ( mSources ) |
609 |
|
- |
{ |
610 |
|
- |
compile(); |
611 |
|
- |
jar(); |
612 |
|
- |
zAnythingBuilt = true; |
613 |
|
- |
} |
614 |
|
- |
} |
615 |
|
- |
zAnythingBuilt |= GWTcompile(); |
616 |
|
- |
zAnythingBuilt |= packageIt(); |
617 |
|
- |
return zAnythingBuilt; |
618 |
|
- |
} |
619 |
|
- |
|
620 |
|
- |
protected boolean needToBuild() |
621 |
|
- |
{ |
622 |
|
- |
return needToBuild( determineOutputLastModified() ); |
623 |
|
- |
} |
624 |
|
- |
|
625 |
|
- |
protected boolean needToBuild( long pOutputLastModified ) |
626 |
|
- |
{ |
627 |
|
- |
return (mProjectFileLastModified > pOutputLastModified) || // |
628 |
|
- |
checkNewer( pOutputLastModified, "ClassPath", compileClasspath() ) || // |
629 |
|
- |
checkNewer( pOutputLastModified, "Source", getSource() ) || // |
630 |
|
- |
checkNewer( pOutputLastModified, "Resources", getResources() ) || // |
631 |
|
- |
checkNewer( pOutputLastModified, "Dist", getDist() ); |
632 |
|
- |
} |
633 |
|
- |
|
634 |
|
- |
protected boolean checkNewer( long pOutputLastModified, String pWhat, Paths pPaths ) |
635 |
|
- |
{ |
636 |
|
- |
Long zLastModified = pPaths.getGreatestLastModified(); |
637 |
|
- |
if ( (zLastModified != null) && (zLastModified > pOutputLastModified) ) |
638 |
|
- |
{ |
639 |
|
- |
System.out.println( this + ": " + pWhat + " - " + new NewerBy( pOutputLastModified, zLastModified ) ); |
640 |
|
- |
return true; |
641 |
|
- |
} |
642 |
|
- |
return false; |
643 |
|
- |
} |
644 |
|
- |
|
645 |
|
- |
protected long forceBuildLastModified() |
646 |
|
- |
{ |
647 |
|
- |
return (mProjectFileLastModified - 1); |
648 |
|
- |
} |
649 |
|
- |
|
650 |
|
- |
protected long determineOutputLastModified() |
651 |
|
- |
{ |
652 |
|
- |
if ( mSources ) |
653 |
|
- |
{ |
654 |
|
- |
File zJarFile = getJarPathFile(); |
655 |
|
- |
if ( zJarFile.isFile() ) |
656 |
|
- |
{ |
657 |
|
- |
return zJarFile.lastModified(); |
658 |
|
- |
} |
659 |
|
- |
} |
660 |
|
- |
else |
661 |
|
- |
{ |
662 |
|
- |
String zPhoneGapDir = getPhoneGapDirPath(); |
663 |
|
- |
if ( zPhoneGapDir != null ) |
664 |
|
- |
{ |
665 |
|
- |
File zPhoneGapDirFile = new File( zPhoneGapDir ); |
666 |
|
- |
if ( zPhoneGapDirFile.isDirectory() ) |
667 |
|
- |
{ |
668 |
|
- |
return zPhoneGapDirFile.lastModified(); |
669 |
|
- |
} |
670 |
|
- |
} |
671 |
|
- |
} |
672 |
|
- |
return forceBuildLastModified(); |
673 |
|
- |
} |
674 |
|
- |
|
675 |
|
- |
/** |
676 |
|
- |
* Deletes the "target" directory and all files and directories under it. |
677 |
|
- |
*/ |
678 |
|
- |
public void clean() |
679 |
|
- |
{ |
680 |
|
- |
progress( "Clean: " + this ); |
681 |
|
- |
packageClean(); |
682 |
|
- |
delete( getGWTwarPath() ); |
683 |
|
- |
delete( getJarPath() ); |
684 |
|
- |
delete( getTargetPath() ); |
685 |
|
- |
} |
686 |
|
- |
|
687 |
|
- |
/** |
688 |
|
- |
* Collects the source files using the "source" property and compiles them into a "classes" directory under the target |
689 |
|
- |
* directory. It uses "classpath" and "dependencies" to find the libraries required to compile the source. |
690 |
|
- |
* <p/> |
691 |
|
- |
* Note: Each dependency project is not built automatically. Each needs to be built before the dependent project. |
692 |
|
- |
* |
693 |
|
- |
* @return The path to the "classes" directory or null if there was no sources to compile |
694 |
|
- |
*/ |
695 |
|
- |
public String compile() |
696 |
|
- |
{ |
697 |
|
- |
Paths source = getSource(); |
698 |
|
- |
if ( source.isEmpty() ) |
699 |
|
- |
{ |
700 |
|
- |
return null; |
701 |
|
- |
} |
702 |
|
- |
Paths classpath = compileClasspath(); |
703 |
|
- |
|
704 |
|
- |
String classesDir = mkdir( path( "$target$/classes/" ) ); |
705 |
|
- |
|
706 |
|
- |
String zMessage = "Compile: " + this; |
707 |
|
- |
if ( LOGGER.debug.isEnabled() ) |
708 |
|
- |
{ |
709 |
|
- |
zMessage += " | " + source.count() + " source files"; |
710 |
|
- |
if ( !classpath.isEmpty() ) |
711 |
|
- |
{ |
712 |
|
- |
zMessage += "\n Classpath: " + classpath; |
713 |
|
- |
} |
714 |
|
- |
} |
715 |
|
- |
progress( zMessage ); |
716 |
|
- |
|
717 |
|
- |
List<String> zCompileArgs = createCompileJavaArgs( classpath, source, classesDir ); |
718 |
|
- |
|
719 |
|
- |
compileJava( classpath, source, zCompileArgs ); |
720 |
|
- |
|
721 |
|
- |
return classesDir; |
722 |
|
- |
} |
723 |
|
- |
|
724 |
|
- |
protected List<String> createCompileJavaArgs( Paths pClasspath, Paths pSource, String pClassesDir ) |
725 |
|
- |
{ |
726 |
|
- |
List<String> args = new ArrayList<String>(); |
727 |
|
- |
if ( LOGGER.trace.isEnabled() ) |
728 |
|
- |
{ |
729 |
|
- |
args.add( "-verbose" ); |
730 |
|
- |
} |
731 |
|
- |
args.add( "-d" ); |
732 |
|
- |
args.add( pClassesDir ); |
733 |
|
- |
args.add( "-g:source,lines" ); |
734 |
|
- |
args.add( "-source" ); |
735 |
|
- |
args.add( getSourceJavaVersion() ); |
736 |
|
- |
args.addAll( pSource.getFullPaths() ); |
737 |
|
- |
if ( !pClasspath.isEmpty() ) |
738 |
|
- |
{ |
739 |
|
- |
args.add( "-classpath" ); |
740 |
|
- |
args.add( pClasspath.toString( File.pathSeparator ) ); |
741 |
|
- |
} |
742 |
|
- |
return args; |
743 |
|
- |
} |
744 |
|
- |
|
745 |
|
- |
protected void compileJava( Paths pClasspath, Paths pSource, List<String> pCompileArgs ) |
746 |
|
- |
{ |
747 |
|
- |
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
748 |
|
- |
|
749 |
|
- |
if ( compiler == null ) |
750 |
|
- |
{ |
751 |
|
- |
throw new RuntimeException( "No compiler available. Ensure you are running from a " + getTargetJavaVersion() + |
752 |
|
- |
"+ JDK, and not a JRE *and* that your class path includes tools.jar." ); |
753 |
|
- |
} |
754 |
|
- |
int zError = compiler.run( getCompile_in(), getCompile_out(), getCompile_err(), pCompileArgs.toArray( new String[pCompileArgs.size()] ) ); |
755 |
|
- |
if ( zError != 0 ) |
756 |
|
- |
{ |
757 |
|
- |
String zMessage = "Error (" + zError + ") during compilation of project: " + this + |
758 |
|
- |
"\nSource: " + pSource.count() + " files\nCompilerArgs: " + pCompileArgs; |
759 |
|
- |
if ( LOGGER.debug.isEnabled() ) |
760 |
|
- |
{ |
761 |
|
- |
zMessage += "\nClasspath: " + pClasspath + "\nSource: " + pSource.toString( " " ); |
762 |
|
- |
} |
763 |
|
- |
throw new RuntimeException( zMessage ); |
764 |
|
- |
} |
765 |
|
- |
try |
766 |
|
- |
{ |
767 |
|
- |
Thread.sleep( 100 ); |
768 |
|
- |
} |
769 |
|
- |
catch ( InterruptedException ex ) |
770 |
|
- |
{ |
771 |
|
- |
// Whatever |
772 |
|
- |
} |
773 |
|
- |
} |
774 |
|
- |
|
775 |
|
- |
protected InputStream getCompile_in() |
776 |
|
- |
{ |
777 |
|
- |
return null; |
778 |
|
- |
} |
779 |
|
- |
|
780 |
|
- |
protected OutputStream getCompile_out() |
781 |
|
- |
{ |
782 |
|
- |
return null; |
783 |
|
- |
} |
784 |
|
- |
|
785 |
|
- |
protected OutputStream getCompile_err() |
786 |
|
- |
{ |
787 |
|
- |
return new OutputStream() |
788 |
|
- |
{ |
789 |
|
- |
private StringBuilder mBuffer = new StringBuilder(); |
790 |
|
- |
private boolean mLastWasCRtreatedAsLF = false; |
791 |
|
- |
|
792 |
|
- |
private void dumpLine( int pByte ) |
793 |
|
- |
{ |
794 |
|
- |
if ( pByte == 13 ) |
795 |
|
- |
{ |
796 |
|
- |
mLastWasCRtreatedAsLF = true; |
797 |
|
- |
pByte = 10; |
798 |
|
- |
} |
799 |
|
- |
else |
800 |
|
- |
{ |
801 |
|
- |
boolean zLastWasCRtreatedAsLF = mLastWasCRtreatedAsLF; |
802 |
|
- |
mLastWasCRtreatedAsLF = false; |
803 |
|
- |
if ( (pByte == 10) && zLastWasCRtreatedAsLF ) |
804 |
|
- |
{ |
805 |
|
- |
return; |
806 |
|
- |
} |
807 |
|
- |
} |
808 |
|
- |
mBuffer.append( (char) pByte ); // Assuming Ascii! |
809 |
|
- |
String line = mBuffer.toString(); |
810 |
|
- |
mBuffer = new StringBuilder(); |
811 |
|
- |
if ( !line.startsWith( "Note: " ) ) |
812 |
|
- |
{ |
813 |
|
- |
System.err.print( line ); |
814 |
|
- |
} |
815 |
|
- |
} |
816 |
|
- |
|
817 |
|
- |
@Override |
818 |
|
- |
public void write( int pByte ) // Not a Unicode character, just a BYTE! --- Asumming Ascii --- |
819 |
|
- |
throws IOException |
820 |
|
- |
{ |
821 |
|
- |
if ( (10 <= pByte) && (pByte <= 13) ) // New Line Indicator |
822 |
|
- |
{ // LF: Line Feed, U+000A |
823 |
|
- |
dumpLine( pByte ); // VT: Vertical Tab, U+000B |
824 |
|
- |
return; // FF: Form Feed, U+000C |
825 |
|
- |
} // CR: Carriage Return, U+000D |
826 |
|
- |
mBuffer.append( (char) pByte ); // Assuming Ascii! |
827 |
|
- |
} |
828 |
|
- |
}; |
829 |
|
- |
} |
830 |
|
- |
|
831 |
|
- |
/** |
832 |
|
- |
* Collects the class files from the "classes" directory and all the resource files using the "resources" property and encodes |
833 |
|
- |
* them into a JAR file. |
834 |
|
- |
* <p/> |
835 |
|
- |
* If the resources don't contain a META-INF/MANIFEST.MF file, one is generated. If the project has a main property, the |
836 |
|
- |
* generated manifest will include "Main-Class" and "Class-Path" entries to allow the main class to be run with "java -jar". |
837 |
|
- |
* |
838 |
|
- |
* @return The path to the created JAR file or null if No JAR created. |
839 |
|
- |
*/ |
840 |
|
- |
public String jar() |
841 |
|
- |
{ |
842 |
|
- |
String zJarPath = getJarPath(); |
843 |
|
- |
|
844 |
|
- |
Paths zClasses = new Paths( path( "$target$/classes/" ), "**.class" ); |
845 |
|
- |
Paths zResources = getResources(); |
846 |
|
- |
if ( zClasses.isEmpty() && zResources.isEmpty() ) |
847 |
|
- |
{ |
848 |
|
- |
delete( zJarPath ); |
849 |
|
- |
return null; |
850 |
|
- |
} |
851 |
|
- |
progress( "JAR: " + this + " -> " + zJarPath ); |
852 |
|
- |
|
853 |
|
- |
String jarDir = mkdir( path( "$target$/jar/" ) ); |
854 |
|
- |
|
855 |
|
- |
zClasses.copyTo( jarDir ); |
856 |
|
- |
zResources.copyTo( jarDir ); |
857 |
|
- |
|
858 |
|
- |
File manifestFile = new File( jarDir, "META-INF/MANIFEST.MF" ); |
859 |
|
- |
if ( !manifestFile.exists() ) |
860 |
|
- |
{ |
861 |
|
- |
createDefaultManifestFile( zJarPath, manifestFile ); |
862 |
|
- |
} |
863 |
|
- |
|
864 |
|
- |
return jar( zJarPath, new Paths( jarDir ) ); |
865 |
|
- |
} |
866 |
|
- |
|
867 |
|
- |
protected void createDefaultManifestFile( String pJarFile, File pManifestFile ) |
868 |
|
- |
{ |
869 |
|
- |
LOGGER.debug.log( "Generating JAR manifest: ", pManifestFile ); |
870 |
|
- |
mkdir( pManifestFile.getParent() ); |
871 |
|
- |
Manifest manifest = new Manifest(); |
872 |
|
- |
manifest.getMainAttributes().putValue( Attributes.Name.MANIFEST_VERSION.toString(), "1.0" ); |
873 |
|
- |
if ( hasMain() ) |
874 |
|
- |
{ |
875 |
|
- |
LOGGER.debug.log( "Main class: ", getMain() ); |
876 |
|
- |
manifest.getMainAttributes().putValue( Attributes.Name.MAIN_CLASS.toString(), getMain() ); |
877 |
|
- |
StringBuilder buffer = new StringBuilder( 512 ); |
878 |
|
- |
buffer.append( Utils.fileName( pJarFile ) ); |
879 |
|
- |
buffer.append( " ." ); |
880 |
|
- |
Paths classpath = classpath(); |
881 |
|
- |
for ( String name : classpath.getRelativePaths( pJarFile ) ) |
882 |
|
- |
{ |
883 |
|
- |
buffer.append( ' ' ); |
884 |
|
- |
buffer.append( name ); |
885 |
|
- |
} |
886 |
|
- |
manifest.getMainAttributes().putValue( Attributes.Name.CLASS_PATH.toString(), buffer.toString() ); |
887 |
|
- |
} |
888 |
|
- |
OutputStream output = createFileOutputStream( pManifestFile ); |
889 |
|
- |
try |
890 |
|
- |
{ |
891 |
|
- |
manifest.write( output ); |
892 |
|
- |
Closeable zCloseable = output; |
893 |
|
- |
output = null; |
894 |
|
- |
close( zCloseable ); |
895 |
|
- |
} |
896 |
|
- |
catch ( IOException e ) |
897 |
|
- |
{ |
898 |
|
- |
throw new WrappedIOException( e ); |
899 |
|
- |
} |
900 |
|
- |
finally |
901 |
|
- |
{ |
902 |
|
- |
dispose( output ); |
903 |
|
- |
} |
904 |
|
- |
} |
905 |
|
- |
|
906 |
|
- |
/** |
907 |
|
- |
* Encodes the specified paths into a JAR file. |
908 |
|
- |
* |
909 |
|
- |
* @return The path to the JAR file. |
910 |
|
- |
*/ |
911 |
|
- |
public String jar( String jarFile, Paths paths ) |
912 |
|
- |
{ |
913 |
|
- |
return innerJar( "JAR", jarFile, paths ); |
914 |
|
- |
} |
915 |
|
- |
|
916 |
|
- |
/** |
917 |
|
- |
* Encodes the specified paths into a JAR/WAR file. |
918 |
|
- |
* |
919 |
|
- |
* @return The path to the JAR/WAR file. |
920 |
|
- |
*/ |
921 |
|
- |
protected String innerJar( String pType, String jarFile, Paths paths ) |
922 |
|
- |
{ |
923 |
|
- |
Util.assertNotNull( "jarFile", jarFile ); |
924 |
|
- |
Util.assertNotNull( "paths", paths ); |
925 |
|
- |
|
926 |
|
- |
progress( "Creating " + pType + " (" + paths.count() + " entries): " + jarFile ); |
927 |
|
- |
|
928 |
|
- |
int zZipped = paths.zip( jarFile, new ZipFactory() |
929 |
|
- |
{ |
930 |
|
- |
@Override |
931 |
|
- |
public ZipOutputStream createZOS( String pFilePath, List<FilePath> pPaths ) |
932 |
|
- |
{ |
933 |
|
- |
putManifestFirst( pPaths ); |
934 |
|
- |
try |
935 |
|
- |
{ |
936 |
|
- |
return new JarOutputStream( FileUtil.createBufferedFileOutputStream( pFilePath ) ); |
937 |
|
- |
} |
938 |
|
- |
catch ( IOException e ) |
939 |
|
- |
{ |
940 |
|
- |
throw new WrappedIOException( e ); |
941 |
|
- |
} |
942 |
|
- |
} |
943 |
|
- |
|
944 |
|
- |
@Override |
945 |
|
- |
public ZipEntry createZE( String pRelativePath ) |
946 |
|
- |
{ |
947 |
|
- |
return new JarEntry( pRelativePath ); |
948 |
|
- |
} |
949 |
|
- |
|
950 |
|
- |
private void putManifestFirst( List<FilePath> pPaths ) |
951 |
|
- |
{ |
952 |
|
- |
int at = findManifest( pPaths ); |
953 |
|
- |
if ( at > 0 ) |
954 |
|
- |
{ |
955 |
|
- |
FilePath zManifest = pPaths.remove( at ); |
956 |
|
- |
pPaths.add( 0, zManifest ); |
957 |
|
- |
} |
958 |
|
- |
} |
959 |
|
- |
|
960 |
|
- |
private int findManifest( List<FilePath> pPaths ) |
961 |
|
- |
{ |
962 |
|
- |
for ( int i = 0; i < pPaths.size(); i++ ) |
963 |
|
- |
{ |
964 |
|
- |
if ( META_INF_MANIFEST_MF.equals( pPaths.get( i ).getFileSubPath() ) ) |
965 |
|
- |
{ |
966 |
|
- |
return i; |
967 |
|
- |
} |
968 |
|
- |
} |
969 |
|
- |
return -1; |
970 |
|
- |
} |
971 |
|
- |
} ); |
972 |
|
- |
return zZipped == 0 ? null : jarFile; |
973 |
|
- |
} |
974 |
|
- |
|
975 |
|
- |
/** |
976 |
|
- |
* Decodes the specified ZIP file. |
977 |
|
- |
* |
978 |
|
- |
* @return The path to the output directory. |
979 |
|
- |
*/ |
980 |
|
- |
protected void quiteUnzip( File zipFile, File outputDir ) |
981 |
|
- |
{ |
982 |
|
- |
ZipInputStream input = new ZipInputStream( createFileInputStream( zipFile ) ); |
983 |
|
- |
try |
984 |
|
- |
{ |
985 |
|
- |
for ( ZipEntry entry; null != (entry = input.getNextEntry()); ) |
986 |
|
- |
{ |
987 |
|
- |
File file = new File( outputDir, entry.getName() ); |
988 |
|
- |
if ( entry.isDirectory() ) |
989 |
|
- |
{ |
990 |
|
- |
mkdir( file.getPath() ); |
991 |
|
- |
continue; |
992 |
|
- |
} |
993 |
|
- |
writeStream( input, createFileOutputStream( file ) ); |
994 |
|
- |
} |
995 |
|
- |
} |
996 |
|
- |
catch ( IOException e ) |
997 |
|
- |
{ |
998 |
|
- |
throw new WrappedIOException( e ); |
999 |
|
- |
} |
1000 |
|
- |
finally |
1001 |
|
- |
{ |
1002 |
|
- |
dispose( input ); |
1003 |
|
- |
} |
1004 |
|
- |
} |
1005 |
|
- |
|
1006 |
|
- |
/** |
1007 |
|
- |
* Decodes the specified ZIP file. |
1008 |
|
- |
*/ |
1009 |
|
- |
public void unzip( File zipFile, File outputDir ) |
1010 |
|
- |
{ |
1011 |
|
- |
Util.assertNotNull( "zipFile", zipFile ); |
1012 |
|
- |
Util.assertNotNull( "outputDir", outputDir ); |
1013 |
|
- |
progress( "ZIP decoding: " + zipFile.getPath() + " -> " + outputDir.getPath() ); |
1014 |
|
- |
quiteUnzip( zipFile, outputDir ); |
1015 |
|
- |
} |
1016 |
|
- |
|
1017 |
|
- |
/** |
1018 |
|
- |
* Decodes the specified ZIP file. |
1019 |
|
- |
* |
1020 |
|
- |
* @return The path to the output directory. |
1021 |
|
- |
*/ |
1022 |
|
- |
public String unzip( String zipFile, String outputDir ) |
1023 |
|
- |
{ |
1024 |
|
- |
zipFile = assertNotEmpty( "zipFile", zipFile ); |
1025 |
|
- |
outputDir = assertNotEmpty( "outputDir", outputDir ); |
1026 |
|
- |
progress( "ZIP decoding: " + zipFile + " -> " + outputDir ); |
1027 |
|
- |
quiteUnzip( new File( zipFile ), new File( outputDir ) ); |
1028 |
|
- |
return outputDir; |
1029 |
|
- |
} |
1030 |
|
- |
|
1031 |
|
- |
/** |
1032 |
|
- |
* Computes the classpath for the specified project and all its dependency projects, recursively. |
1033 |
|
- |
*/ |
1034 |
|
- |
protected Paths compileClasspath() |
1035 |
|
- |
{ |
1036 |
|
- |
Paths classpath = getCompileClasspath(); |
1037 |
|
- |
classpath.add( getClasspath() ); |
1038 |
|
- |
for ( Project zProject : mDependantProjects ) |
1039 |
|
- |
{ |
1040 |
|
- |
zProject.addDependantProjectsCompileClassPaths( classpath ); |
1041 |
|
- |
} |
1042 |
|
- |
return classpath; |
1043 |
|
- |
} |
1044 |
|
- |
|
1045 |
|
- |
/** |
1046 |
|
- |
* Computes the classpath for all the dependencies of the specified project, recursively. |
1047 |
|
- |
*/ |
1048 |
|
- |
protected void addDependantProjectsCompileClassPaths( Paths pPathsToAddTo ) |
1049 |
|
- |
{ |
1050 |
|
- |
addDependentProjectJar( pPathsToAddTo ); |
1051 |
|
- |
pPathsToAddTo.add( compileClasspath() ); |
1052 |
|
- |
} |
1053 |
|
- |
|
1054 |
|
- |
/** |
1055 |
|
- |
* Computes the classpath for the specified project and all its dependency projects, recursively. |
1056 |
|
- |
*/ |
1057 |
|
- |
protected Paths classpath() |
1058 |
|
- |
{ |
1059 |
|
- |
Paths classpath = getClasspath(); |
1060 |
|
- |
for ( Project zProject : mDependantProjects ) |
1061 |
|
- |
{ |
1062 |
|
- |
zProject.addDependantProjectsClassPaths( classpath ); |
1063 |
|
- |
} |
1064 |
|
- |
return classpath; |
1065 |
|
- |
} |
1066 |
|
- |
|
1067 |
|
- |
/** |
1068 |
|
- |
* Computes the classpath for all the dependencies of the specified project, recursively. |
1069 |
|
- |
*/ |
1070 |
|
- |
protected void addDependantProjectsClassPaths( Paths pPathsToAddTo ) |
1071 |
|
- |
{ |
1072 |
|
- |
addDependentProjectJar( pPathsToAddTo ); |
1073 |
|
- |
pPathsToAddTo.add( classpath() ); |
1074 |
|
- |
} |
1075 |
|
- |
|
1076 |
|
- |
protected void addDependentProjectJar( Paths pPathsToAddTo ) |
1077 |
|
- |
{ |
1078 |
|
- |
if ( mSources ) |
1079 |
|
- |
{ |
1080 |
|
- |
File zJarFile = getJarPathFile(); |
1081 |
|
- |
if ( !zJarFile.isFile() ) |
1082 |
|
- |
{ |
1083 |
|
- |
throw new RuntimeException( "Dependency (" + this + ") Jar not found, not built?" ); |
1084 |
|
- |
} |
1085 |
|
- |
pPathsToAddTo.add( new FilePath( zJarFile.getParentFile(), zJarFile.getName() ) ); |
1086 |
|
- |
} |
1087 |
|
- |
} |
1088 |
|
- |
|
1089 |
|
- |
/** |
1090 |
|
- |
* Calls {@link #build(Project)} for each dependency project in the specified project. |
1091 |
|
- |
*/ |
1092 |
|
- |
public boolean buildDependencies() |
1093 |
|
- |
{ |
1094 |
|
- |
boolean anyBuilt = false; |
1095 |
|
- |
for ( Project zProject : mDependantProjects ) |
1096 |
|
- |
{ |
1097 |
|
- |
anyBuilt |= zProject.build(); |
1098 |
|
- |
} |
1099 |
|
- |
return anyBuilt; |
1100 |
|
- |
} |
1101 |
|
- |
|
1102 |
|
- |
public void set( Object key, Object object ) |
1103 |
|
- |
{ |
1104 |
|
- |
mManager.put( updatableKey( key ), object ); |
1105 |
|
- |
} |
1106 |
|
- |
|
1107 |
|
- |
public void remove( Object key ) |
1108 |
|
- |
{ |
1109 |
|
- |
set( key, null ); |
1110 |
|
- |
} |
1111 |
|
- |
|
1112 |
|
- |
/** |
1113 |
|
- |
* Removes an item from a list or map. If the mData under the specified key is a list, the entry equal to the specified value is |
1114 |
|
- |
* removed. If the mData under the specified key is a map, the entry with the key specified by value is removed. |
1115 |
|
- |
*/ |
1116 |
|
- |
public void remove( Object key, Object value ) |
1117 |
|
- |
{ |
1118 |
|
- |
mManager.remove( updatableKey( key ), value ); |
1119 |
|
- |
} |
1120 |
|
- |
|
1121 |
|
- |
private Object updatableKey( Object pKey ) |
1122 |
|
- |
{ |
1123 |
|
- |
if ( pKey instanceof String ) |
1124 |
|
- |
{ |
1125 |
|
- |
String zStrKey = noEmpty( pKey.toString().toLowerCase() ); |
1126 |
|
- |
if ( Parameter.reservedNames().contains( zStrKey ) ) |
1127 |
|
- |
{ |
1128 |
|
- |
throw new IllegalArgumentException( zStrKey + " not updatable!" ); |
1129 |
|
- |
} |
1130 |
|
- |
pKey = zStrKey; |
1131 |
|
- |
} |
1132 |
|
- |
Util.assertNotNull( "key", pKey ); |
1133 |
|
- |
return pKey; |
1134 |
|
- |
} |
1135 |
|
- |
|
1136 |
|
- |
public synchronized void initialize( ProjectFactory pProjectFactory ) |
1137 |
|
- |
{ |
1138 |
|
- |
List<String> zDependencies = getDependencies(); |
1139 |
|
- |
if ( zDependencies != null ) |
1140 |
|
- |
{ |
1141 |
|
- |
for ( String zDependency : zDependencies ) |
1142 |
|
- |
{ |
1143 |
|
- |
mDependantProjects.add( pProjectFactory.project( mCanonicalProjectDir, zDependency ) ); |
1144 |
|
- |
} |
1145 |
|
- |
} |
1146 |
|
- |
|
1147 |
|
- |
// Project defaults = new Project(); |
1148 |
|
- |
// |
1149 |
|
- |
// File file = new File( canonical( pPath ) ); |
1150 |
|
- |
// if ( file.isDirectory() ) |
1151 |
|
- |
// { |
1152 |
|
- |
// String name = file.getName(); |
1153 |
|
- |
// defaults.set( "name", name ); |
1154 |
|
- |
// defaults.set( "target", file.getParent() + "/target/" + name + "/" ); |
1155 |
|
- |
// } |
1156 |
|
- |
// else |
1157 |
|
- |
// { |
1158 |
|
- |
// String name = file.getParentFile().getName(); |
1159 |
|
- |
// defaults.set( "name", name ); |
1160 |
|
- |
// defaults.set( "target", file.getParentFile().getParent() + "/target/" + name + "/" ); |
1161 |
|
- |
// } |
1162 |
|
- |
// defaults.set( "classpath", "lib|**/*.jar" ); |
1163 |
|
- |
// defaults.set( "dist", "dist" ); |
1164 |
|
- |
// |
1165 |
|
- |
// List<String> source = new ArrayList<String>(); |
1166 |
|
- |
// source.add( "src|**/*.java" ); |
1167 |
|
- |
// source.add( "src/main/java|**/*.java" ); |
1168 |
|
- |
// defaults.set( "source", source ); |
1169 |
|
- |
// |
1170 |
|
- |
// List<String> resources = new ArrayList<String>(); |
1171 |
|
- |
// resources.add( "resources" ); |
1172 |
|
- |
// resources.add( "src/main/resources" ); |
1173 |
|
- |
// defaults.set( "resources", resources ); |
1174 |
|
- |
// |
1175 |
|
- |
// Project project = project( pPath, defaults ); |
1176 |
|
- |
// |
1177 |
|
- |
// // Remove dependency if a JAR of the same name is on the classpath. |
1178 |
|
- |
// Paths classpath = project.getPaths( "classpath" ); |
1179 |
|
- |
// classpath.add( dependencyClasspaths( project, classpath, false, false ) ); |
1180 |
|
- |
// for ( String dependency : project.getDependencies() ) |
1181 |
|
- |
// { |
1182 |
|
- |
// String dependencyName = project( project.path( dependency ) ).getName(); |
1183 |
|
- |
// for ( String classpathFile : classpath ) |
1184 |
|
- |
// { |
1185 |
|
- |
// String name = fileWithoutExtension( classpathFile ); |
1186 |
|
- |
// int dashIndex = name.lastIndexOf( '-' ); |
1187 |
|
- |
// if ( dashIndex != -1 ) |
1188 |
|
- |
// { |
1189 |
|
- |
// name = name.substring( 0, dashIndex ); |
1190 |
|
- |
// } |
1191 |
|
- |
// if ( name.equals( dependencyName ) ) |
1192 |
|
- |
// { |
1193 |
|
- |
// if ( DEBUG ) |
1194 |
|
- |
// { |
1195 |
|
- |
// debug( "Ignoring " + project + " dependency: " + dependencyName + " (already on classpath: " + classpathFile + ")" ); |
1196 |
|
- |
// } |
1197 |
|
- |
// project.remove( "dependencies", dependency ); |
1198 |
|
- |
// break; |
1199 |
|
- |
// } |
1200 |
|
- |
// } |
1201 |
|
- |
// } |
1202 |
|
- |
// |
1203 |
|
- |
// if ( TRACE ) |
1204 |
|
- |
// { |
1205 |
|
- |
// trace( "scar", "Project: " + project + "\n" + project ); |
1206 |
|
- |
// } |
1207 |
|
- |
// |
1208 |
|
- |
// return project; |
1209 |
|
- |
} |
1210 |
|
- |
|
1211 |
|
- |
protected boolean mBuilt = false; |
1212 |
|
- |
protected boolean mSources = false; |
1213 |
|
- |
protected List<Project> mDependantProjects = new ArrayList<Project>(); |
1214 |
|
- |
} |
|
1 |
+ |
package com.esotericsoftware.scar; |
|
2 |
+ |
|
|
3 |
+ |
import org.litesoft.logger.*; |
|
4 |
+ |
|
|
5 |
+ |
import com.esotericsoftware.filesystem.*; |
|
6 |
+ |
import com.esotericsoftware.scar.support.*; |
|
7 |
+ |
import com.esotericsoftware.utils.*; |
|
8 |
+ |
|
|
9 |
+ |
import javax.tools.*; |
|
10 |
+ |
import java.io.*; |
|
11 |
+ |
import java.util.*; |
|
12 |
+ |
import java.util.jar.*; |
|
13 |
+ |
import java.util.zip.*; |
|
14 |
+ |
|
|
15 |
+ |
/** |
|
16 |
+ |
* Generic Data structure that contains information needed to perform tasks. |
|
17 |
+ |
*/ |
|
18 |
+ |
@SuppressWarnings("UnusedDeclaration") |
|
19 |
+ |
public class Project extends ProjectParameters { |
|
20 |
+ |
private static final String JAVA_SOURCE_TARGET_VERSION = "1.7"; |
|
21 |
+ |
|
|
22 |
+ |
protected static final Logger LOGGER = LoggerFactory.getLogger( Project.class ); |
|
23 |
+ |
|
|
24 |
+ |
private static final String META_INF_MANIFEST_MF = "META-INF/MANIFEST.MF"; |
|
25 |
+ |
|
|
26 |
+ |
private static final String VERSIONED_URL_PATTERN_PREFIX = "<url-pattern>/v"; |
|
27 |
+ |
private static final String VERSIONED_SCRIPT_PREFIX = "<script src='v"; |
|
28 |
+ |
private static final String VERSIONED_SCRIPT_SUFFIX = ".nocache.js'></script>"; |
|
29 |
+ |
private static final String VERSIONED_MODULE_PREFIX = "<module rename-to=\"v"; |
|
30 |
+ |
private static final String VERSIONED_MODULE_SUFFIX = "\">"; |
|
31 |
+ |
private static final String JAVA_HOME = "JAVA_HOME"; |
|
32 |
+ |
|
|
33 |
+ |
public Project( ProjectParameters pParameters ) { |
|
34 |
+ |
super( pParameters.validate() ); |
|
35 |
+ |
applyDefaults(); |
|
36 |
+ |
} |
|
37 |
+ |
|
|
38 |
+ |
public String getSourceJavaVersion() { |
|
39 |
+ |
return JAVA_SOURCE_TARGET_VERSION; |
|
40 |
+ |
} |
|
41 |
+ |
|
|
42 |
+ |
public String getTargetJavaVersion() { |
|
43 |
+ |
return JAVA_SOURCE_TARGET_VERSION; |
|
44 |
+ |
} |
|
45 |
+ |
|
|
46 |
+ |
protected void packageClean() { |
|
47 |
+ |
delete( getPhoneGapDirPath() ); |
|
48 |
+ |
delete( getAppDirPath() ); |
|
49 |
+ |
delete( getOneJarPath() ); |
|
50 |
+ |
delete( getWarPath() ); |
|
51 |
+ |
} |
|
52 |
+ |
|
|
53 |
+ |
protected boolean packageIt() { |
|
54 |
+ |
return phoneGapDir() | appDir() | oneJAR() | war(); // Note: SINGLE '|' ORs to force full execution! |
|
55 |
+ |
} |
|
56 |
+ |
|
|
57 |
+ |
/** |
|
58 |
+ |
* Unzips all JARs in the classpath and creates a single JAR containing those files and this Project's JAR (which MUST exist). |
|
59 |
+ |
* The manifest from the project's JAR is used. Putting everything into a single JAR makes it harder to see what libraries are |
|
60 |
+ |
* being used, but makes it easier for end users to distribute the application. |
|
61 |
+ |
* <p/> |
|
62 |
+ |
* Note: Files with the same path in different JARs will be overwritten. Files in the project's JAR will never be overwritten, |
|
63 |
+ |
* but may overwrite other files. |
|
64 |
+ |
* |
|
65 |
+ |
* @param pExcludeJARs The names of any JARs to exclude. |
|
66 |
+ |
* |
|
67 |
+ |
* @return True if the "OneJAR" was created / updated or false if no OneJar is NOT requested for this project or it was not needed. |
|
68 |
+ |
*/ |
|
69 |
+ |
public boolean oneJAR( String... pExcludeJARs ) { |
|
70 |
+ |
File zOneJarPath = getOneJarPathFile(); |
|
71 |
+ |
|
|
72 |
+ |
if ( zOneJarPath == null ) { |
|
73 |
+ |
return false; |
|
74 |
+ |
} |
|
75 |
+ |
|
|
76 |
+ |
File zJarPath = getJarPathFile(); |
|
77 |
+ |
if ( !zJarPath.isFile() ) { |
|
78 |
+ |
throw new IllegalStateException( "One JAR: " + this + " requested, BUT NO jar File produced at: " + zJarPath.getPath() ); |
|
79 |
+ |
} |
|
80 |
+ |
|
|
81 |
+ |
if ( zOneJarPath.isFile() && (zOneJarPath.lastModified() >= zJarPath.lastModified()) ) { |
|
82 |
+ |
progress( "One JAR: " + this + " NOT Needed!" ); |
|
83 |
+ |
return false; |
|
84 |
+ |
} |
|
85 |
+ |
|
|
86 |
+ |
Paths zClasspath = classpath(); |
|
87 |
+ |
if ( zClasspath.isEmpty() ) { |
|
88 |
+ |
progress( "One JAR: " + this + " No supporting Jars! Simply Copying to: " + zOneJarPath.getPath() ); |
|
89 |
+ |
copyFile( zJarPath, zOneJarPath ); |
|
90 |
+ |
return true; |
|
91 |
+ |
} |
|
92 |
+ |
progress( "One JAR: " + this ); |
|
93 |
+ |
|
|
94 |
+ |
File zOnejarDir = mkdir( new File( path( "$target$/onejar/" ) ) ); |
|
95 |
+ |
|
|
96 |
+ |
List<String> zExcludeJARs = Arrays.asList( pExcludeJARs ); |
|
97 |
+ |
for ( File jarFile : zClasspath.getFiles() ) // All our Class Path (dependant) JARS |
|
98 |
+ |
{ |
|
99 |
+ |
if ( !zExcludeJARs.contains( jarFile.getName() ) ) { |
|
100 |
+ |
unzip( jarFile, zOnejarDir ); |
|
101 |
+ |
} |
|
102 |
+ |
} |
|
103 |
+ |
|
|
104 |
+ |
unzip( zJarPath, zOnejarDir ); // Our Jar! - Our Manifest will be "the" Manifest !!!!!! Need to remove class PATH! |
|
105 |
+ |
innerJar( "'ONE' JAR", zOneJarPath.getPath(), new Paths( zOnejarDir.getPath() ) ); |
|
106 |
+ |
return true; |
|
107 |
+ |
} |
|
108 |
+ |
|
|
109 |
+ |
/** |
|
110 |
+ |
* Collects the distribution files using the "dist" property, the project's JAR file, and everything on the project's classpath |
|
111 |
+ |
* (including dependency project classpaths) and places them into the specified directory. This is also done for depenency projects, |
|
112 |
+ |
* recursively. This is everything the application needs to be run from JAR files. |
|
113 |
+ |
* |
|
114 |
+ |
* @return True if the PhoneGapDir was populated or false if no distribution (App Dir) is requested for this project. |
|
115 |
+ |
*/ |
|
116 |
+ |
public boolean phoneGapDir() { |
|
117 |
+ |
String zPhoneGapDir = getPhoneGapDirPath(); |
|
118 |
+ |
if ( zPhoneGapDir == null ) { |
|
119 |
+ |
return false; |
|
120 |
+ |
} |
|
121 |
+ |
Paths zPaths = new Paths( getGWTwarPath(), "**.js", "**.gif" ); |
|
122 |
+ |
zPaths.add( getDist() ); |
|
123 |
+ |
|
|
124 |
+ |
File zPhoneGapDirFile = new File( zPhoneGapDir ); |
|
125 |
+ |
if ( zPhoneGapDirFile.exists() ) { |
|
126 |
+ |
if ( zPhoneGapDirFile.lastModified() >= zPaths.getGreatestLastModified() ) { |
|
127 |
+ |
progress( "PhoneGapDir: " + this + " NOT Needed!" ); |
|
128 |
+ |
return false; |
|
129 |
+ |
} |
|
130 |
+ |
delete( zPhoneGapDirFile ); |
|
131 |
+ |
} |
|
132 |
+ |
|
|
133 |
+ |
progress( "PhoneGapDir: " + this + " -> " + zPhoneGapDir ); |
|
134 |
+ |
String distDir = mkdir( zPhoneGapDir ); // Give it a new Timestamp |
|
135 |
+ |
zPaths.copyTo( distDir ); |
|
136 |
+ |
return true; |
|
137 |
+ |
} |
|
138 |
+ |
|
|
139 |
+ |
/** |
|
140 |
+ |
* Collects the distribution files using the "dist" property, the project's JAR file, and everything on the project's classpath |
|
141 |
+ |
* (including dependency project classpaths) and places them into the specified directory. This is also done for depenency projects, |
|
142 |
+ |
* recursively. This is everything the application needs to be run from JAR files. |
|
143 |
+ |
* |
|
144 |
+ |
* @return True if the AppDir was populated or false if no distribution (App Dir) is requested for this project. |
|
145 |
+ |
*/ |
|
146 |
+ |
public boolean appDir() { |
|
147 |
+ |
String zAppDir = getAppDirPath(); |
|
148 |
+ |
if ( zAppDir == null ) { |
|
149 |
+ |
return false; |
|
150 |
+ |
} |
|
151 |
+ |
File zJarPath = getJarPathFile(); |
|
152 |
+ |
if ( !zJarPath.isFile() ) { |
|
153 |
+ |
progress( "AppDir: " + this + " BUT NO jar File produced at: " + zJarPath.getPath() ); |
|
154 |
+ |
return false; |
|
155 |
+ |
} |
|
156 |
+ |
Paths zPaths = new Paths(); |
|
157 |
+ |
addDependantProjectsDistPaths( zPaths ); |
|
158 |
+ |
zPaths.add( classpath() ); |
|
159 |
+ |
zPaths.add( FilePath.canonicalize( getJarPathFile() ) ); |
|
160 |
+ |
|
|
161 |
+ |
File zAppDirFile = new File( zAppDir ); |
|
162 |
+ |
if ( zAppDirFile.exists() ) { |
|
163 |
+ |
if ( zAppDirFile.lastModified() >= zPaths.getGreatestLastModified() ) { |
|
164 |
+ |
progress( "AppDir: " + this + " NOT Needed!" ); |
|
165 |
+ |
return false; |
|
166 |
+ |
} |
|
167 |
+ |
delete( zAppDirFile ); |
|
168 |
+ |
} |
|
169 |
+ |
|
|
170 |
+ |
progress( "AppDir: " + this + " -> " + zAppDir ); |
|
171 |
+ |
String distDir = mkdir( zAppDir ); // Give it a new Timestamp |
|
172 |
+ |
zPaths.copyTo( distDir ); |
|
173 |
+ |
return true; |
|
174 |
+ |
} |
|
175 |
+ |
|
|
176 |
+ |
/** |
|
177 |
+ |
* Produce either a 'war' directory or a '.war' file, in theory ready to deploy to a servlet/web container. |
|
178 |
+ |
* |
|
179 |
+ |
* @return true if the 'war' was created. |
|
180 |
+ |
*/ |
|
181 |
+ |
public boolean war() { |
|
182 |
+ |
String zWar = getWar(); |
|
183 |
+ |
if ( zWar == null ) { |
|
184 |
+ |
return false; |
|
185 |
+ |
} |
|
186 |
+ |
File zJarPath = getJarPathFile(); |
|
187 |
+ |
if ( !zJarPath.isFile() ) { |
|
188 |
+ |
progress( "WAR: " + this + " BUT NO jar File produced at: " + zJarPath.getPath() ); |
|
189 |
+ |
return false; |
|
190 |
+ |
} |
|
191 |
+ |
|
|
192 |
+ |
Paths zDistPaths = new Paths(); |
|
193 |
+ |
addDependantProjectsDistPaths( zDistPaths ); |
|
194 |
+ |
if ( null != getGWT() ) { |
|
195 |
+ |
zDistPaths.add( new Paths( getGWTwarPath() ) ); |
|
196 |
+ |
} |
|
197 |
+ |
|
|
198 |
+ |
Paths zClassPath = new Paths(); |
|
199 |
+ |
zClassPath.add( FilePath.canonical( getGWTatDir(), GWT_SERVLET ) ); |
|
200 |
+ |
zClassPath.add( classpath() ); |
|
201 |
+ |
zClassPath.add( FilePath.canonicalize( getJarPathFile() ) ); |
|
202 |
+ |
|
|
203 |
+ |
File zWarPathFile = getWarPathFile(); |
|
204 |
+ |
if ( zWarPathFile.exists() ) { |
|
205 |
+ |
long zWarLastModified = zWarPathFile.lastModified(); |
|
206 |
+ |
if ( (zWarLastModified >= zClassPath.getGreatestLastModified()) && (zWarLastModified >= zDistPaths.getGreatestLastModified()) ) { |
|
207 |
+ |
progress( "WAR: " + this + " NOT Needed!" ); |
|
208 |
+ |
return false; |
|
209 |
+ |
} |
|
210 |
+ |
delete( zWarPathFile ); |
|
211 |
+ |
} |
|
212 |
+ |
|
|
213 |
+ |
boolean zWarIt = zWar.endsWith( ".war" ); |
|
214 |
+ |
|
|
215 |
+ |
File zWarDir = zWarPathFile; |
|
216 |
+ |
if ( zWarIt ) { |
|
217 |
+ |
zWarDir = new File( path( "$target$/war/" ) ); |
|
218 |
+ |
delete( zWarDir ); |
|
219 |
+ |
} |
|
220 |
+ |
|
|
221 |
+ |
progress( "WAR: " + this + " -> " + zWarDir.getPath() ); |
|
222 |
+ |
|
|
223 |
+ |
File zWarDirLibPath = new File( zWarDir, "WEB-INF/lib" ); |
|
224 |
+ |
mkdir( zWarDirLibPath ); |
|
225 |
+ |
|
|
226 |
+ |
zDistPaths.copyTo( zWarDir.getPath() ); |
|
227 |
+ |
zClassPath.copyTo( zWarDirLibPath.getPath() ); |
|
228 |
+ |
|
|
229 |
+ |
if ( zWarIt ) { |
|
230 |
+ |
innerJar( "WAR", zWarPathFile.getPath(), new Paths( zWarDir.getPath() ) ); |
|
231 |
+ |
} |
|
232 |
+ |
return true; |
|
233 |
+ |
} |
|
234 |
+ |
|
|
235 |
+ |
/** |
|
236 |
+ |
* Computes the classpath for all the dependencies of the specified project, recursively. |
|
237 |
+ |
*/ |
|
238 |
+ |
protected void addDependantProjectsDistPaths( Paths pPathsToAddTo ) { |
|
239 |
+ |
for ( Project zProject : mDependantProjects ) { |
|
240 |
+ |
zProject.addDependantProjectsDistPaths( pPathsToAddTo ); |
|
241 |
+ |
} |
|
242 |
+ |
pPathsToAddTo.add( getDist() ); |
|
243 |
+ |
} |
|
244 |
+ |
|
|
245 |
+ |
protected boolean GWTcompileIt() { |
|
246 |
+ |
Utils.shell( new ShellArgs() |
|
247 |
+ |
.add( getPathJavaJRE() ) |
|
248 |
+ |
.add( "-Xmx" + getGWTmx() ) |
|
249 |
+ |
.add( "-cp", buildGWTcompileClassPath() ) |
|
250 |
+ |
.add( "com.google.gwt.dev.Compiler" ) |
|
251 |
+ |
.add( getGWTcompileReport() ) |
|
252 |
+ |
.add( "-logLevel", getGWTlogging() ) |
|
253 |
+ |
.add( "-war", getGWTwarPath() ) |
|
254 |
+ |
.add( "-style", getGWTstyle() ) |
|
255 |
+ |
.add( getGWT() ) |
|
256 |
+ |
.toArray() ); |
|
257 |
+ |
return true; |
|
258 |
+ |
} |
|
259 |
+ |
|
|
260 |
+ |
private String buildGWTcompileClassPath() { |
|
261 |
+ |
Paths zGWTclassPath = new Paths(); |
|
262 |
+ |
File zGWTatDir = getGWTatDir(); |
|
263 |
+ |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_DEV ) ); |
|
264 |
+ |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_USER ) ); |
|
265 |
+ |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_VALIDATION ) ); |
|
266 |
+ |
zGWTclassPath.add( FilePath.canonical( zGWTatDir, GWT_VALIDATION_SOURCE ) ); |
|
267 |
+ |
if ( mSources ) { |
|
268 |
+ |
zGWTclassPath.add( FilePath.canonicalize( getJarPathFile() ) ); |
|
269 |
+ |
} |
|
270 |
+ |
zGWTclassPath.add( classpath() ); |
|
271 |
+ |
return zGWTclassPath.toString( File.pathSeparator ); |
|
272 |
+ |
} |
|
273 |
+ |
|
|
274 |
+ |
protected String getPathJavaJRE() { |
|
275 |
+ |
File zJavaHomeDir = assertIsDirectory( JAVA_HOME, new File( assertNotEmpty( JAVA_HOME, System.getenv( JAVA_HOME ) ) ) ); |
|
276 |
+ |
File zJavaDir = new File( zJavaHomeDir, "jre/bin" ); |
|
277 |
+ |
if ( !zJavaDir.isDirectory() ) { |
|
278 |
+ |
if ( !(zJavaDir = new File( zJavaHomeDir, "bin" )).isDirectory() ) { |
|
279 |
+ |
throw new IllegalStateException( "Unable to find JAVA_HOME bin directory under: " + zJavaHomeDir ); |
|
280 |
+ |
} |
|
281 |
+ |
} |
|
282 |
+ |
File zJavaExecutable = new File( zJavaDir, isWindows ? "java.exe" : "java" ); |
|
283 |
+ |
if ( zJavaExecutable.isFile() ) { |
|
284 |
+ |
return getCanonicalFile( zJavaExecutable ).getPath(); |
|
285 |
+ |
} |
|
286 |
+ |
throw new IllegalStateException( "Unable to find JAVA_HOME based executable at: " + zJavaExecutable ); |
|
287 |
+ |
} |
|
288 |
+ |
|
|
289 |
+ |
protected File getGeneratedGWT_nocache_jsFile() { |
|
290 |
+ |
String zGWTxmlRelativeFilePath = getGWT().replace( '.', '/' ) + ".gwt.xml"; // e.g. org.litesoft.sandbox.csapp.CSapp |
|
291 |
+ |
File zFound = getGeneratedGWT_nocache_jsFile( zGWTxmlRelativeFilePath, getSource() ); |
|
292 |
+ |
if ( zFound == null ) { |
|
293 |
+ |
if ( null == (zFound = getGeneratedGWT_nocache_jsFile( zGWTxmlRelativeFilePath, getResources() )) ) { |
|
294 |
+ |
throw new IllegalArgumentException( "Unable to locate GWT module file: " + getGWT() ); |
|
295 |
+ |
} |
|
296 |
+ |
} |
|
297 |
+ |
return zFound; |
|
298 |
+ |
} |
|
299 |
+ |
|
|
300 |
+ |
private File getGeneratedGWT_nocache_jsFile( String pGWTxmlRelativeFilePath, Paths pPaths ) { |
|
301 |
+ |
RootedPaths[] zRootedPaths = pPaths.getRootedPaths(); |
|
302 |
+ |
for ( RootedPaths zPath : zRootedPaths ) { |
|
303 |
+ |
File zFile = new File( zPath.getCanonicalRootDirectory(), pGWTxmlRelativeFilePath ); |
|
304 |
+ |
if ( zFile.isFile() ) { |
|
305 |
+ |
String moduleName = extractModuleNameFrom( getGWT(), fileContents( zFile ) ); |
|
306 |
+ |
return new File( getGWTwarPath(), moduleName + "/" + moduleName + ".nocache.js" ); |
|
307 |
+ |
} |
|
308 |
+ |
} |
|
309 |
+ |
return null; |
|
310 |
+ |
} |
|
311 |
+ |
|
|
312 |
+ |
private String extractModuleNameFrom( String pGWTmoduleReference, String pGWTmoduleFileContents ) { |
|
313 |
+ |
int at = pGWTmoduleFileContents.indexOf( " rename-to" ); |
|
314 |
+ |
if ( at != -1 ) // . . . . . . . . . . . .01234567890 |
|
315 |
+ |
{ |
|
316 |
+ |
int upTo = pGWTmoduleFileContents.indexOf( '>', at += 10 ); |
|
317 |
+ |
if ( upTo != -1 ) { |
|
318 |
+ |
String stuff = pGWTmoduleFileContents.substring( at, upTo ).trim(); |
|
319 |
+ |
if ( stuff.startsWith( "=" ) ) { |
|
320 |
+ |
if ( (stuff = stuff.substring( 1 ).trim()).length() > 2 ) { |
|
321 |
+ |
char c = stuff.charAt( 0 ); |
|
322 |
+ |
if ( (c == '"') || (c == '\'') ) { |
|
323 |
+ |
if ( -1 != (at = stuff.indexOf( c, 1 )) ) { |
|
324 |
+ |
return stuff.substring( 1, at ); |
|
325 |
+ |
} |
|
326 |
+ |
} |
|
327 |
+ |
} |
|
328 |
+ |
} |
|
329 |
+ |
} |
|
330 |
+ |
} |
|
331 |
+ |
String s = "." + pGWTmoduleReference; |
|
332 |
+ |
return s.substring( s.lastIndexOf( '.' ) + 1 ); |
|
333 |
+ |
} |
|
334 |
+ |
|
|
335 |
+ |
protected boolean needToCompileGWT() { |
|
336 |
+ |
File zGeneratedGWT_nocache_jsFile = getGeneratedGWT_nocache_jsFile(); |
|
337 |
+ |
return needToBuild( ((zGeneratedGWT_nocache_jsFile != null) && zGeneratedGWT_nocache_jsFile.isFile()) ? |
|
338 |
+ |
zGeneratedGWT_nocache_jsFile.lastModified() : forceBuildLastModified() ); |
|
339 |
+ |
} |
|
340 |
+ |
|
|
341 |
+ |
public boolean GWTcompile() { |
|
342 |
+ |
String zGWT = getGWT(); |
|
343 |
+ |
if ( zGWT == null ) { |
|
344 |
+ |
return false; |
|
345 |
+ |
} |
|
346 |
+ |
if ( !needToCompileGWT() ) { |
|
347 |
+ |
progress( "GWT Compile: " + this + " NOT Needed!" ); |
|
348 |
+ |
return false; |
|
349 |
+ |
} |
|
350 |
+ |
progress( "GWT Compile: " + this ); |
|
351 |
+ |
return GWTcompileIt(); |
|
352 |
+ |
} |
|
353 |
+ |
|
|
354 |
+ |
/** |
|
355 |
+ |
* Assert that this project is currently a 'Versioned' GWT project, and then rev the version number by 1 |
|
356 |
+ |
*/ |
|
357 |
+ |
public void versionGWT() { |
|
358 |
+ |
File zWarWebXmlFile = new File( mCanonicalProjectDir, "war/WEB-INF/web.xml" ); |
|
359 |
+ |
String zWarWebXml = fileContents( assertIsFile( "web.xml", zWarWebXmlFile ) ); |
|
360 |
+ |
|
|
361 |
+ |
int zCurVersion = extractVersionFromUrlPattern( zWarWebXml ); |
|
362 |
+ |
|
|
363 |
+ |
String zWarResourceRelativePathCurrent = "warResources/v" + zCurVersion; |
|
364 |
+ |
|
|
365 |
+ |
File zIndexHtmlFile = new File( mCanonicalProjectDir, zWarResourceRelativePathCurrent + "/index.html" ); |
|
366 |
+ |
String zIndexHtml = assertVersionedIndexHtml( zIndexHtmlFile, zCurVersion ); |
|
367 |
+ |
|
|
368 |
+ |
List<File> zVersionedGwtXmlFiles = findVersionedGwtXmlFiles( zCurVersion ); |
|
369 |
+ |
|
|
370 |
+ |
int zNewVersion = zCurVersion + 1; |
|
371 |
+ |
|
|
372 |
+ |
String zWarResourceRelativePathNew = "warResources/v" + zNewVersion; |
|
373 |
+ |
if ( new File( mCanonicalProjectDir, zWarResourceRelativePathNew ).exists() ) { |
|
374 |
+ |
throw new IllegalStateException( "Project already contains a 'warResources/v" + zNewVersion + "' directory?" ); |
|
375 |
+ |
} |
|
376 |
+ |
|
|
377 |
+ |
progress( "versionGWT: " + this + " | " + zCurVersion + " -> " + (zCurVersion + 1) ); |
|
378 |
+ |
progress( " " + zWarWebXmlFile.getPath() ); |
|
379 |
+ |
progress( " " + zIndexHtmlFile.getPath() ); |
|
380 |
+ |
for ( File zFile : zVersionedGwtXmlFiles ) { |
|
381 |
+ |
progress( " " + zFile.getPath() ); |
|
382 |
+ |
} |
|
383 |
+ |
progress( " " + zWarResourceRelativePathCurrent + " -> " + zWarResourceRelativePathNew ); |
|
384 |
+ |
|
|
385 |
+ |
new Paths( zWarResourceRelativePathCurrent ).copyTo( zWarResourceRelativePathNew ); |
|
386 |
+ |
|
|
387 |
+ |
updateFileContents( new File( mCanonicalProjectDir, zWarResourceRelativePathNew + "/index.html" ), |
|
388 |
+ |
updateVersionedIndexHtml( zIndexHtml, zCurVersion, zNewVersion ) ); |
|
389 |
+ |
|
|
390 |
+ |
updateFileContents( zWarWebXmlFile, updateVersionedWebXml( zWarWebXml, zCurVersion, zNewVersion ) ); |
|
391 |
+ |
|
|
392 |
+ |
for ( File zFile : zVersionedGwtXmlFiles ) { |
|
393 |
+ |
updateFileContents( zFile, updateVersionedGwtXmlFile( fileContents( zFile ), zCurVersion, zNewVersion ) ); |
|
394 |
+ |
} |
|
395 |
+ |
// Update/Create the Current Version's redirect JavaScript file |
|
396 |
+ |
String zCurPathVersion = "/v" + zCurVersion; |
|
397 |
+ |
String redirectScript = "var loc = window.location.href;\n" + // |
|
398 |
+ |
"var at = loc.indexOf( '" + zCurPathVersion + "' );\n" + // |
|
399 |
+ |
"window.location.href = loc.substring(0, at) + '/v" + zNewVersion + "' + loc.substring(at + " + zCurPathVersion.length() + ");\n"; |
|
400 |
+ |
updateFileContents( new File( mCanonicalProjectDir, zWarResourceRelativePathCurrent + "/v" + zCurVersion + ".nocache.js" ), redirectScript ); |
|
401 |
+ |
|
|
402 |
+ |
// Update the "root" html (if it exists) |
|
403 |
+ |
File zRootHtmlFile = new File( mCanonicalProjectDir, "warResources/index.html" ); |
|
404 |
+ |
if ( zRootHtmlFile.isFile() ) { |
|
405 |
+ |
updateFileContents( zRootHtmlFile, updateRootHTML( fileContents( zRootHtmlFile ), zCurVersion, zNewVersion ) ); |
|
406 |
+ |
} |
|
407 |
+ |
} |
|
408 |
+ |
|
|
409 |
+ |
protected String updateRootHTML( String pFileContents, int pCurVersion, int pNewVersion ) { |
|
410 |
+ |
// <!DOCTYPE html> |
|
411 |
+ |
// <html> |
|
412 |
+ |
// <head> |
|
413 |
+ |
// <meta http-equiv="Refresh" content="1; url=v1/"> |
|
414 |
+ |
// </head> |
|
415 |
+ |
// <body> |
|
416 |
+ |
// <script>window.location.href = 'v1/';</script> |
|
417 |
+ |
// </body> |
|
418 |
+ |
// </html> |
|
419 |
+ |
String zCurPathVersion = "v" + pCurVersion + "/"; |
|
420 |
+ |
String zNewPathVersion = "v" + pNewVersion + "/"; |
|
421 |
+ |
for ( int at; -1 != (at = pFileContents.indexOf( zCurPathVersion )); ) { |
|
422 |
+ |
pFileContents = pFileContents.substring( 0, at ) + zNewPathVersion + pFileContents.substring( at + zCurPathVersion.length() ); |
|
423 |
+ |
} |
|
424 |
+ |
return pFileContents; |
|
425 |
+ |
} |
|
426 |
+ |
|
|
427 |
+ |
protected String updateVersionedGwtXmlFile( String pFileContents, int pCurVersion, int pNewVersion ) { |
|
428 |
+ |
String zCurVersionedModule = VERSIONED_MODULE_PREFIX + pCurVersion + VERSIONED_MODULE_SUFFIX; |
|
429 |
+ |
String zNewVersionedModule = VERSIONED_MODULE_PREFIX + pNewVersion + VERSIONED_MODULE_SUFFIX; |
|
430 |
+ |
int at = pFileContents.indexOf( zCurVersionedModule ); |
|
431 |
+ |
return pFileContents.substring( 0, at ) + zNewVersionedModule + pFileContents.substring( at + zCurVersionedModule.length() ); |
|
432 |
+ |
} |
|
433 |
+ |
|
|
434 |
+ |
protected List<File> findVersionedGwtXmlFiles( int pVersion ) { |
|
435 |
+ |
String zVersionedModule = VERSIONED_MODULE_PREFIX + pVersion + VERSIONED_MODULE_SUFFIX; |
|
436 |
+ |
|
|
437 |
+ |
ArrayList<File> zVersionedFiles = new ArrayList<File>(); |
|
438 |
+ |
|
|
439 |
+ |
String zSourceString = get( SOURCE.getName() ) + "|"; |
|
440 |
+ |
Paths zGwtXml = new Paths( zSourceString.substring( 0, zSourceString.indexOf( '|' ) ), "**.gwt.xml" ); |
|
441 |
+ |
for ( File zFile : zGwtXml.getFiles() ) { |
|
442 |
+ |
if ( fileContents( zFile ).contains( zVersionedModule ) ) { |
|
443 |
+ |
zVersionedFiles.add( zFile ); |
|
444 |
+ |
} |
|
445 |
+ |
} |
|
446 |
+ |
if ( zVersionedFiles.isEmpty() ) { |
|
447 |
+ |
throw new IllegalStateException( |
|
448 |
+ |
"Project does not appear to contain a 'gwt.xml' file with the current version module definition of: " + zVersionedModule ); |
|
449 |
+ |
} |
|
450 |
+ |
return zVersionedFiles; |
|
451 |
+ |
} |
|
452 |
+ |
|
|
453 |
+ |
protected String updateVersionedIndexHtml( String pFileContents, int pCurVersion, int pNewVersion ) { |
|
454 |
+ |
String zCurVersionedScript = VERSIONED_SCRIPT_PREFIX + pCurVersion + VERSIONED_SCRIPT_SUFFIX; |
|
455 |
+ |
String zNewVersionedScript = VERSIONED_SCRIPT_PREFIX + pNewVersion + VERSIONED_SCRIPT_SUFFIX; |
|
456 |
+ |
int at = pFileContents.indexOf( zCurVersionedScript ); |
|
457 |
+ |
return pFileContents.substring( 0, at ) + zNewVersionedScript + pFileContents.substring( at + zCurVersionedScript.length() ); |
|
458 |
+ |
} |
|
459 |
+ |
|
|
460 |
+ |
protected String assertVersionedIndexHtml( File pIndexHtmlFile, int pVersion ) { |
|
461 |
+ |
String zVersionedScript = VERSIONED_SCRIPT_PREFIX + pVersion + VERSIONED_SCRIPT_SUFFIX; |
|
462 |
+ |
|
|
463 |
+ |
String zContents = fileContents( assertIsFile( "Versioned index.html", pIndexHtmlFile ) ); |
|
464 |
+ |
if ( !zContents.contains( zVersionedScript ) ) { |
|
465 |
+ |
throw new IllegalStateException( |
|
466 |
+ |
"Project's current versioned index.html file (" + pIndexHtmlFile.getPath() + ") does not contain a 'versioned' script element of: " + |
|
467 |
+ |
zVersionedScript ); |
|
468 |
+ |
} |
|
469 |
+ |
return zContents; |
|
470 |
+ |
} |
|
471 |
+ |
|
|
472 |
+ |
protected String updateVersionedWebXml( String pFileContents, int pCurVersion, int pNewVersion ) { |
|
473 |
+ |
String zCurVersionedUrlPattern = VERSIONED_URL_PATTERN_PREFIX + pCurVersion + "/"; |
|
474 |
+ |
String zNewVersionedUrlPattern = VERSIONED_URL_PATTERN_PREFIX + pNewVersion + "/"; |
|
475 |
+ |
for ( int at; -1 != (at = pFileContents.indexOf( zCurVersionedUrlPattern )); ) { |
|
476 |
+ |
pFileContents = pFileContents.substring( 0, at ) + zNewVersionedUrlPattern + pFileContents.substring( at + zCurVersionedUrlPattern.length() ); |
|
477 |
+ |
} |
|
478 |
+ |
return pFileContents; |
|
479 |
+ |
} |
|
480 |
+ |
|
|
481 |
+ |
protected int extractVersionFromUrlPattern( String pWarWebXml ) { |
|
482 |
+ |
for ( int at, from = 0; -1 != (at = pWarWebXml.indexOf( VERSIONED_URL_PATTERN_PREFIX, from )); from = at + 1 ) { |
|
483 |
+ |
int slashAt = pWarWebXml.indexOf( '/', at += VERSIONED_URL_PATTERN_PREFIX.length() ); |
|
484 |
+ |
if ( slashAt > 0 ) { |
|
485 |
+ |
try { |
|
486 |
+ |
return Integer.parseInt( pWarWebXml.substring( at, slashAt ) ); |
|
487 |
+ |
} |
|
488 |
+ |
catch ( NumberFormatException acceptable ) { |
|
489 |
+ |
// path starts w/ a 'v' but is not of pattern "v####" |
|
490 |
+ |
} |
|
491 |
+ |
} |
|
492 |
+ |
} |
|
493 |
+ |
throw new IllegalStateException( "Project's war/WEB-INF/web.xml does not appear to contain a 'versioned' <url-pattern>." ); |
|
494 |
+ |
} |
|
495 |
+ |
|
|
496 |
+ |
/** |
|
497 |
+ |
* Executes the buildDependencies, clean, compile, jar, [GWTcompile], and then "packageIt" utility methods. |
|
498 |
+ |
*/ |
|
499 |
+ |
public synchronized boolean build() { |
|
500 |
+ |
if ( mBuilt ) { |
|
501 |
+ |
return false; |
|
502 |
+ |
} |
|
503 |
+ |
mBuilt = true; |
|
504 |
+ |
mSources = !getSource().isEmpty(); |
|
505 |
+ |
boolean zAnythingBuilt = false; |
|
506 |
+ |
boolean zBuildIt; |
|
507 |
+ |
try { |
|
508 |
+ |
zBuildIt = buildDependencies() || needToBuild(); |
|
509 |
+ |
} |
|
510 |
+ |
catch ( RuntimeException e ) { |
|
511 |
+ |
progress( "Build: " + this ); |
|
512 |
+ |
throw e; |
|
513 |
+ |
} |
|
514 |
+ |
if ( !zBuildIt ) { |
|
515 |
+ |
progress( "Build: " + this + " NOT Needed!" ); |
|
516 |
+ |
} else { |
|
517 |
+ |
progress( "Build: " + this ); |
|
518 |
+ |
clean(); |
|
519 |
+ |
if ( mSources ) { |
|
520 |
+ |
compile(); |
|
521 |
+ |
jar(); |
|
522 |
+ |
zAnythingBuilt = true; |
|
523 |
+ |
} |
|
524 |
+ |
} |
|
525 |
+ |
zAnythingBuilt |= GWTcompile(); |
|
526 |
+ |
zAnythingBuilt |= packageIt(); |
|
527 |
+ |
return zAnythingBuilt; |
|
528 |
+ |
} |
|
529 |
+ |
|
|
530 |
+ |
protected boolean needToBuild() { |
|
531 |
+ |
return needToBuild( determineOutputLastModified() ); |
|
532 |
+ |
} |
|
533 |
+ |
|
|
534 |
+ |
protected boolean needToBuild( long pOutputLastModified ) { |
|
535 |
+ |
return (mProjectFileLastModified > pOutputLastModified) || // |
|
536 |
+ |
checkNewer( pOutputLastModified, "ClassPath", compileClasspath() ) || // |
|
537 |
+ |
checkNewer( pOutputLastModified, "Source", getSource() ) || // |
|
538 |
+ |
checkNewer( pOutputLastModified, "Resources", getResources() ) || // |
|
539 |
+ |
checkNewer( pOutputLastModified, "Dist", getDist() ); |
|
540 |
+ |
} |
|
541 |
+ |
|
|
542 |
+ |
protected boolean checkNewer( long pOutputLastModified, String pWhat, Paths pPaths ) { |
|
543 |
+ |
Long zLastModified = pPaths.getGreatestLastModified(); |
|
544 |
+ |
if ( (zLastModified != null) && (zLastModified > pOutputLastModified) ) { |
|
545 |
+ |
System.out.println( this + ": " + pWhat + " - " + new NewerBy( pOutputLastModified, zLastModified ) ); |
|
546 |
+ |
return true; |
|
547 |
+ |
} |
|
548 |
+ |
return false; |
|
549 |
+ |
} |
|
550 |
+ |
|
|
551 |
+ |
protected long forceBuildLastModified() { |
|
552 |
+ |
return (mProjectFileLastModified - 1); |
|
553 |
+ |
} |
|
554 |
+ |
|
|
555 |
+ |
protected long determineOutputLastModified() { |
|
556 |
+ |
if ( mSources ) { |
|
557 |
+ |
File zJarFile = getJarPathFile(); |
|
558 |
+ |
if ( zJarFile.isFile() ) { |
|
559 |
+ |
return zJarFile.lastModified(); |
|
560 |
+ |
} |
|
561 |
+ |
} else { |
|
562 |
+ |
String zPhoneGapDir = getPhoneGapDirPath(); |
|
563 |
+ |
if ( zPhoneGapDir != null ) { |
|
564 |
+ |
File zPhoneGapDirFile = new File( zPhoneGapDir ); |
|
565 |
+ |
if ( zPhoneGapDirFile.isDirectory() ) { |
|
566 |
+ |
return zPhoneGapDirFile.lastModified(); |
|
567 |
+ |
} |
|
568 |
+ |
} |
|
569 |
+ |
} |
|
570 |
+ |
return forceBuildLastModified(); |
|
571 |
+ |
} |
|
572 |
+ |
|
|
573 |
+ |
/** |
|
574 |
+ |
* Deletes the "target" directory and all files and directories under it. |
|
575 |
+ |
*/ |
|
576 |
+ |
public void clean() { |
|
577 |
+ |
progress( "Clean: " + this ); |
|
578 |
+ |
packageClean(); |
|
579 |
+ |
delete( getGWTwarPath() ); |
|
580 |
+ |
delete( getJarPath() ); |
|
581 |
+ |
delete( getTargetPath() ); |
|
582 |
+ |
} |
|
583 |
+ |
|
|
584 |
+ |
/** |
|
585 |
+ |
* Collects the source files using the "source" property and compiles them into a "classes" directory under the target |
|
586 |
+ |
* directory. It uses "classpath" and "dependencies" to find the libraries required to compile the source. |
|
587 |
+ |
* <p/> |
|
588 |
+ |
* Note: Each dependency project is not built automatically. Each needs to be built before the dependent project. |
|
589 |
+ |
* |
|
590 |
+ |
* @return The path to the "classes" directory or null if there was no sources to compile |
|
591 |
+ |
*/ |
|
592 |
+ |
public String compile() { |
|
593 |
+ |
Paths source = getSource(); |
|
594 |
+ |
if ( source.isEmpty() ) { |
|
595 |
+ |
return null; |
|
596 |
+ |
} |
|
597 |
+ |
Paths classpath = compileClasspath(); |
|
598 |
+ |
|
|
599 |
+ |
String classesDir = mkdir( path( "$target$/classes/" ) ); |
|
600 |
+ |
|
|
601 |
+ |
String zMessage = "Compile: " + this; |
|
602 |
+ |
if ( LOGGER.debug.isEnabled() ) { |
|
603 |
+ |
zMessage += " | " + source.count() + " source files"; |
|
604 |
+ |
if ( !classpath.isEmpty() ) { |
|
605 |
+ |
zMessage += "\n Classpath: " + classpath; |
|
606 |
+ |
} |
|
607 |
+ |
} |
|
608 |
+ |
progress( zMessage ); |
|
609 |
+ |
|
|
610 |
+ |
List<String> zCompileArgs = createCompileJavaArgs( classpath, source, classesDir ); |
|
611 |
+ |
|
|
612 |
+ |
compileJava( classpath, source, zCompileArgs ); |
|
613 |
+ |
|
|
614 |
+ |
return classesDir; |
|
615 |
+ |
} |
|
616 |
+ |
|
|
617 |
+ |
protected List<String> createCompileJavaArgs( Paths pClasspath, Paths pSource, String pClassesDir ) { |
|
618 |
+ |
List<String> args = new ArrayList<String>(); |
|
619 |
+ |
if ( LOGGER.trace.isEnabled() ) { |
|
620 |
+ |
args.add( "-verbose" ); |
|
621 |
+ |
} |
|
622 |
+ |
args.add( "-d" ); |
|
623 |
+ |
args.add( pClassesDir ); |
|
624 |
+ |
args.add( "-g:source,lines" ); |
|
625 |
+ |
args.add( "-source" ); |
|
626 |
+ |
args.add( getSourceJavaVersion() ); |
|
627 |
+ |
args.addAll( pSource.getFullPaths() ); |
|
628 |
+ |
if ( !pClasspath.isEmpty() ) { |
|
629 |
+ |
args.add( "-classpath" ); |
|
630 |
+ |
args.add( pClasspath.toString( File.pathSeparator ) ); |
|
631 |
+ |
} |
|
632 |
+ |
return args; |
|
633 |
+ |
} |
|
634 |
+ |
|
|
635 |
+ |
protected void compileJava( Paths pClasspath, Paths pSource, List<String> pCompileArgs ) { |
|
636 |
+ |
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
|
637 |
+ |
|
|
638 |
+ |
if ( compiler == null ) { |
|
639 |
+ |
throw new RuntimeException( "No compiler available. Ensure you are running from a " + getTargetJavaVersion() + |
|
640 |
+ |
"+ JDK, and not a JRE *and* that your class path includes tools.jar." ); |
|
641 |
+ |
} |
|
642 |
+ |
int zError = compiler.run( getCompile_in(), getCompile_out(), getCompile_err(), pCompileArgs.toArray( new String[pCompileArgs.size()] ) ); |
|
643 |
+ |
if ( zError != 0 ) { |
|
644 |
+ |
String zMessage = "Error (" + zError + ") during compilation of project: " + this + |
|
645 |
+ |
"\nSource: " + pSource.count() + " files\nCompilerArgs: " + pCompileArgs; |
|
646 |
+ |
if ( LOGGER.debug.isEnabled() ) { |
|
647 |
+ |
zMessage += "\nClasspath: " + pClasspath + "\nSource: " + pSource.toString( " " ); |
|
648 |
+ |
} |
|
649 |
+ |
throw new RuntimeException( zMessage ); |
|
650 |
+ |
} |
|
651 |
+ |
try { |
|
652 |
+ |
Thread.sleep( 100 ); |
|
653 |
+ |
} |
|
654 |
+ |
catch ( InterruptedException ex ) { |
|
655 |
+ |
// Whatever |
|
656 |
+ |
} |
|
657 |
+ |
} |
|
658 |
+ |
|
|
659 |
+ |
protected InputStream getCompile_in() { |
|
660 |
+ |
return null; |
|
661 |
+ |
} |
|
662 |
+ |
|
|
663 |
+ |
protected OutputStream getCompile_out() { |
|
664 |
+ |
return null; |
|
665 |
+ |
} |
|
666 |
+ |
|
|
667 |
+ |
protected OutputStream getCompile_err() { |
|
668 |
+ |
return new OutputStream() { |
|
669 |
+ |
private StringBuilder mBuffer = new StringBuilder(); |
|
670 |
+ |
private boolean mLastWasCRtreatedAsLF = false; |
|
671 |
+ |
|
|
672 |
+ |
private void dumpLine( int pByte ) { |
|
673 |
+ |
if ( pByte == 13 ) { |
|
674 |
+ |
mLastWasCRtreatedAsLF = true; |
|
675 |
+ |
pByte = 10; |
|
676 |
+ |
} else { |
|
677 |
+ |
boolean zLastWasCRtreatedAsLF = mLastWasCRtreatedAsLF; |
|
678 |
+ |
mLastWasCRtreatedAsLF = false; |
|
679 |
+ |
if ( (pByte == 10) && zLastWasCRtreatedAsLF ) { |
|
680 |
+ |
return; |
|
681 |
+ |
} |
|
682 |
+ |
} |
|
683 |
+ |
mBuffer.append( (char) pByte ); // Assuming Ascii! |
|
684 |
+ |
String line = mBuffer.toString(); |
|
685 |
+ |
mBuffer = new StringBuilder(); |
|
686 |
+ |
if ( !line.startsWith( "Note: " ) ) { |
|
687 |
+ |
System.err.print( line ); |
|
688 |
+ |
} |
|
689 |
+ |
} |
|
690 |
+ |
|
|
691 |
+ |
@Override |
|
692 |
+ |
public void write( int pByte ) // Not a Unicode character, just a BYTE! --- Asumming Ascii --- |
|
693 |
+ |
throws IOException { |
|
694 |
+ |
if ( (10 <= pByte) && (pByte <= 13) ) // New Line Indicator |
|
695 |
+ |
{ // LF: Line Feed, U+000A |
|
696 |
+ |
dumpLine( pByte ); // VT: Vertical Tab, U+000B |
|
697 |
+ |
return; // FF: Form Feed, U+000C |
|
698 |
+ |
} // CR: Carriage Return, U+000D |
|
699 |
+ |
mBuffer.append( (char) pByte ); // Assuming Ascii! |
|
700 |
+ |
} |
|
701 |
+ |
}; |
|
702 |
+ |
} |
|
703 |
+ |
|
|
704 |
+ |
/** |
|
705 |
+ |
* Collects the class files from the "classes" directory and all the resource files using the "resources" property and encodes |
|
706 |
+ |
* them into a JAR file. |
|
707 |
+ |
* <p/> |
|
708 |
+ |
* If the resources don't contain a META-INF/MANIFEST.MF file, one is generated. If the project has a main property, the |
|
709 |
+ |
* generated manifest will include "Main-Class" and "Class-Path" entries to allow the main class to be run with "java -jar". |
|
710 |
+ |
* |
|
711 |
+ |
* @return The path to the created JAR file or null if No JAR created. |
|
712 |
+ |
*/ |
|
713 |
+ |
public String jar() { |
|
714 |
+ |
String zJarPath = getJarPath(); |
|
715 |
+ |
|
|
716 |
+ |
Paths zClasses = new Paths( path( "$target$/classes/" ), "**.class" ); |
|
717 |
+ |
Paths zResources = getResources(); |
|
718 |
+ |
if ( zClasses.isEmpty() && zResources.isEmpty() ) { |
|
719 |
+ |
delete( zJarPath ); |
|
720 |
+ |
return null; |
|
721 |
+ |
} |
|
722 |
+ |
progress( "JAR: " + this + " -> " + zJarPath ); |
|
723 |
+ |
|
|
724 |
+ |
String jarDir = mkdir( path( "$target$/jar/" ) ); |
|
725 |
+ |
|
|
726 |
+ |
zClasses.copyTo( jarDir ); |
|
727 |
+ |
zResources.copyTo( jarDir ); |
|
728 |
+ |
|
|
729 |
+ |
File manifestFile = new File( jarDir, "META-INF/MANIFEST.MF" ); |
|
730 |
+ |
if ( !manifestFile.exists() ) { |
|
731 |
+ |
createDefaultManifestFile( zJarPath, manifestFile ); |
|
732 |
+ |
} |
|
733 |
+ |
|
|
734 |
+ |
return jar( zJarPath, new Paths( jarDir ) ); |
|
735 |
+ |
} |
|
736 |
+ |
|
|
737 |
+ |
protected void createDefaultManifestFile( String pJarFile, File pManifestFile ) { |
|
738 |
+ |
LOGGER.debug.log( "Generating JAR manifest: ", pManifestFile ); |
|
739 |
+ |
mkdir( pManifestFile.getParent() ); |
|
740 |
+ |
Manifest manifest = new Manifest(); |
|
741 |
+ |
manifest.getMainAttributes().putValue( Attributes.Name.MANIFEST_VERSION.toString(), "1.0" ); |
|
742 |
+ |
if ( hasMain() ) { |
|
743 |
+ |
LOGGER.debug.log( "Main class: ", getMain() ); |
|
744 |
+ |
manifest.getMainAttributes().putValue( Attributes.Name.MAIN_CLASS.toString(), getMain() ); |
|
745 |
+ |
StringBuilder buffer = new StringBuilder( 512 ); |
|
746 |
+ |
buffer.append( Utils.fileName( pJarFile ) ); |
|
747 |
+ |
buffer.append( " ." ); |
|
748 |
+ |
Paths classpath = classpath(); |
|
749 |
+ |
for ( String name : classpath.getRelativePaths( pJarFile ) ) { |
|
750 |
+ |
buffer.append( ' ' ); |
|
751 |
+ |
buffer.append( name ); |
|
752 |
+ |
} |
|
753 |
+ |
manifest.getMainAttributes().putValue( Attributes.Name.CLASS_PATH.toString(), buffer.toString() ); |
|
754 |
+ |
} |
|
755 |
+ |
OutputStream output = createFileOutputStream( pManifestFile ); |
|
756 |
+ |
try { |
|
757 |
+ |
manifest.write( output ); |
|
758 |
+ |
Closeable zCloseable = output; |
|
759 |
+ |
output = null; |
|
760 |
+ |
close( zCloseable ); |
|
761 |
+ |
} |
|
762 |
+ |
catch ( IOException e ) { |
|
763 |
+ |
throw new WrappedIOException( e ); |
|
764 |
+ |
} |
|
765 |
+ |
finally { |
|
766 |
+ |
dispose( output ); |
|
767 |
+ |
} |
|
768 |
+ |
} |
|
769 |
+ |
|
|
770 |
+ |
/** |
|
771 |
+ |
* Encodes the specified paths into a JAR file. |
|
772 |
+ |
* |
|
773 |
+ |
* @return The path to the JAR file. |
|
774 |
+ |
*/ |
|
775 |
+ |
public String jar( String jarFile, Paths paths ) { |
|
776 |
+ |
return innerJar( "JAR", jarFile, paths ); |
|
777 |
+ |
} |
|
778 |
+ |
|
|
779 |
+ |
/** |
|
780 |
+ |
* Encodes the specified paths into a JAR/WAR file. |
|
781 |
+ |
* |
|
782 |
+ |
* @return The path to the JAR/WAR file. |
|
783 |
+ |
*/ |
|
784 |
+ |
protected String innerJar( String pType, String jarFile, Paths paths ) { |
|
785 |
+ |
Util.assertNotNull( "jarFile", jarFile ); |
|
786 |
+ |
Util.assertNotNull( "paths", paths ); |
|
787 |
+ |
|
|
788 |
+ |
progress( "Creating " + pType + " (" + paths.count() + " entries): " + jarFile ); |
|
789 |
+ |
|
|
790 |
+ |
int zZipped = paths.zip( jarFile, new ZipFactory() { |
|
791 |
+ |
@Override |
|
792 |
+ |
public ZipOutputStream createZOS( String pFilePath, List<FilePath> pPaths ) { |
|
793 |
+ |
putManifestFirst( pPaths ); |
|
794 |
+ |
try { |
|
795 |
+ |
return new JarOutputStream( FileUtil.createBufferedFileOutputStream( pFilePath ) ); |
|
796 |
+ |
} |
|
797 |
+ |
catch ( IOException e ) { |
|
798 |
+ |
throw new WrappedIOException( e ); |
|
799 |
+ |
} |
|
800 |
+ |
} |
|
801 |
+ |
|
|
802 |
+ |
@Override |
|
803 |
+ |
public ZipEntry createZE( String pRelativePath ) { |
|
804 |
+ |
return new JarEntry( pRelativePath ); |
|
805 |
+ |
} |
|
806 |
+ |
|
|
807 |
+ |
private void putManifestFirst( List<FilePath> pPaths ) { |
|
808 |
+ |
int at = findManifest( pPaths ); |
|
809 |
+ |
if ( at > 0 ) { |
|
810 |
+ |
FilePath zManifest = pPaths.remove( at ); |
|
811 |
+ |
pPaths.add( 0, zManifest ); |
|
812 |
+ |
} |
|
813 |
+ |
} |
|
814 |
+ |
|
|
815 |
+ |
private int findManifest( List<FilePath> pPaths ) { |
|
816 |
+ |
for ( int i = 0; i < pPaths.size(); i++ ) { |
|
817 |
+ |
if ( META_INF_MANIFEST_MF.equals( pPaths.get( i ).getFileSubPath() ) ) { |
|
818 |
+ |
return i; |
|
819 |
+ |
} |
|
820 |
+ |
} |
|
821 |
+ |
return -1; |
|
822 |
+ |
} |
|
823 |
+ |
} ); |
|
824 |
+ |
return zZipped == 0 ? null : jarFile; |
|
825 |
+ |
} |
|
826 |
+ |
|
|
827 |
+ |
/** |
|
828 |
+ |
* Decodes the specified ZIP file. |
|
829 |
+ |
* |
|
830 |
+ |
* @return The path to the output directory. |
|
831 |
+ |
*/ |
|
832 |
+ |
protected void quiteUnzip( File zipFile, File outputDir ) { |
|
833 |
+ |
ZipInputStream input = new ZipInputStream( createFileInputStream( zipFile ) ); |
|
834 |
+ |
try { |
|
835 |
+ |
for ( ZipEntry entry; null != (entry = input.getNextEntry()); ) { |
|
836 |
+ |
File file = new File( outputDir, entry.getName() ); |
|
837 |
+ |
if ( entry.isDirectory() ) { |
|
838 |
+ |
mkdir( file.getPath() ); |
|
839 |
+ |
continue; |
|
840 |
+ |
} |
|
841 |
+ |
writeStream( input, createFileOutputStream( file ) ); |
|
842 |
+ |
} |
|
843 |
+ |
} |
|
844 |
+ |
catch ( IOException e ) { |
|
845 |
+ |
throw new WrappedIOException( e ); |
|
846 |
+ |
} |
|
847 |
+ |
finally { |
|
848 |
+ |
dispose( input ); |
|
849 |
+ |
} |
|
850 |
+ |
} |
|
851 |
+ |
|
|
852 |
+ |
/** |
|
853 |
+ |
* Decodes the specified ZIP file. |
|
854 |
+ |
*/ |
|
855 |
+ |
public void unzip( File zipFile, File outputDir ) { |
|
856 |
+ |
Util.assertNotNull( "zipFile", zipFile ); |
|
857 |
+ |
Util.assertNotNull( "outputDir", outputDir ); |
|
858 |
+ |
progress( "ZIP decoding: " + zipFile.getPath() + " -> " + outputDir.getPath() ); |
|
859 |
+ |
quiteUnzip( zipFile, outputDir ); |
|
860 |
+ |
} |
|
861 |
+ |
|
|
862 |
+ |
/** |
|
863 |
+ |
* Decodes the specified ZIP file. |
|
864 |
+ |
* |
|
865 |
+ |
* @return The path to the output directory. |
|
866 |
+ |
*/ |
|
867 |
+ |
public String unzip( String zipFile, String outputDir ) { |
|
868 |
+ |
zipFile = assertNotEmpty( "zipFile", zipFile ); |
|
869 |
+ |
outputDir = assertNotEmpty( "outputDir", outputDir ); |
|
870 |
+ |
progress( "ZIP decoding: " + zipFile + " -> " + outputDir ); |
|
871 |
+ |
quiteUnzip( new File( zipFile ), new File( outputDir ) ); |
|
872 |
+ |
return outputDir; |
|
873 |
+ |
} |
|
874 |
+ |
|
|
875 |
+ |
/** |
|
876 |
+ |
* Computes the classpath for the specified project and all its dependency projects, recursively. |
|
877 |
+ |
*/ |
|
878 |
+ |
protected Paths compileClasspath() { |
|
879 |
+ |
Paths classpath = getCompileClasspath(); |
|
880 |
+ |
classpath.add( getClasspath() ); |
|
881 |
+ |
for ( Project zProject : mDependantProjects ) { |
|
882 |
+ |
zProject.addDependantProjectsCompileClassPaths( classpath ); |
|
883 |
+ |
} |
|
884 |
+ |
return classpath; |
|
885 |
+ |
} |
|
886 |
+ |
|
|
887 |
+ |
/** |
|
888 |
+ |
* Computes the classpath for all the dependencies of the specified project, recursively. |
|
889 |
+ |
*/ |
|
890 |
+ |
protected void addDependantProjectsCompileClassPaths( Paths pPathsToAddTo ) { |
|
891 |
+ |
addDependentProjectJar( pPathsToAddTo ); |
|
892 |
+ |
pPathsToAddTo.add( compileClasspath() ); |
|
893 |
+ |
} |
|
894 |
+ |
|
|
895 |
+ |
/** |
|
896 |
+ |
* Computes the classpath for the specified project and all its dependency projects, recursively. |
|
897 |
+ |
*/ |
|
898 |
+ |
protected Paths classpath() { |
|
899 |
+ |
Paths classpath = getClasspath(); |
|
900 |
+ |
for ( Project zProject : mDependantProjects ) { |
|
901 |
+ |
zProject.addDependantProjectsClassPaths( classpath ); |
|
902 |
+ |
} |
|
903 |
+ |
return classpath; |
|
904 |
+ |
} |
|
905 |
+ |
|
|
906 |
+ |
/** |
|
907 |
+ |
* Computes the classpath for all the dependencies of the specified project, recursively. |
|
908 |
+ |
*/ |
|
909 |
+ |
protected void addDependantProjectsClassPaths( Paths pPathsToAddTo ) { |
|
910 |
+ |
addDependentProjectJar( pPathsToAddTo ); |
|
911 |
+ |
pPathsToAddTo.add( classpath() ); |
|
912 |
+ |
} |
|
913 |
+ |
|
|
914 |
+ |
protected void addDependentProjectJar( Paths pPathsToAddTo ) { |
|
915 |
+ |
if ( mSources ) { |
|
916 |
+ |
File zJarFile = getJarPathFile(); |
|
917 |
+ |
if ( !zJarFile.isFile() ) { |
|
918 |
+ |
throw new RuntimeException( "Dependency (" + this + ") Jar not found, not built?" ); |
|
919 |
+ |
} |
|
920 |
+ |
pPathsToAddTo.add( new FilePath( zJarFile.getParentFile(), zJarFile.getName() ) ); |
|
921 |
+ |
} |
|
922 |
+ |
} |
|
923 |
+ |
|
|
924 |
+ |
/** |
|
925 |
+ |
* Calls {@link #build(Project)} for each dependency project in the specified project. |
|
926 |
+ |
*/ |
|
927 |
+ |
public boolean buildDependencies() { |
|
928 |
+ |
boolean anyBuilt = false; |
|
929 |
+ |
for ( Project zProject : mDependantProjects ) { |
|
930 |
+ |
anyBuilt |= zProject.build(); |
|
931 |
+ |
} |
|
932 |
+ |
return anyBuilt; |
|
933 |
+ |
} |
|
934 |
+ |
|
|
935 |
+ |
public void set( Object key, Object object ) { |
|
936 |
+ |
mManager.put( validateSetableKey( key ), object ); |
|
937 |
+ |
} |
|
938 |
+ |
|
|
939 |
+ |
public void remove( Object key ) { |
|
940 |
+ |
set( key, null ); |
|
941 |
+ |
} |
|
942 |
+ |
|
|
943 |
+ |
private Object validateSetableKey( Object pKey ) { |
|
944 |
+ |
if ( pKey instanceof String ) { |
|
945 |
+ |
String zStrKey = noEmpty( pKey.toString().toLowerCase() ); |
|
946 |
+ |
if ( Parameter.reservedNames().contains( zStrKey ) ) { |
|
947 |
+ |
throw new IllegalArgumentException( zStrKey + " not updatable!" ); |
|
948 |
+ |
} |
|
949 |
+ |
pKey = zStrKey; |
|
950 |
+ |
} |
|
951 |
+ |
Util.assertNotNull( "key", pKey ); |
|
952 |
+ |
return pKey; |
|
953 |
+ |
} |
|
954 |
+ |
|
|
955 |
+ |
public synchronized void initialize( ProjectFactory pProjectFactory ) { |
|
956 |
+ |
List<String> zDependencies = getDependencies(); |
|
957 |
+ |
if ( zDependencies != null ) { |
|
958 |
+ |
for ( String zDependency : zDependencies ) { |
|
959 |
+ |
mDependantProjects.add( pProjectFactory.project( mCanonicalProjectDir, zDependency ) ); |
|
960 |
+ |
} |
|
961 |
+ |
} |
|
962 |
+ |
|
|
963 |
+ |
// Project defaults = new Project(); |
|
964 |
+ |
// |
|
965 |
+ |
// File file = new File( canonical( pPath ) ); |
|
966 |
+ |
// if ( file.isDirectory() ) |
|
967 |
+ |
// { |
|
968 |
+ |
// String name = file.getName(); |
|
969 |
+ |
// defaults.set( "name", name ); |
|
970 |
+ |
// defaults.set( "target", file.getParent() + "/target/" + name + "/" ); |
|
971 |
+ |
// } |
|
972 |
+ |
// else |
|
973 |
+ |
// { |
|
974 |
+ |
// String name = file.getParentFile().getName(); |
|
975 |
+ |
// defaults.set( "name", name ); |
|
976 |
+ |
// defaults.set( "target", file.getParentFile().getParent() + "/target/" + name + "/" ); |
|
977 |
+ |
// } |
|
978 |
+ |
// defaults.set( "classpath", "lib|**/*.jar" ); |
|
979 |
+ |
// defaults.set( "dist", "dist" ); |
|
980 |
+ |
// |
|
981 |
+ |
// List<String> source = new ArrayList<String>(); |
|
982 |
+ |
// source.add( "src|**/*.java" ); |
|
983 |
+ |
// source.add( "src/main/java|**/*.java" ); |
|
984 |
+ |
// defaults.set( "source", source ); |
|
985 |
+ |
// |
|
986 |
+ |
// List<String> resources = new ArrayList<String>(); |
|
987 |
+ |
// resources.add( "resources" ); |
|
988 |
+ |
// resources.add( "src/main/resources" ); |
|
989 |
+ |
// defaults.set( "resources", resources ); |
|
990 |
+ |
// |
|
991 |
+ |
// Project project = project( pPath, defaults ); |
|
992 |
+ |
// |
|
993 |
+ |
// // Remove dependency if a JAR of the same name is on the classpath. |
|
994 |
+ |
// Paths classpath = project.getPaths( "classpath" ); |
|
995 |
+ |
// classpath.add( dependencyClasspaths( project, classpath, false, false ) ); |
|
996 |
+ |
// for ( String dependency : project.getDependencies() ) |
|
997 |
+ |
// { |
|
998 |
+ |
// String dependencyName = project( project.path( dependency ) ).getName(); |
|
999 |
+ |
// for ( String classpathFile : classpath ) |
|
1000 |
+ |
// { |
|
1001 |
+ |
// String name = fileWithoutExtension( classpathFile ); |
|
1002 |
+ |
// int dashIndex = name.lastIndexOf( '-' ); |
|
1003 |
+ |
// if ( dashIndex != -1 ) |
|
1004 |
+ |
// { |
|
1005 |
+ |
// name = name.substring( 0, dashIndex ); |
|
1006 |
+ |
// } |
|
1007 |
+ |
// if ( name.equals( dependencyName ) ) |
|
1008 |
+ |
// { |
|
1009 |
+ |
// if ( DEBUG ) |
|
1010 |
+ |
// { |
|
1011 |
+ |
// debug( "Ignoring " + project + " dependency: " + dependencyName + " (already on classpath: " + classpathFile + ")" ); |
|
1012 |
+ |
// } |
|
1013 |
+ |
// project.remove( "dependencies", dependency ); |
|
1014 |
+ |
// break; |
|
1015 |
+ |
// } |
|
1016 |
+ |
// } |
|
1017 |
+ |
// } |
|
1018 |
+ |
// |
|
1019 |
+ |
// if ( TRACE ) |
|
1020 |
+ |
// { |
|
1021 |
+ |
// trace( "scar", "Project: " + project + "\n" + project ); |
|
1022 |
+ |
// } |
|
1023 |
+ |
// |
|
1024 |
+ |
// return project; |
|
1025 |
+ |
} |
|
1026 |
+ |
|
|
1027 |
+ |
protected boolean mBuilt = false; |
|
1028 |
+ |
protected boolean mSources = false; |
|
1029 |
+ |
protected List<Project> mDependantProjects = new ArrayList<Project>(); |
|
1030 |
+ |
} |