1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
package org.codehaus.mojo.nbm; |
18 | |
|
19 | |
import com.google.common.collect.Sets; |
20 | |
import java.io.*; |
21 | |
import java.net.URL; |
22 | |
import java.util.ArrayList; |
23 | |
import java.util.Arrays; |
24 | |
import java.util.Collection; |
25 | |
import java.util.Collections; |
26 | |
import java.util.Date; |
27 | |
import java.util.Enumeration; |
28 | |
import java.util.HashMap; |
29 | |
import java.util.HashSet; |
30 | |
import java.util.Iterator; |
31 | |
import java.util.List; |
32 | |
import java.util.Map; |
33 | |
import java.util.Set; |
34 | |
import java.util.jar.JarEntry; |
35 | |
import java.util.jar.JarFile; |
36 | |
import java.util.jar.JarOutputStream; |
37 | |
import java.util.jar.Pack200; |
38 | |
import java.util.regex.Matcher; |
39 | |
import java.util.regex.Pattern; |
40 | |
import java.util.zip.CRC32; |
41 | |
import java.util.zip.GZIPInputStream; |
42 | |
import java.util.zip.ZipEntry; |
43 | |
import java.util.zip.ZipFile; |
44 | |
import org.apache.maven.artifact.Artifact; |
45 | |
import org.apache.maven.artifact.factory.ArtifactFactory; |
46 | |
import org.apache.maven.artifact.repository.ArtifactRepository; |
47 | |
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException; |
48 | |
import org.apache.maven.artifact.resolver.ArtifactNotFoundException; |
49 | |
import org.apache.maven.artifact.resolver.ArtifactResolutionException; |
50 | |
import org.apache.maven.artifact.resolver.ArtifactResolver; |
51 | |
import org.apache.maven.plugin.MojoExecutionException; |
52 | |
import org.apache.maven.plugin.MojoFailureException; |
53 | |
import org.apache.maven.plugin.logging.Log; |
54 | |
import org.apache.maven.plugins.annotations.Component; |
55 | |
import org.apache.maven.plugins.annotations.LifecyclePhase; |
56 | |
import org.apache.maven.plugins.annotations.Mojo; |
57 | |
import org.apache.maven.plugins.annotations.Parameter; |
58 | |
import org.apache.maven.plugins.annotations.ResolutionScope; |
59 | |
import org.apache.maven.project.MavenProject; |
60 | |
import org.apache.tools.ant.BuildException; |
61 | |
import org.apache.tools.ant.Project; |
62 | |
import org.apache.tools.ant.filters.StringInputStream; |
63 | |
import org.apache.tools.ant.taskdefs.Chmod; |
64 | |
import org.apache.tools.ant.types.FileSet; |
65 | |
import org.codehaus.mojo.nbm.utils.ExamineManifest; |
66 | |
import org.codehaus.plexus.util.FileUtils; |
67 | |
import org.codehaus.plexus.util.IOUtil; |
68 | |
import org.codehaus.plexus.util.StringUtils; |
69 | |
import org.codehaus.plexus.util.io.InputStreamFacade; |
70 | |
import org.netbeans.nbbuild.MakeListOfNBM; |
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
@Mojo(name="cluster-app", |
79 | |
defaultPhase= LifecyclePhase.PACKAGE, |
80 | |
requiresProject=true, |
81 | |
threadSafe = true, |
82 | |
requiresDependencyResolution= ResolutionScope.RUNTIME ) |
83 | 0 | public class CreateClusterAppMojo |
84 | |
extends AbstractNbmMojo |
85 | |
{ |
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
@Parameter(defaultValue="${project.build.directory}", required=true) |
91 | |
private File outputDirectory; |
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
@Parameter(required=true, readonly=true, property="project") |
97 | |
private MavenProject project; |
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
@Parameter(property="netbeans.branding.token", required=true) |
103 | |
protected String brandingToken; |
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
|
109 | |
@Parameter( property="netbeans.conf.file") |
110 | |
private File etcConfFile; |
111 | |
|
112 | |
|
113 | |
|
114 | |
|
115 | |
|
116 | |
@Parameter(property="netbeans.clusters.file") |
117 | |
private File etcClustersFile; |
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | |
|
124 | |
|
125 | |
@Parameter(property="netbeans.bin.directory") |
126 | |
private File binDirectory; |
127 | |
|
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | |
|
133 | |
@Parameter(defaultValue="extra") |
134 | |
private String defaultCluster; |
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
@Parameter(defaultValue = "true", property = "netbeans.verify.integrity") |
142 | |
private boolean verifyIntegrity; |
143 | |
|
144 | 0 | private final Collection<String> defaultPlatformTokens = Arrays.asList( new String[] { |
145 | |
"org.openide.modules.os.Windows", |
146 | |
"org.openide.modules.os.Unix", |
147 | |
"org.openide.modules.os.MacOSX", |
148 | |
"org.openide.modules.os.OS2", |
149 | |
"org.openide.modules.os.PlainUnix", |
150 | |
"org.openide.modules.os.Linux", |
151 | |
"org.openide.modules.os.Solaris", |
152 | |
"org.openide.modules.ModuleFormat1", |
153 | |
"org.openide.modules.ModuleFormat2", |
154 | |
"org.openide.modules.jre.JavaFX" |
155 | |
}); |
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | |
@Component |
161 | |
private ArtifactFactory artifactFactory; |
162 | |
|
163 | |
@Component |
164 | |
private ArtifactResolver artifactResolver; |
165 | |
|
166 | |
|
167 | |
|
168 | |
|
169 | |
|
170 | |
@Parameter(required=true, readonly=true, property="localRepository") |
171 | |
protected ArtifactRepository localRepository; |
172 | |
|
173 | |
|
174 | |
|
175 | |
|
176 | |
public void execute() |
177 | |
throws MojoExecutionException, MojoFailureException |
178 | |
{ |
179 | |
|
180 | 0 | File nbmBuildDirFile = new File( outputDirectory, brandingToken ); |
181 | 0 | if ( !nbmBuildDirFile.exists() ) |
182 | |
{ |
183 | 0 | nbmBuildDirFile.mkdirs(); |
184 | |
} |
185 | |
|
186 | 0 | if ( "nbm-application".equals( project.getPackaging() ) ) |
187 | |
{ |
188 | 0 | Project antProject = registerNbmAntTasks(); |
189 | |
|
190 | 0 | Set<String> wrappedBundleCNBs = new HashSet<String>(100); |
191 | 0 | Map<String, Set<String>> clusterDependencies = new HashMap<String, Set<String>>(); |
192 | 0 | Map<String, Set<String>> clusterModules = new HashMap<String, Set<String>>(); |
193 | |
|
194 | |
|
195 | 0 | Set<String> modulesCNBs = new HashSet<String>(200); |
196 | 0 | Set<String> dependencyCNBs = new HashSet<String>(200); |
197 | 0 | Map<String, Set<String>> dependencyCNBBacktraces = new HashMap<String, Set<String>>(50); |
198 | 0 | Set<String> requireTokens = new HashSet<String>(50); |
199 | 0 | Map<String, Set<String>> requireTokensBacktraces = new HashMap<String, Set<String>>(50); |
200 | 0 | Set<String> provideTokens = new HashSet<String>(50); |
201 | 0 | Set<String> osgiImports = new HashSet<String>(50); |
202 | 0 | Map<String, Set<String>> osgiImportsBacktraces = new HashMap<String, Set<String>>(50); |
203 | 0 | Set<String> osgiExports = new HashSet<String>(50); |
204 | 0 | Set<String> osgiExportsSubs = new HashSet<String>(50); |
205 | |
|
206 | 0 | List<BundleTuple> bundles = new ArrayList<BundleTuple>(); |
207 | |
|
208 | |
@SuppressWarnings( "unchecked" ) |
209 | 0 | Set<Artifact> artifacts = project.getArtifacts(); |
210 | 0 | for ( Artifact art : artifacts ) |
211 | |
{ |
212 | 0 | ArtifactResult res = turnJarToNbmFile( art, artifactFactory, artifactResolver, project, localRepository ); |
213 | 0 | if ( res.hasConvertedArtifact() ) |
214 | |
{ |
215 | 0 | art = res.getConvertedArtifact(); |
216 | |
} |
217 | |
|
218 | 0 | if ( art.getType().equals( "nbm-file" ) ) |
219 | |
{ |
220 | |
try |
221 | |
{ |
222 | 0 | JarFile jf = new JarFile( art.getFile() ); |
223 | |
try |
224 | |
{ |
225 | 0 | String clusterName = findCluster( jf ); |
226 | 0 | ClusterTuple cluster = processCluster( clusterName, nbmBuildDirFile, art ); |
227 | |
|
228 | 0 | getLog().debug( "Copying " + art.getId() + " to cluster " + clusterName ); |
229 | 0 | Enumeration<JarEntry> enu = jf.entries(); |
230 | |
|
231 | |
|
232 | 0 | MakeListOfNBM makeTask = (MakeListOfNBM) antProject.createTask( "genlist" ); |
233 | 0 | antProject.setNewProperty( "module.name", art.getFile().getName() ); |
234 | 0 | antProject.setProperty( "cluster.dir", clusterName ); |
235 | 0 | FileSet set = makeTask.createFileSet(); |
236 | 0 | set.setDir( cluster.location ); |
237 | 0 | makeTask.setOutputfiledir( cluster.location ); |
238 | 0 | String[] executables = null; |
239 | 0 | File classpathRoot = null; |
240 | 0 | String classPath = null; |
241 | 0 | while ( enu.hasMoreElements() ) |
242 | |
{ |
243 | 0 | JarEntry ent = enu.nextElement(); |
244 | 0 | String name = ent.getName(); |
245 | |
|
246 | 0 | if (name.equals("Info/executables.list")) { |
247 | 0 | if (cluster.newer) { |
248 | 0 | InputStream is = jf.getInputStream( ent ); |
249 | 0 | executables = StringUtils.split( IOUtil.toString( is, "UTF-8" ), "\n"); |
250 | 0 | } |
251 | |
} |
252 | 0 | else if ( name.startsWith( "netbeans/" ) ) |
253 | |
{ |
254 | 0 | String path = clusterName + name.substring( "netbeans".length() ); |
255 | 0 | boolean ispack200 = path.endsWith( ".jar.pack.gz" ); |
256 | 0 | if ( ispack200 ) |
257 | |
{ |
258 | 0 | path = path.replace( ".jar.pack.gz", ".jar" ); |
259 | |
} |
260 | 0 | File fl = new File( nbmBuildDirFile, path.replace( "/", File.separator ) ); |
261 | 0 | String part = name.substring( "netbeans/".length() ); |
262 | 0 | if ( ispack200 ) |
263 | |
{ |
264 | 0 | part = part.replace( ".jar.pack.gz", ".jar" ); |
265 | |
} |
266 | 0 | if (cluster.newer) |
267 | |
{ |
268 | 0 | if ( ent.isDirectory() ) |
269 | |
{ |
270 | 0 | fl.mkdirs(); |
271 | |
} |
272 | 0 | else if ( path.endsWith( ".external" ) ) |
273 | |
{ |
274 | 0 | InputStream is = jf.getInputStream( ent ); |
275 | |
try |
276 | |
{ |
277 | 0 | externalDownload( new File( fl.getParentFile(), |
278 | |
fl.getName().replaceFirst( "[.]external$", |
279 | |
"" ) ), is ); |
280 | |
} |
281 | |
finally |
282 | |
{ |
283 | 0 | is.close(); |
284 | 0 | } |
285 | |
|
286 | 0 | set.appendIncludes( new String[] { name.substring( "netbeans/".length(), name.length() - ".external".length() ) } ); |
287 | 0 | } |
288 | |
else |
289 | |
{ |
290 | 0 | set.appendIncludes( new String[] { part } ); |
291 | |
|
292 | 0 | fl.getParentFile().mkdirs(); |
293 | 0 | fl.createNewFile(); |
294 | 0 | BufferedOutputStream outstream = null; |
295 | |
try |
296 | |
{ |
297 | 0 | outstream = new BufferedOutputStream( new FileOutputStream( fl ) ); |
298 | 0 | InputStream instream = jf.getInputStream( ent ); |
299 | 0 | if ( ispack200 ) |
300 | |
{ |
301 | 0 | Pack200.Unpacker unp = Pack200.newUnpacker(); |
302 | 0 | JarOutputStream jos = new JarOutputStream( outstream ); |
303 | 0 | GZIPInputStream gzip = new GZIPInputStream( instream ); |
304 | |
try |
305 | |
{ |
306 | 0 | unp.unpack( gzip, jos ); |
307 | |
} |
308 | |
finally |
309 | |
{ |
310 | 0 | jos.close(); |
311 | 0 | } |
312 | 0 | } |
313 | |
else |
314 | |
{ |
315 | 0 | IOUtil.copy( instream, outstream ); |
316 | |
} |
317 | |
} |
318 | |
finally |
319 | |
{ |
320 | 0 | IOUtil.close( outstream ); |
321 | 0 | } |
322 | |
} |
323 | |
} |
324 | |
|
325 | |
|
326 | |
|
327 | |
|
328 | |
|
329 | |
|
330 | |
|
331 | |
|
332 | 0 | if ( part.matches("(modules|core|lib)/[^/]+[.]jar") ) |
333 | |
{ |
334 | 0 | ExamineManifest ex = new ExamineManifest( getLog() ); |
335 | 0 | ex.setJarFile( fl ); |
336 | 0 | ex.setPopulateDependencies( true ); |
337 | 0 | ex.checkFile(); |
338 | 0 | if ( ex.isNetBeansModule() ) |
339 | |
{ |
340 | 0 | makeTask.setModule( part ); |
341 | 0 | addToMap(clusterDependencies, clusterName, ex.getDependencyTokens()); |
342 | 0 | addToMap(clusterModules, clusterName, Collections.singletonList( ex.getModule() )); |
343 | 0 | if (ex.getClasspath().length() > 0) { |
344 | 0 | classPath = ex.getClasspath(); |
345 | 0 | classpathRoot = fl.getParentFile(); |
346 | |
} |
347 | |
} |
348 | 0 | if (verifyIntegrity) { |
349 | 0 | dependencyCNBs.addAll(ex.getDependencyTokens()); |
350 | 0 | modulesCNBs.add(ex.getModule()); |
351 | 0 | for (String d : ex.getDependencyTokens()) { |
352 | 0 | addToMap(dependencyCNBBacktraces, d, Collections.singletonList( ex.getModule() )); |
353 | 0 | } |
354 | 0 | if (ex.isNetBeansModule()) { |
355 | 0 | requireTokens.addAll(ex.getNetBeansRequiresTokens()); |
356 | 0 | for (String r : ex.getNetBeansRequiresTokens()) { |
357 | 0 | addToMap( requireTokensBacktraces, r, Collections.singletonList( ex.getModule())); |
358 | 0 | } |
359 | 0 | provideTokens.addAll(ex.getNetBeansProvidesTokens()); |
360 | 0 | for (String pack : ex.getPackages()) { |
361 | 0 | if (pack.endsWith( ".**")) { |
362 | |
|
363 | 0 | pack = pack.substring( 0, pack.length() - ".**".length()); |
364 | 0 | osgiExportsSubs.add( pack ); |
365 | 0 | } else if (pack.endsWith( ".*")) { |
366 | 0 | pack = pack.substring( 0, pack.length() - ".*".length()); |
367 | 0 | osgiExports.add(pack); |
368 | |
} |
369 | 0 | } |
370 | |
|
371 | |
} |
372 | |
} |
373 | |
} |
374 | |
} |
375 | 0 | } |
376 | 0 | if (classPath != null) { |
377 | 0 | String[] paths = StringUtils.split( classPath, " "); |
378 | 0 | for (String path : paths) { |
379 | 0 | path = path.trim(); |
380 | 0 | File classpathFile = new File(classpathRoot, path); |
381 | 0 | if (path.equals("${java.home}/lib/ext/jfxrt.jar")) { |
382 | 0 | String jhm = System.getProperty("java.home"); |
383 | 0 | classpathFile = new File(new File(new File(new File(jhm), "lib"), "ext"), "jfxrt.jar"); |
384 | 0 | if (!classpathFile.exists()) { |
385 | 0 | File jdk7 = new File(new File(new File(jhm), "lib"), "jfxrt.jar"); |
386 | 0 | if (jdk7.exists()) { |
387 | 0 | classpathFile = jdk7; |
388 | |
} |
389 | |
} |
390 | |
} |
391 | 0 | if (!classpathFile.isFile()) { |
392 | 0 | getLog().warn( "Could not resolve Class-Path item in " + art.getId() + ", path is:" + path + ", skipping"); |
393 | 0 | continue; |
394 | |
} |
395 | 0 | ExamineManifest ex = new ExamineManifest( getLog() ); |
396 | 0 | ex.setJarFile( classpathFile ); |
397 | |
|
398 | 0 | ex.checkFile(); |
399 | 0 | if (ex.isOsgiBundle()) { |
400 | 0 | wrappedBundleCNBs.add( ex.getModule() ); |
401 | |
} |
402 | |
} |
403 | |
} |
404 | 0 | if ( cluster.newer ) |
405 | |
{ |
406 | |
try |
407 | |
{ |
408 | 0 | makeTask.execute(); |
409 | |
} |
410 | 0 | catch ( BuildException e ) |
411 | |
{ |
412 | 0 | getLog().error( "Cannot Generate update_tracking XML file from " + art.getFile() ); |
413 | 0 | throw new MojoExecutionException( e.getMessage(), e ); |
414 | 0 | } |
415 | |
|
416 | 0 | if ( executables != null ) |
417 | |
{ |
418 | |
|
419 | 0 | for ( String exec : executables ) |
420 | |
{ |
421 | 0 | exec = exec.replace( "/", File.separator ); |
422 | 0 | File execFile = new File( cluster.location, exec ); |
423 | 0 | if ( execFile.exists() ) |
424 | |
{ |
425 | 0 | execFile.setExecutable( true, false ); |
426 | |
} |
427 | |
} |
428 | |
} |
429 | |
} |
430 | |
|
431 | |
} |
432 | |
finally |
433 | |
{ |
434 | 0 | jf.close(); |
435 | 0 | } |
436 | |
} |
437 | 0 | catch ( IOException ex ) |
438 | |
{ |
439 | 0 | getLog().error( art.getFile().getAbsolutePath(), ex ); |
440 | 0 | } |
441 | |
} |
442 | 0 | if ( res.isOSGiBundle() ) |
443 | |
{ |
444 | 0 | ExamineManifest ex = res.getExaminedManifest(); |
445 | 0 | bundles.add( new BundleTuple( art, ex) ); |
446 | 0 | if (verifyIntegrity) { |
447 | 0 | dependencyCNBs.addAll(ex.getDependencyTokens()); |
448 | 0 | for ( String d : ex.getDependencyTokens() ) |
449 | |
{ |
450 | 0 | addToMap( dependencyCNBBacktraces, d, Collections.singletonList( ex.getModule() ) ); |
451 | 0 | } |
452 | 0 | modulesCNBs.add(ex.getModule()); |
453 | 0 | osgiImports.addAll( ex.getOsgiImports()); |
454 | 0 | for ( String d : ex.getOsgiImports() ) |
455 | |
{ |
456 | 0 | addToMap( osgiImportsBacktraces, d, Collections.singletonList( ex.getModule() ) ); |
457 | 0 | } |
458 | |
|
459 | 0 | osgiExports.addAll( ex.getOsgiExports()); |
460 | |
} |
461 | |
} |
462 | 0 | } |
463 | |
|
464 | 0 | if (verifyIntegrity) { |
465 | 0 | if (getLog().isDebugEnabled()) { |
466 | 0 | getLog().debug( "All found codenamebases:" + Arrays.toString( modulesCNBs.toArray()) ); |
467 | 0 | getLog().debug( "All found OSGI exports:" + Arrays.toString( osgiExports.toArray()) ); |
468 | 0 | getLog().debug( "All found provided tokens:" + Arrays.toString( provideTokens.toArray()) ); |
469 | |
} |
470 | 0 | dependencyCNBs.removeAll( modulesCNBs ); |
471 | 0 | if (modulesCNBs.contains( "org.netbeans.modules.netbinox")) { |
472 | 0 | dependencyCNBs.remove( "org.eclipse.osgi"); |
473 | |
} |
474 | 0 | osgiImports.removeAll( osgiExports ); |
475 | 0 | Iterator<String> it = osgiImports.iterator(); |
476 | 0 | while (it.hasNext()) { |
477 | 0 | String s = it.next(); |
478 | 0 | if (s.startsWith( "java.") || s.startsWith( "javax.") || s.startsWith( "sun.") || s.startsWith( "org.xml.sax") || s.startsWith( "org.w3c.dom") || s.startsWith( "org.ietf.jgss")) { |
479 | 0 | it.remove(); |
480 | 0 | continue; |
481 | |
} |
482 | 0 | for (String sub : osgiExportsSubs) { |
483 | 0 | if (s.startsWith( sub )) { |
484 | 0 | it.remove(); |
485 | 0 | break; |
486 | |
} |
487 | 0 | } |
488 | 0 | } |
489 | 0 | requireTokens.removeAll( provideTokens ); |
490 | 0 | requireTokens.removeAll( defaultPlatformTokens ); |
491 | 0 | if (!dependencyCNBs.isEmpty() || !osgiImports.isEmpty() ||!requireTokens.isEmpty()) { |
492 | 0 | if (!dependencyCNBs.isEmpty()) { |
493 | 0 | getLog().error( "Some included modules/bundles depend on these codenamebases but they are not included. The application will fail starting up. The missing codenamebases are:" ); |
494 | 0 | for (String s : dependencyCNBs) { |
495 | 0 | Set<String> back = dependencyCNBBacktraces.get( s ); |
496 | 0 | getLog().error(" " + s + (back != null ? " ref: " + Arrays.toString( back.toArray()) : "")); |
497 | 0 | } |
498 | |
} |
499 | 0 | if (!osgiImports.isEmpty()) { |
500 | 0 | getLog().error("Some OSGi imports are not satisfied by included bundles' exports. The application will fail starting up. The missing imports are:"); |
501 | 0 | for (String s : osgiImports) { |
502 | 0 | Set<String> back = osgiImportsBacktraces.get( s ); |
503 | 0 | getLog().error(" " + s + (back != null ? " ref: " + Arrays.toString( back.toArray()) : "")); |
504 | 0 | } |
505 | |
} |
506 | 0 | if (!requireTokens.isEmpty()) { |
507 | 0 | getLog().error("Some tokens required by included modules are not provided by included modules. The application will fail starting up. The missing tokens are:"); |
508 | 0 | for (String s : requireTokens) { |
509 | 0 | Set<String> back = requireTokensBacktraces.get( s ); |
510 | 0 | getLog().error(" " + s + (back != null ? " ref: " + Arrays.toString( back.toArray()) : "")); |
511 | 0 | } |
512 | |
} |
513 | 0 | throw new MojoFailureException("See above for consistency validation check failures. Either fix those by adding the relevant dependencies to the application or disable the check by setting the verifyIntegrity parameter to false or by running with -Dnetbeans.verify.integrity=false cmd line parameter."); |
514 | |
} else { |
515 | 0 | getLog().info( "Integrity verification passed."); |
516 | |
} |
517 | 0 | } else { |
518 | 0 | getLog().info( "Integrity verification skipped."); |
519 | |
} |
520 | |
|
521 | |
|
522 | 0 | Map<String, Set<String>> cluster2depClusters = computeClusterOrdering( clusterDependencies, clusterModules ); |
523 | 0 | clusterModules.clear(); |
524 | |
|
525 | |
|
526 | 0 | assignClustersToBundles( bundles, wrappedBundleCNBs, clusterDependencies, cluster2depClusters, getLog() ); |
527 | |
|
528 | |
|
529 | 0 | for (BundleTuple ent : bundles) { |
530 | 0 | Artifact art = ent.artifact; |
531 | 0 | final ExamineManifest ex = ent.manifest; |
532 | |
|
533 | 0 | String clstr = ent.cluster; |
534 | 0 | if (clstr == null) { |
535 | 0 | clstr = defaultCluster; |
536 | |
} |
537 | |
|
538 | 0 | ClusterTuple cluster = processCluster( clstr, nbmBuildDirFile, art ); |
539 | 0 | if ( cluster.newer ) |
540 | |
{ |
541 | 0 | getLog().info( "Copying " + art.getId() + " to cluster " + clstr ); |
542 | 0 | File modules = new File( cluster.location, "modules" ); |
543 | 0 | modules.mkdirs(); |
544 | 0 | File config = new File( cluster.location, "config" ); |
545 | 0 | File confModules = new File( config, "Modules" ); |
546 | 0 | confModules.mkdirs(); |
547 | 0 | File updateTracking = new File( cluster.location, "update_tracking" ); |
548 | 0 | updateTracking.mkdirs(); |
549 | 0 | final String cnb = ex.getModule(); |
550 | 0 | final String cnbDashed = cnb.replace( ".", "-" ); |
551 | 0 | final File moduleArt = new File( modules, cnbDashed + ".jar" ); |
552 | 0 | final String specVer = ex.getSpecVersion(); |
553 | |
try |
554 | |
{ |
555 | 0 | FileUtils.copyFile( art.getFile(), moduleArt ); |
556 | 0 | final File moduleConf = new File( confModules, cnbDashed + ".xml" ); |
557 | 0 | FileUtils.copyStreamToFile( new InputStreamFacade() { |
558 | |
@Override |
559 | |
public InputStream getInputStream() throws IOException |
560 | |
{ |
561 | 0 | return new StringInputStream( createBundleConfigFile( cnb, ex.isBundleAutoload() ), "UTF-8" ); |
562 | |
} |
563 | |
}, moduleConf ); |
564 | 0 | FileUtils.copyStreamToFile( new InputStreamFacade() { |
565 | |
@Override |
566 | |
public InputStream getInputStream() throws IOException |
567 | |
{ |
568 | 0 | return new StringInputStream( createBundleUpdateTracking( cnb, moduleArt, moduleConf, specVer ), "UTF-8" ); |
569 | |
} |
570 | |
}, new File( updateTracking, cnbDashed + ".xml" ) ); |
571 | |
} |
572 | 0 | catch ( IOException exc ) |
573 | |
{ |
574 | 0 | getLog().error( exc ); |
575 | 0 | } |
576 | |
} |
577 | 0 | } |
578 | |
|
579 | 0 | getLog().info( |
580 | |
"Created NetBeans module cluster(s) at " + nbmBuildDirFile.getAbsoluteFile() ); |
581 | |
|
582 | 0 | } |
583 | |
else |
584 | |
{ |
585 | 0 | throw new MojoExecutionException( |
586 | |
"This goal only makes sense on project with nbm-application packaging" ); |
587 | |
} |
588 | |
|
589 | 0 | File[] files = nbmBuildDirFile.listFiles(); |
590 | 0 | for ( int i = 0; i < files.length; i++ ) |
591 | |
{ |
592 | 0 | if ( files[i].isDirectory() ) |
593 | |
{ |
594 | 0 | File stamp = new File( files[i], ".lastModified" ); |
595 | 0 | if ( !stamp.exists() ) |
596 | |
{ |
597 | |
try |
598 | |
{ |
599 | 0 | stamp.createNewFile(); |
600 | |
} |
601 | 0 | catch ( IOException ex ) |
602 | |
{ |
603 | 0 | ex.printStackTrace(); |
604 | 0 | } |
605 | |
} |
606 | 0 | stamp.setLastModified( new Date().getTime() ); |
607 | |
} |
608 | |
} |
609 | |
try |
610 | |
{ |
611 | 0 | createBinEtcDir( nbmBuildDirFile, brandingToken ); |
612 | |
} |
613 | 0 | catch ( IOException ex ) |
614 | |
{ |
615 | 0 | throw new MojoExecutionException( |
616 | |
"Cannot process etc folder content creation.", ex ); |
617 | 0 | } |
618 | 0 | } |
619 | 0 | private final static Pattern patt = Pattern.compile( |
620 | |
".*targetcluster=\"([a-zA-Z0-9_\\.\\-]+)\".*", Pattern.DOTALL ); |
621 | |
|
622 | |
private String findCluster( JarFile jf ) |
623 | |
throws MojoFailureException, IOException |
624 | |
{ |
625 | 0 | ZipEntry entry = jf.getEntry( "Info/info.xml" ); |
626 | 0 | InputStream ins = jf.getInputStream( entry ); |
627 | 0 | String str = IOUtil.toString( ins, "UTF8" ); |
628 | 0 | Matcher m = patt.matcher( str ); |
629 | 0 | if ( !m.matches() ) |
630 | |
{ |
631 | 0 | getLog().info( "Cannot find cluster for " + jf.getName() + " Falling back to default value - '" |
632 | |
+ defaultCluster + "'." ); |
633 | 0 | return defaultCluster; |
634 | |
} |
635 | |
else |
636 | |
{ |
637 | 0 | return m.group( 1 ); |
638 | |
} |
639 | |
} |
640 | |
|
641 | |
|
642 | |
|
643 | |
|
644 | |
|
645 | |
|
646 | |
|
647 | |
|
648 | |
private void createBinEtcDir( File buildDir, String brandingToken ) |
649 | |
throws IOException, MojoExecutionException |
650 | |
{ |
651 | 0 | File etcDir = new File( buildDir + File.separator + "etc" ); |
652 | 0 | etcDir.mkdir(); |
653 | |
|
654 | |
|
655 | |
|
656 | 0 | File clusterConf = new File( etcDir + File.separator + brandingToken + ".clusters" ); |
657 | |
String clustersString; |
658 | 0 | if ( etcClustersFile != null ) |
659 | |
{ |
660 | 0 | clustersString = FileUtils.fileRead( etcClustersFile, "UTF-8" ); |
661 | |
} |
662 | |
else |
663 | |
{ |
664 | 0 | clusterConf.createNewFile(); |
665 | 0 | StringBuffer buffer = new StringBuffer(); |
666 | 0 | File[] clusters = buildDir.listFiles( new FileFilter() |
667 | 0 | { |
668 | |
|
669 | |
@Override |
670 | |
public boolean accept( File pathname ) |
671 | |
{ |
672 | 0 | return new File( pathname, ".lastModified" ).exists(); |
673 | |
} |
674 | |
} ); |
675 | 0 | for ( File cluster : clusters ) |
676 | |
{ |
677 | 0 | buffer.append( cluster.getName() ); |
678 | 0 | buffer.append( "\n" ); |
679 | |
} |
680 | 0 | clustersString = buffer.toString(); |
681 | |
} |
682 | |
|
683 | 0 | FileUtils.fileWrite( clusterConf.getAbsolutePath(), clustersString ); |
684 | |
|
685 | 0 | File confFile = etcConfFile; |
686 | |
String str; |
687 | 0 | if ( confFile == null ) |
688 | |
{ |
689 | 0 | File harnessDir = new File( buildDir, "harness" ); |
690 | |
|
691 | 0 | confFile = new File( |
692 | |
harnessDir.getAbsolutePath() + File.separator + "etc" + File.separator + "app.conf" ); |
693 | 0 | if ( confFile.exists() ) |
694 | |
{ |
695 | 0 | str = FileUtils.fileRead( confFile, "UTF-8" ); |
696 | |
} |
697 | |
else |
698 | |
{ |
699 | 0 | getLog().debug( "Using fallback app.conf shipping with the nbm-maven-plugin." ); |
700 | 0 | InputStream instream = null; |
701 | |
try |
702 | |
{ |
703 | 0 | instream = getClass().getClassLoader().getResourceAsStream( "harness/etc/app.conf" ); |
704 | 0 | str = IOUtil.toString( instream, "UTF-8" ); |
705 | |
} |
706 | |
finally |
707 | |
{ |
708 | 0 | IOUtil.close( instream ); |
709 | 0 | } |
710 | |
} |
711 | 0 | } |
712 | |
else |
713 | |
{ |
714 | 0 | str = FileUtils.fileRead( confFile, "UTF-8" ); |
715 | |
} |
716 | 0 | File confDestFile = new File( |
717 | |
etcDir.getAbsolutePath() + File.separator + brandingToken + ".conf" ); |
718 | |
|
719 | 0 | str = str.replace( "${branding.token}", brandingToken ); |
720 | 0 | FileUtils.fileWrite( confDestFile.getAbsolutePath(), "UTF-8", str ); |
721 | |
|
722 | 0 | File destBinDir = new File( buildDir + File.separator + "bin" ); |
723 | 0 | destBinDir.mkdir(); |
724 | |
|
725 | |
File binDir; |
726 | 0 | File destExeW = new File( destBinDir, brandingToken + "_w.exe" ); |
727 | 0 | File destExe = new File( destBinDir, brandingToken + ".exe" ); |
728 | 0 | File destExe64 = new File( destBinDir, brandingToken + "64.exe" ); |
729 | 0 | File destSh = new File( destBinDir, brandingToken ); |
730 | |
|
731 | 0 | if ( binDirectory != null ) |
732 | |
{ |
733 | |
|
734 | 0 | binDir = binDirectory; |
735 | 0 | File[] fls = binDir.listFiles(); |
736 | 0 | if ( fls == null ) |
737 | |
{ |
738 | 0 | throw new MojoExecutionException( "Parameter 'binDirectory' has to point to an existing folder." ); |
739 | |
} |
740 | 0 | for ( File fl : fls ) |
741 | |
{ |
742 | 0 | String name = fl.getName(); |
743 | 0 | File dest = null; |
744 | 0 | if ( name.endsWith( "_w.exe" ) ) |
745 | |
{ |
746 | 0 | dest = destExeW; |
747 | |
} |
748 | 0 | else if ( name.endsWith( "64.exe" ) ) |
749 | |
{ |
750 | 0 | dest = destExe64; |
751 | |
} |
752 | 0 | else if ( name.endsWith( ".exe" ) ) |
753 | |
{ |
754 | 0 | dest = destExe; |
755 | |
} |
756 | 0 | else if ( !name.contains( "." ) || name.endsWith( ".sh" ) ) |
757 | |
{ |
758 | 0 | dest = destSh; |
759 | |
} |
760 | 0 | if ( dest != null && fl.exists() ) |
761 | |
{ |
762 | 0 | FileUtils.copyFile( fl, dest ); |
763 | |
} |
764 | |
else |
765 | |
{ |
766 | |
|
767 | |
} |
768 | |
} |
769 | 0 | } |
770 | |
else |
771 | |
{ |
772 | 0 | File harnessDir = new File( buildDir, "harness" ); |
773 | |
|
774 | 0 | binDir = new File( |
775 | |
harnessDir.getAbsolutePath() + File.separator + "launchers" ); |
776 | 0 | if ( binDir.exists() ) |
777 | |
{ |
778 | 0 | File exe = new File( binDir, "app.exe" ); |
779 | 0 | FileUtils.copyFile( exe, destExe ); |
780 | 0 | File exe64 = new File( binDir, "app64.exe" ); |
781 | 0 | if ( exe64.isFile() ) |
782 | |
{ |
783 | 0 | FileUtils.copyFile( exe64, destExe64 ); |
784 | |
} |
785 | 0 | File exew = new File( binDir, "app_w.exe" ); |
786 | 0 | if ( exew.exists() ) |
787 | |
{ |
788 | 0 | FileUtils.copyFile( exew, destExeW ); |
789 | |
} |
790 | 0 | File sh = new File( binDir, "app.sh" ); |
791 | 0 | FileUtils.copyFile( sh, destSh ); |
792 | 0 | } |
793 | |
else |
794 | |
{ |
795 | 0 | File nbm = getHarnessNbm(); |
796 | 0 | ZipFile zip = new ZipFile( nbm ); |
797 | |
try { |
798 | 0 | getLog().debug( "Using fallback executables from downloaded org-netbeans-modules-apisupport-harness nbm file." ); |
799 | 0 | writeFromZip(zip, "netbeans/launchers/app.sh", destSh, true ); |
800 | 0 | writeFromZip(zip, "netbeans/launchers/app.exe", destExe, true ); |
801 | 0 | writeFromZip(zip, "netbeans/launchers/app64.exe", destExe64, false ); |
802 | 0 | writeFromZip(zip, "netbeans/launchers/app_w.exe", destExeW, false ); |
803 | |
} finally { |
804 | 0 | zip.close(); |
805 | 0 | } |
806 | |
} |
807 | |
} |
808 | |
|
809 | 0 | Project antProject = antProject(); |
810 | |
|
811 | 0 | Chmod chmod = (Chmod) antProject.createTask( "chmod" ); |
812 | 0 | FileSet fs = new FileSet(); |
813 | 0 | fs.setDir( destBinDir ); |
814 | 0 | fs.setIncludes( "*" ); |
815 | 0 | chmod.addFileset( fs ); |
816 | 0 | chmod.setPerm( "755" ); |
817 | 0 | chmod.execute(); |
818 | 0 | } |
819 | |
|
820 | |
private void writeFile( String path, File destSh ) |
821 | |
throws IOException |
822 | |
{ |
823 | 0 | InputStream instream = null; |
824 | 0 | OutputStream output = null; |
825 | |
try |
826 | |
{ |
827 | 0 | instream = getClass().getClassLoader().getResourceAsStream( path ); |
828 | 0 | if ( instream == null ) |
829 | |
{ |
830 | 0 | throw new FileNotFoundException( path ); |
831 | |
} |
832 | 0 | destSh.createNewFile(); |
833 | 0 | output = new BufferedOutputStream( new FileOutputStream( destSh ) ); |
834 | 0 | IOUtil.copy( instream, output ); |
835 | |
} |
836 | |
finally |
837 | |
{ |
838 | 0 | IOUtil.close( instream ); |
839 | 0 | IOUtil.close( output ); |
840 | 0 | } |
841 | 0 | } |
842 | |
|
843 | |
private ClusterTuple processCluster( String cluster, File nbmBuildDirFile, Artifact art ) |
844 | |
{ |
845 | 0 | File clusterFile = new File( nbmBuildDirFile, cluster ); |
846 | 0 | boolean newer = false; |
847 | 0 | if ( !clusterFile.exists() ) |
848 | |
{ |
849 | 0 | clusterFile.mkdir(); |
850 | 0 | newer = true; |
851 | |
} |
852 | |
else |
853 | |
{ |
854 | 0 | File stamp = new File( clusterFile, ".lastModified" ); |
855 | 0 | if ( stamp.lastModified() < art.getFile().lastModified() ) |
856 | |
{ |
857 | 0 | newer = true; |
858 | |
} |
859 | |
} |
860 | 0 | return new ClusterTuple( clusterFile, newer ); |
861 | |
} |
862 | |
|
863 | |
private void externalDownload( File f, InputStream is ) |
864 | |
throws IOException |
865 | |
{ |
866 | |
|
867 | 0 | BufferedReader r = new BufferedReader( new InputStreamReader( is, "UTF-8" ) ); |
868 | 0 | long crc = -1; |
869 | 0 | long size = -1; |
870 | 0 | boolean found = false; |
871 | |
String line; |
872 | 0 | while ( ( line = r.readLine() ) != null ) |
873 | |
{ |
874 | 0 | if ( line.startsWith( "CRC:" ) ) |
875 | |
{ |
876 | 0 | crc = Long.parseLong( line.substring( 4 ).trim() ); |
877 | |
} |
878 | 0 | else if ( line.startsWith( "URL:m2:/" ) ) |
879 | |
{ |
880 | 0 | if ( ! found ) |
881 | |
{ |
882 | 0 | String[] coords = line.substring( 8 ).trim().split( ":" ); |
883 | |
Artifact artifact; |
884 | 0 | if ( coords.length == 4 ) |
885 | |
{ |
886 | 0 | artifact = artifactFactory.createArtifact( coords[0], coords[1], coords[2], null, coords[3] ); |
887 | |
} |
888 | |
else |
889 | |
{ |
890 | 0 | artifact = artifactFactory.createArtifactWithClassifier( coords[0], coords[1], coords[2], coords[3], coords[4] ); |
891 | |
} |
892 | |
try |
893 | |
{ |
894 | 0 | artifactResolver.resolve( artifact, project.getRemoteArtifactRepositories(), localRepository ); |
895 | 0 | FileUtils.copyFile( artifact.getFile(), f ); |
896 | 0 | found = true; |
897 | |
} |
898 | 0 | catch ( AbstractArtifactResolutionException x ) |
899 | |
{ |
900 | 0 | getLog().warn( "Cannot find " + line.substring( 8 ), x ); |
901 | 0 | } |
902 | 0 | } |
903 | |
} |
904 | 0 | else if ( line.startsWith( "URL:" ) ) |
905 | |
{ |
906 | 0 | if ( ! found ) |
907 | |
{ |
908 | 0 | String url = line.substring( 4 ).trim(); |
909 | |
try |
910 | |
{ |
911 | |
|
912 | 0 | FileUtils.copyURLToFile( new URL( url ), f ); |
913 | 0 | found = true; |
914 | |
} |
915 | 0 | catch ( IOException x ) |
916 | |
{ |
917 | 0 | getLog().warn( "Cannot download " + url, x ); |
918 | 0 | } |
919 | 0 | } |
920 | |
} |
921 | 0 | else if ( line.startsWith( "SIZE:" ) ) |
922 | |
{ |
923 | 0 | size = Long.parseLong( line.substring( 5 ).trim() ); |
924 | |
} |
925 | |
else |
926 | |
{ |
927 | 0 | getLog().warn( "Unrecognized line: " + line ); |
928 | |
} |
929 | |
} |
930 | 0 | if ( ! found ) |
931 | |
{ |
932 | 0 | throw new IOException( "Could not download " + f ); |
933 | |
} |
934 | 0 | if ( crc != -1 && crc != crcForFile( f ).getValue() ) |
935 | |
{ |
936 | 0 | throw new IOException( "CRC-32 of " + f + " does not match declared " + crc ); |
937 | |
} |
938 | 0 | if ( size != -1 && size != f.length() ) |
939 | |
{ |
940 | 0 | throw new IOException( "Size of " + f + " does not match declared " + size ); |
941 | |
} |
942 | 0 | } |
943 | |
|
944 | |
private File getHarnessNbm() throws MojoExecutionException |
945 | |
{ |
946 | |
@SuppressWarnings( "unchecked" ) |
947 | 0 | Set<Artifact> artifacts = project.getArtifacts(); |
948 | 0 | String version = null; |
949 | 0 | for (Artifact a : artifacts) { |
950 | 0 | if ("org.netbeans.modules".equals(a.getGroupId()) && "org-netbeans-bootstrap".equals(a.getArtifactId())) { |
951 | 0 | version = a.getBaseVersion(); |
952 | 0 | break; |
953 | |
} |
954 | 0 | } |
955 | 0 | if (version == null) { |
956 | 0 | throw new MojoExecutionException( "We could not find org-netbeans-bootstrap among the modules in the application. Launchers could not be found."); |
957 | |
} |
958 | 0 | Artifact nbmArt = artifactFactory.createArtifact( |
959 | |
"org.netbeans.modules", |
960 | |
"org-netbeans-modules-apisupport-harness", |
961 | |
version, |
962 | |
"compile", |
963 | |
"nbm-file"); |
964 | |
try |
965 | |
{ |
966 | 0 | artifactResolver.resolve( nbmArt, project.getRemoteArtifactRepositories(), localRepository ); |
967 | |
} |
968 | |
|
969 | 0 | catch ( ArtifactResolutionException ex ) |
970 | |
{ |
971 | 0 | throw new MojoExecutionException( "Failed to retrieve the nbm file from repository", ex ); |
972 | |
} |
973 | 0 | catch ( ArtifactNotFoundException ex ) |
974 | |
{ |
975 | 0 | throw new MojoExecutionException( "Failed to retrieve the nbm file from repository", ex ); |
976 | 0 | } |
977 | 0 | return nbmArt.getFile(); |
978 | |
} |
979 | |
|
980 | |
private void writeFromZip( final ZipFile zip, String zipPath, File destFile, boolean mandatory ) throws MojoExecutionException, IOException |
981 | |
{ |
982 | 0 | final ZipEntry path = zip.getEntry( zipPath ); |
983 | 0 | if (path == null) { |
984 | 0 | if (mandatory) { |
985 | 0 | throw new MojoExecutionException( zipPath + " not found in " + zip.getName()); |
986 | |
} |
987 | 0 | getLog().debug(zipPath + " is not present in " + zip.getName()); |
988 | 0 | return; |
989 | |
} |
990 | 0 | FileUtils.copyStreamToFile( new InputStreamFacade() { |
991 | |
|
992 | |
@Override |
993 | |
public InputStream getInputStream() throws IOException |
994 | |
{ |
995 | 0 | return zip.getInputStream( path ); |
996 | |
} |
997 | |
}, destFile); |
998 | 0 | } |
999 | |
|
1000 | |
private static void addToMap( Map<String, Set<String>> map, String clusterName, List<String> newValues ) |
1001 | |
{ |
1002 | 0 | Set<String> lst = map.get( clusterName ); |
1003 | 0 | if ( lst == null ) |
1004 | |
{ |
1005 | 0 | lst = new HashSet<String>(); |
1006 | 0 | map.put( clusterName, lst ); |
1007 | |
} |
1008 | 0 | if ( newValues != null ) |
1009 | |
{ |
1010 | 0 | lst.addAll( newValues ); |
1011 | |
} |
1012 | 0 | } |
1013 | |
|
1014 | |
private static List<String> findByDependencies( Map<String, Set<String>> clusterDependencies, String spec) |
1015 | |
{ |
1016 | 0 | List<String> toRet = new ArrayList<String>(); |
1017 | 0 | for ( Map.Entry<String, Set<String>> entry : clusterDependencies.entrySet() ) |
1018 | |
{ |
1019 | 0 | if ( entry.getValue().contains( spec ) ) |
1020 | |
{ |
1021 | 0 | toRet.add(entry.getKey()); |
1022 | |
} |
1023 | 0 | } |
1024 | 0 | return toRet; |
1025 | |
} |
1026 | |
|
1027 | |
|
1028 | |
|
1029 | |
|
1030 | |
|
1031 | |
|
1032 | |
|
1033 | |
|
1034 | |
|
1035 | |
static void assignClustersToBundles( List<BundleTuple> bundles, Set<String> wrappedBundleCNBs, Map<String, Set<String>> clusterDependencies, Map<String, Set<String>> cluster2depClusters, Log log) |
1036 | |
{ |
1037 | 0 | List<BundleTuple> toProcess = new ArrayList<BundleTuple>(); |
1038 | 0 | List<BundleTuple> known = new ArrayList<BundleTuple>(); |
1039 | 0 | for ( Iterator<BundleTuple> it = bundles.iterator(); it.hasNext(); ) |
1040 | |
{ |
1041 | 0 | BundleTuple ent = it.next(); |
1042 | 0 | Artifact art = ent.artifact; |
1043 | 0 | ExamineManifest ex = ent.manifest; |
1044 | 0 | String spec = ex.getModule(); |
1045 | 0 | if ( wrappedBundleCNBs.contains( spec ) ) |
1046 | |
{ |
1047 | |
|
1048 | 0 | log.debug( "Not including bundle " + art.getDependencyConflictId() |
1049 | |
+ ". It is already included in a NetBeans module" ); |
1050 | 0 | it.remove(); |
1051 | 0 | continue; |
1052 | |
} |
1053 | 0 | List<String> depclusters = findByDependencies(clusterDependencies, spec); |
1054 | 0 | if (depclusters.size() == 1) { |
1055 | 0 | ent.cluster = depclusters.get( 0 ); |
1056 | 0 | known.add( ent ); |
1057 | 0 | } else if (depclusters.isEmpty()) { |
1058 | 0 | toProcess.add(ent); |
1059 | |
} else { |
1060 | |
|
1061 | 0 | for ( Iterator<String> it2 = depclusters.iterator(); it2.hasNext(); ) |
1062 | |
{ |
1063 | 0 | String s = it2.next(); |
1064 | 0 | Set<String> depsCs = cluster2depClusters.get( s ); |
1065 | 0 | boolean removeS = false; |
1066 | 0 | for (String sDep : depclusters) { |
1067 | 0 | if (s.equals( sDep) ) { |
1068 | 0 | continue; |
1069 | |
} |
1070 | 0 | if (depsCs != null && depsCs.contains( sDep ) ) { |
1071 | 0 | removeS = true; |
1072 | |
} |
1073 | 0 | } |
1074 | 0 | if (removeS) { |
1075 | 0 | it2.remove(); |
1076 | |
} |
1077 | 0 | } |
1078 | 0 | ent.cluster = depclusters.get( 0 ); |
1079 | 0 | known.add (ent); |
1080 | |
} |
1081 | 0 | } |
1082 | 0 | if (!toProcess.isEmpty()) |
1083 | |
{ |
1084 | 0 | walkKnownBundleDependenciesDown(known, toProcess); |
1085 | |
} |
1086 | 0 | if (!toProcess.isEmpty()) |
1087 | |
{ |
1088 | 0 | walkKnownBundleDependenciesUp(known, toProcess); |
1089 | |
} |
1090 | 0 | } |
1091 | |
|
1092 | |
private static void walkKnownBundleDependenciesDown( List<BundleTuple> known, List<BundleTuple> toProcess ) |
1093 | |
{ |
1094 | 0 | boolean atLeastOneWasFound = false; |
1095 | 0 | for ( Iterator<BundleTuple> it = toProcess.iterator(); it.hasNext(); ) |
1096 | |
{ |
1097 | 0 | BundleTuple bundleTuple = it.next(); |
1098 | 0 | boolean found = false; |
1099 | 0 | for ( BundleTuple knownBT : known) |
1100 | |
{ |
1101 | 0 | Sets.SetView<String> is = Sets.intersection(bundleTuple.manifest.getOsgiExports() , knownBT.manifest.getOsgiImports() ); |
1102 | 0 | if (!is.isEmpty()) { |
1103 | 0 | found = true; |
1104 | 0 | bundleTuple.cluster = knownBT.cluster; |
1105 | 0 | break; |
1106 | |
} |
1107 | |
|
1108 | 0 | is = Sets.intersection(Collections.singleton( bundleTuple.manifest.getModule()), new HashSet(knownBT.manifest.getDependencyTokens()) ); |
1109 | 0 | if (!is.isEmpty()) { |
1110 | 0 | found = true; |
1111 | 0 | bundleTuple.cluster = knownBT.cluster; |
1112 | 0 | break; |
1113 | |
} |
1114 | |
|
1115 | 0 | } |
1116 | 0 | if (found) { |
1117 | 0 | atLeastOneWasFound = true; |
1118 | 0 | it.remove(); |
1119 | 0 | known.add(bundleTuple); |
1120 | |
} |
1121 | |
|
1122 | 0 | } |
1123 | 0 | if (!toProcess.isEmpty() && atLeastOneWasFound) { |
1124 | 0 | walkKnownBundleDependenciesDown( known, toProcess ); |
1125 | |
} |
1126 | 0 | } |
1127 | |
|
1128 | |
private static void walkKnownBundleDependenciesUp( List<BundleTuple> known, List<BundleTuple> toProcess ) |
1129 | |
{ |
1130 | 0 | boolean atLeastOneWasFound = false; |
1131 | 0 | for ( Iterator<BundleTuple> it = toProcess.iterator(); it.hasNext(); ) |
1132 | |
{ |
1133 | 0 | BundleTuple bundleTuple = it.next(); |
1134 | 0 | boolean found = false; |
1135 | 0 | for ( BundleTuple knownBT : known) |
1136 | |
{ |
1137 | 0 | Sets.SetView<String> is = Sets.intersection(bundleTuple.manifest.getOsgiImports() , knownBT.manifest.getOsgiExports() ); |
1138 | 0 | if (!is.isEmpty()) { |
1139 | 0 | found = true; |
1140 | 0 | bundleTuple.cluster = knownBT.cluster; |
1141 | 0 | break; |
1142 | |
} |
1143 | |
|
1144 | 0 | is = Sets.intersection(Collections.singleton( knownBT.manifest.getModule()), new HashSet(bundleTuple.manifest.getDependencyTokens()) ); |
1145 | 0 | if (!is.isEmpty()) { |
1146 | 0 | found = true; |
1147 | 0 | bundleTuple.cluster = knownBT.cluster; |
1148 | 0 | break; |
1149 | |
} |
1150 | |
|
1151 | 0 | } |
1152 | 0 | if (found) { |
1153 | 0 | atLeastOneWasFound = true; |
1154 | 0 | it.remove(); |
1155 | 0 | known.add(bundleTuple); |
1156 | |
} |
1157 | |
|
1158 | 0 | } |
1159 | 0 | if (!toProcess.isEmpty() && atLeastOneWasFound) { |
1160 | 0 | walkKnownBundleDependenciesDown( known, toProcess ); |
1161 | |
} |
1162 | 0 | if (!toProcess.isEmpty() && atLeastOneWasFound) { |
1163 | 0 | walkKnownBundleDependenciesUp( known, toProcess ); |
1164 | |
} |
1165 | 0 | } |
1166 | |
|
1167 | |
|
1168 | |
static Map<String, Set<String>> computeClusterOrdering( Map<String, Set<String>> clusterDependencies, Map<String, Set<String>> clusterModules ) |
1169 | |
{ |
1170 | 0 | Map<String, Set<String>> cluster2depClusters = new HashMap<String, Set<String>>(); |
1171 | 0 | for ( Map.Entry<String, Set<String>> entry : clusterDependencies.entrySet() ) |
1172 | |
{ |
1173 | 0 | String cluster = entry.getKey(); |
1174 | 0 | Set<String> deps = entry.getValue(); |
1175 | 0 | for (Map.Entry<String, Set<String>> subEnt : clusterModules.entrySet()) { |
1176 | 0 | if (subEnt.getKey().equals( cluster) ) { |
1177 | 0 | continue; |
1178 | |
} |
1179 | 0 | Sets.SetView<String> is = Sets.intersection(subEnt.getValue(), deps ); |
1180 | 0 | if (!is.isEmpty()) { |
1181 | 0 | addToMap( cluster2depClusters, cluster, Collections.singletonList( subEnt.getKey() ) ); |
1182 | |
} |
1183 | 0 | } |
1184 | 0 | } |
1185 | 0 | return cluster2depClusters; |
1186 | |
} |
1187 | |
|
1188 | |
static class BundleTuple { |
1189 | |
final Artifact artifact; |
1190 | |
final ExamineManifest manifest; |
1191 | |
String cluster; |
1192 | |
|
1193 | |
BundleTuple( Artifact artifact, ExamineManifest manifest ) |
1194 | 4 | { |
1195 | 4 | this.artifact = artifact; |
1196 | 4 | this.manifest = manifest; |
1197 | 4 | } |
1198 | |
|
1199 | |
} |
1200 | |
|
1201 | 0 | private static class ClusterTuple |
1202 | |
{ |
1203 | |
final File location; |
1204 | |
final boolean newer; |
1205 | |
|
1206 | |
private ClusterTuple( File clusterFile, boolean newer ) |
1207 | 0 | { |
1208 | 0 | location = clusterFile; |
1209 | 0 | this.newer = newer; |
1210 | 0 | } |
1211 | |
} |
1212 | |
|
1213 | |
static String createBundleConfigFile( String cnb, boolean autoload) |
1214 | |
{ |
1215 | 0 | return |
1216 | |
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
1217 | |
"<!DOCTYPE module PUBLIC \"-//NetBeans//DTD Module Status 1.0//EN\"\n" + |
1218 | |
" \"http://www.netbeans.org/dtds/module-status-1_0.dtd\">\n" + |
1219 | |
"<module name=\"" + cnb +"\">\n" + |
1220 | |
" <param name=\"autoload\">" + autoload + "</param>\n" + |
1221 | |
" <param name=\"eager\">false</param>\n" + (autoload ? "" : " <param name=\"enabled\">true</param>\n") + |
1222 | |
" <param name=\"jar\">modules/" + cnb.replace( ".", "-") + ".jar</param>\n" + |
1223 | |
" <param name=\"reloadable\">false</param>\n" + |
1224 | |
"</module>\n"; |
1225 | |
} |
1226 | |
|
1227 | |
static String createBundleUpdateTracking( String cnb, File moduleArt, File moduleConf, String specVersion ) |
1228 | |
throws FileNotFoundException, IOException |
1229 | |
{ |
1230 | |
|
1231 | 0 | return |
1232 | |
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
1233 | |
"<module codename=\"" + cnb + "\">\n" + |
1234 | |
" <module_version install_time=\"" + System.currentTimeMillis() + "\" last=\"true\" origin=\"installer\" specification_version=\"" + specVersion + "\">\n" + |
1235 | |
" <file crc=\"" + crcForFile( moduleConf ).getValue() + "\" name=\"config/Modules/" + cnb.replace( ".", "-" ) + ".xml\"/>\n" + |
1236 | |
" <file crc=\"" + crcForFile( moduleArt ).getValue() + "\" name=\"modules/" + cnb.replace( ".", "-" ) + ".jar\"/>\n" + |
1237 | |
" </module_version>\n" + |
1238 | |
"</module>"; |
1239 | |
|
1240 | |
} |
1241 | |
|
1242 | |
static CRC32 crcForFile( File inFile ) |
1243 | |
throws FileNotFoundException, IOException |
1244 | |
{ |
1245 | 0 | CRC32 crc = new CRC32(); |
1246 | 0 | InputStream inFileStream = new FileInputStream( inFile ); |
1247 | |
try { |
1248 | 0 | byte[] array = new byte[(int) inFile.length()]; |
1249 | 0 | int len = inFileStream.read( array ); |
1250 | 0 | if ( len != array.length ) |
1251 | |
{ |
1252 | 0 | throw new IOException( "Cannot fully read " + inFile ); |
1253 | |
} |
1254 | 0 | crc.update( array ); |
1255 | |
} |
1256 | |
finally |
1257 | |
{ |
1258 | 0 | inFileStream.close(); |
1259 | 0 | } |
1260 | |
|
1261 | 0 | return crc; |
1262 | |
} |
1263 | |
|
1264 | |
} |