KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > petals > tools > jbiplugin > JBIPluginMojo


1 /**
2  * PETALS - PETALS Services Platform.
3  * Copyright (c) 2005 EBM Websourcing, http://www.ebmwebsourcing.com/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * -------------------------------------------------------------------------
19  * $Id: PackageAssemblyMojo.java 16:56:43 ddesjardins $
20  * -------------------------------------------------------------------------
21  */

22 package org.objectweb.petals.tools.jbiplugin;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.io.DataInputStream JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileNotFoundException JavaDoc;
29 import java.io.FileOutputStream JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.StringWriter JavaDoc;
32 import java.nio.ByteBuffer JavaDoc;
33 import java.nio.channels.Channels JavaDoc;
34 import java.nio.channels.FileChannel JavaDoc;
35 import java.nio.channels.ReadableByteChannel JavaDoc;
36 import java.util.HashSet JavaDoc;
37 import java.util.Set JavaDoc;
38 import java.util.jar.JarFile JavaDoc;
39 import java.util.zip.ZipEntry JavaDoc;
40 import java.util.zip.ZipException JavaDoc;
41 import java.util.zip.ZipOutputStream JavaDoc;
42
43 import javax.xml.parsers.DocumentBuilder JavaDoc;
44 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
45 import javax.xml.transform.Result JavaDoc;
46 import javax.xml.transform.Source JavaDoc;
47 import javax.xml.transform.Transformer JavaDoc;
48 import javax.xml.transform.TransformerFactory JavaDoc;
49 import javax.xml.transform.dom.DOMSource JavaDoc;
50 import javax.xml.transform.stream.StreamResult JavaDoc;
51
52 import org.apache.commons.io.FileUtils;
53 import org.apache.maven.artifact.repository.ArtifactRepository;
54 import org.apache.maven.artifact.resolver.ArtifactResolver;
55 import org.apache.maven.embedder.MavenEmbedder;
56 import org.apache.maven.model.Dependency;
57 import org.apache.maven.plugin.AbstractMojo;
58 import org.apache.maven.plugin.MojoExecutionException;
59 import org.apache.maven.project.MavenProject;
60 import org.w3c.dom.Document JavaDoc;
61 import org.w3c.dom.Element JavaDoc;
62 import org.w3c.dom.NodeList JavaDoc;
63
64 /**
65  * Make a JBI Archive of a project
66  *
67  * @goal jbi
68  * @description Make a JBI from a JBI component
69  * @requiresDependencyResolution runtime
70  *
71  * @author ddesjardins - eBMWebsourcing
72  */

73 public class JBIPluginMojo extends AbstractMojo {
74
75     /**
76      * @component
77      */

78     protected ArtifactResolver artifactResolver;
79
80     /**
81      * Component Jar
82      *
83      * @parameter expression="${project.build.directory}/${project.artifactId}-${project.version}.jar"
84      * @editable true
85      * @required
86      * @description Name of the generated component Jar
87      */

88     protected File JavaDoc componentJar;
89
90     /**
91      * JBI conf directory
92      *
93      * @parameter expression="${basedir}/src/conf/"
94      * @required
95      * @description Path of the JBI conf directory
96      */

97     protected File JavaDoc jbiDirectory;
98
99     /**
100      * JBI Name
101      *
102      * @parameter expression="${project.artifactId}-${project.version}"
103      * @editable true
104      * @required
105      * @description Name of the generated jbi archive
106      */

107     protected String JavaDoc jbiName;
108
109     /**
110      * SubDependencies inclusion
111      *
112      * @parameter expression="false"
113      * @editable true
114      * @required
115      * @description Boolean to include the dependencies of the dependencies
116      */

117     protected boolean includeSubDependencies;
118
119     /**
120      * Verbose
121      *
122      * @parameter expression="false"
123      * @editable true
124      * @required
125      * @description Boolean to switch to verbose mode
126      */

127     protected boolean verbose;
128
129     /**
130      * Update JBI XML file
131      *
132      * @parameter expression="false"
133      * @editable true
134      * @required
135      * @description Boolean to force the update of the JBI XML file to add all
136      * the dependencies of the archive
137      */

138     protected boolean updateJBIXml;
139
140     /**
141      * Local maven repository.
142      *
143      * @parameter expression="${localRepository}"
144      * @required
145      * @readonly
146      */

147     protected ArtifactRepository localRepository;
148
149     /**
150      * Output directory
151      *
152      * @parameter expression="${project.build.directory}"
153      * @required
154      */

155     protected File JavaDoc outputDirectory;
156
157     /**
158      * List of jar to exclude (comma separated values)
159      *
160      * @parameter expression="foo"
161      * @required
162      * @editable true
163      * @description List of jar to exclude (comma separated values)
164      */

165     protected String JavaDoc toExcludes;
166
167     /**
168      * The Maven Project.
169      *
170      * @parameter expression="${project}"
171      * @required
172      * @readonly
173      */

174     protected MavenProject project;
175
176     /**
177      * Set of entries in the zip
178      */

179     private Set JavaDoc<String JavaDoc> entries = new HashSet JavaDoc<String JavaDoc>();
180
181     /**
182      * List of entries to exclude
183      */

184     private Set JavaDoc<String JavaDoc> entriesToExclude = new HashSet JavaDoc<String JavaDoc>();
185
186     /**
187      * Recurse a directory to add its content to a zip file if updateJBIXml file
188      * is true do not add the jbi.xml file to the archive we will added it after
189      *
190      * @param zipOutputStream
191      * zip file
192      * @param directory
193      * directory to recurse
194      * @param entryDirectoryName
195      * directory to put the content in the zip
196      * @throws Exception
197      */

198     private void recurseDirectory(ZipOutputStream JavaDoc zipOutputStream,
199         File JavaDoc directory, String JavaDoc entryDirectoryName) throws Exception JavaDoc {
200         for (File JavaDoc file : directory.listFiles()) {
201             if (file.isFile()) {
202                 if (!updateJBIXml
203                     || (updateJBIXml && !file.getName().equals("jbi.xml"))) {
204                     ZipEntry JavaDoc zipEntry = new ZipEntry JavaDoc(entryDirectoryName
205                         + File.separator + file.getName());
206                     DataInputStream JavaDoc dis = new DataInputStream JavaDoc(
207                         new FileInputStream JavaDoc(file));
208                     byte[] content = new byte[dis.available()];
209                     dis.readFully(content);
210                     zipOutputStream.putNextEntry(zipEntry);
211                     zipOutputStream.write(content);
212                     zipOutputStream.closeEntry();
213                 }
214             } else {
215                 if (!file.getName().startsWith(".")) {
216                     // Avoid to add the .svn directory
217
recurseDirectory(zipOutputStream, file, entryDirectoryName
218                         + File.separator + file.getName());
219                 }
220             }
221         }
222     }
223
224     /**
225      * Extract the list of jar to exclude from the archive
226      *
227      */

228     private void extractExcludeValues() {
229         // We remove the space
230
if (!"foo".equals(toExcludes)) {
231             toExcludes = toExcludes.replace(" ", "");
232             for (String JavaDoc jar : toExcludes.split(",")) {
233                 entriesToExclude.add(jar);
234             }
235         }
236     }
237
238     /**
239      * Execute the plugin
240      */

241     public void execute() throws MojoExecutionException {
242         try {
243             project.getArtifact().setFile(new File JavaDoc(outputDirectory
244                 + File.separator + jbiName + ".zip"));
245             if (jbiDirectory.exists()) {
246                 if (verbose) {
247                     System.out.println("Start building JBI archive "
248                         + new File JavaDoc(outputDirectory
249                             + File.separator + jbiName + ".zip")
250                             .getAbsolutePath());
251                 }
252                 new File JavaDoc(outputDirectory
253                     + File.separator + jbiName + ".zip").delete();
254
255                 // Extract the exclude values
256
extractExcludeValues();
257
258                 // Add the jbi files
259
ZipOutputStream JavaDoc zipOutputStream = new ZipOutputStream JavaDoc(
260                     new FileOutputStream JavaDoc(new File JavaDoc(outputDirectory
261                         + File.separator + jbiName + ".zip")));
262                 recurseDirectory(zipOutputStream, jbiDirectory, "META-INF");
263                 zipOutputStream.flush();
264
265                 // Add the component jar
266
ZipEntry JavaDoc zipEntry = new ZipEntry JavaDoc(componentJar.getName());
267                 DataInputStream JavaDoc dis = new DataInputStream JavaDoc(new FileInputStream JavaDoc(
268                     componentJar));
269                 byte[] content = new byte[dis.available()];
270                 dis.readFully(content);
271                 zipOutputStream.putNextEntry(zipEntry);
272                 zipOutputStream.write(content);
273                 zipOutputStream.closeEntry();
274
275                 // Include a project
276
includeProject(zipOutputStream, project);
277
278                 if (updateJBIXml) {
279                     // Update the JBI XML file
280
updateJBIXmlFile(zipOutputStream);
281                 }
282
283                 zipOutputStream.flush();
284                 if (project.getDependencies().size() > 0) {
285                     zipOutputStream.close();
286                 }
287                 if (verbose) {
288                     System.out.println("JBI archive building done.\n");
289                 }
290             }
291         } catch (Exception JavaDoc e) {
292             e.printStackTrace();
293             throw new MojoExecutionException(e.getLocalizedMessage(), e);
294         }
295     }
296
297     /**
298      * Clone a set of String
299      *
300      * @param setToClone
301      * @return
302      */

303     private Set JavaDoc<String JavaDoc> cloneSet(Set JavaDoc<String JavaDoc> setToClone) {
304         Set JavaDoc<String JavaDoc> outSet = new HashSet JavaDoc<String JavaDoc>();
305         for (String JavaDoc string : setToClone) {
306             outSet.add(string);
307         }
308         return outSet;
309     }
310
311     /**
312      * Update the JBI xml file to added all the dependencies of the JBI archive
313      *
314      * @param zipOutputStream
315      * @throws FileNotFoundException
316      */

317     private void updateJBIXmlFile(ZipOutputStream JavaDoc zipOutputStream)
318         throws FileNotFoundException JavaDoc {
319         InputStream JavaDoc inputStream = null;
320         try {
321             DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory
322                 .newInstance();
323             DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
324             Document JavaDoc document = builder.parse(new File JavaDoc(jbiDirectory
325                 + File.separator + "jbi.xml"));
326             Element JavaDoc element = document.getDocumentElement();
327
328             // Check the component-class-path
329

330             Element JavaDoc compoClassPath = (Element JavaDoc) element.getElementsByTagName(
331                 "component-class-path").item(0);
332             NodeList JavaDoc compoElems = compoClassPath
333                 .getElementsByTagName("path-element");
334             Set JavaDoc<String JavaDoc> elemsToAdd = cloneSet(entries);
335             for (int i = 0; i < compoElems.getLength(); i++) {
336                 Element JavaDoc elem = (Element JavaDoc) compoElems.item(i);
337                 if (entries.contains(elem.getTextContent())) {
338                     elemsToAdd.remove(elem.getTextContent());
339                 }
340             }
341             if (elemsToAdd.size() > 0) {
342                 // We need to add the missing elements
343
for (String JavaDoc jar : elemsToAdd) {
344                     Element JavaDoc elem = document.createElement("path-element");
345                     elem.setTextContent(jar);
346                     compoClassPath.appendChild(elem);
347                 }
348             }
349             // add the main component-jar in the component-class-path
350
Element JavaDoc mainElem = document.createElement("path-element");
351             mainElem.setTextContent(componentJar.getName());
352             compoClassPath.appendChild(mainElem);
353             
354             // Check the bootstrap-class-path
355

356             Element JavaDoc bootClassPath = (Element JavaDoc) element.getElementsByTagName(
357                 "bootstrap-class-path").item(0);
358             NodeList JavaDoc bootElems = bootClassPath
359                 .getElementsByTagName("path-element");
360             elemsToAdd = cloneSet(entries);
361             for (int i = 0; i < bootElems.getLength(); i++) {
362                 Element JavaDoc elem = (Element JavaDoc) bootElems.item(i);
363                 if (elemsToAdd.contains(elem.getTextContent())) {
364                     elemsToAdd.remove(elem.getTextContent());
365                 }
366             }
367             if (elemsToAdd.size() > 0) {
368                 // We need to add the missing elements
369
for (String JavaDoc jar : elemsToAdd) {
370                     Element JavaDoc elem = document.createElement("path-element");
371                     elem.setTextContent(jar);
372                     bootClassPath.appendChild(elem);
373                 }
374             }
375             // add the main component-jar in the bootstrap-class-path
376
mainElem = document.createElement("path-element");
377             mainElem.setTextContent(componentJar.getName());
378             bootClassPath.appendChild(mainElem);
379             
380
381             document.normalize();
382             Source JavaDoc source = new DOMSource JavaDoc(document);
383             StringWriter JavaDoc out = new StringWriter JavaDoc();
384             Result JavaDoc resultStream = new StreamResult JavaDoc(out);
385             TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
386             Transformer JavaDoc transformer;
387             transformer = tFactory.newTransformer();
388             transformer.transform(source, resultStream);
389
390             inputStream = new ByteArrayInputStream JavaDoc(out.toString().getBytes());
391
392         } catch (Exception JavaDoc e) {
393             if (verbose) {
394                 System.out
395                     .println("Problem while updating jbi.xml file. We add it like it is");
396             }
397             inputStream = new FileInputStream JavaDoc(new File JavaDoc(jbiDirectory
398                 + File.separator + "jbi.xml"));
399         }
400
401         // Add the jbi.xml entry
402
try {
403             ZipEntry JavaDoc zipEntry = new ZipEntry JavaDoc("META-INF/jbi.xml");
404             DataInputStream JavaDoc dis = new DataInputStream JavaDoc(inputStream);
405             byte[] content = new byte[dis.available()];
406             dis.readFully(content);
407             zipOutputStream.putNextEntry(zipEntry);
408             zipOutputStream.write(content);
409             zipOutputStream.closeEntry();
410         } catch (Exception JavaDoc e) {
411             if (verbose) {
412                 System.out.println("Fail to add jbi.xml file");
413             }
414         }
415     }
416
417     /**
418      * Recurse the dependencies of a dependencies to add them to the component
419      * archive
420      *
421      * @param dependency
422      */

423     private void recurseDepencies(ZipOutputStream JavaDoc zipOutputStream,
424         Dependency dependency) throws Exception JavaDoc {
425
426         MavenEmbedder maven = new MavenEmbedder();
427         ClassLoader JavaDoc classLoader = Thread.currentThread()
428             .getContextClassLoader();
429         maven.setClassLoader(classLoader);
430         maven.setLogger(null);
431         maven.start();
432
433         String JavaDoc pomName = dependency.getArtifactId()
434             + "-" + dependency.getVersion() + ".pom";
435
436         File JavaDoc pomFile = new File JavaDoc(localRepository.getBasedir()
437             + File.separator
438             + dependency.getGroupId().replace(".", File.separator)
439             + File.separator + dependency.getArtifactId() + File.separator
440             + dependency.getVersion() + File.separator + pomName);
441         if (pomFile.exists()) {
442             MavenProject project = null;
443             try {
444                 project = maven.readProject(pomFile);
445             } catch (Exception JavaDoc e) {
446                 String JavaDoc jarName=null;
447                 try {
448                     jarName = localRepository.getBasedir()
449                     + File.separator
450                     + dependency.getGroupId().replace(".", File.separator)
451                     + File.separator + dependency.getArtifactId()
452                     + File.separator + dependency.getVersion() + File.separator
453                     + dependency.getArtifactId() + "-"
454                     + dependency.getVersion() + ".jar";
455                     
456                     JarFile JavaDoc jarFile = new JarFile JavaDoc(jarName);
457                     String JavaDoc pomEntryName = "META-INF/maven/"
458                         + dependency.getGroupId() + "/"
459                         + dependency.getArtifactId() + "/pom.xml";
460                     ZipEntry JavaDoc jarEntry = jarFile.getEntry(pomEntryName);
461                     if (jarEntry != null) {
462                         // Copy pom.xml file
463
File JavaDoc tmpFile = new File JavaDoc(outputDirectory
464                             + File.separator + "temp.xml");
465                         copyStreamToFile(jarFile.getInputStream(jarEntry), tmpFile);
466                         project = maven.readProject(tmpFile);
467                         FileUtils.forceDelete(tmpFile);
468                     }
469                 } catch (ZipException JavaDoc e1) {
470                     if (verbose) {
471                         System.out.println("Problem while adding "
472                             + jarName + " to JBI archive");
473                     }
474                 }
475             }
476             if (project != null) {
477                 includeProject(zipOutputStream, project);
478             }
479         }
480     }
481
482     /**
483      * Include a project dependencies to the archive
484      *
485      * @param zipOutputStream
486      * @param project
487      * @throws Exception
488      */

489     private void includeProject(ZipOutputStream JavaDoc zipOutputStream,
490         MavenProject project) throws Exception JavaDoc {
491
492         for (Object JavaDoc object : project.getDependencies()) {
493             if (object instanceof Dependency) {
494                 Dependency dep = (Dependency) object;
495                 String JavaDoc jarName = dep.getArtifactId()
496                     + "-" + dep.getVersion() + ".jar";
497
498                 String JavaDoc scope = "test";
499                 if (dep.getScope() == null
500                     || (dep.getScope() != null && !dep.getScope()
501                         .equals("test"))) {
502                     scope = "other";
503                 }
504                 if (!"test".equals(scope)
505                     && !entriesToExclude.contains(jarName)) {
506
507                     // Add the dep to the zip
508
zipDependency(zipOutputStream, dep);
509                     // Recurse the dep
510
recurseDepencies(zipOutputStream, dep);
511                 }
512             }
513         }
514     }
515
516     /**
517      * Copy a stream to a file
518      *
519      * @param inputStream
520      * @param tmpFile
521      * @throws Exception
522      */

523     private void copyStreamToFile(InputStream JavaDoc inputStream, File JavaDoc tmpFile)
524         throws Exception JavaDoc {
525         ReadableByteChannel JavaDoc inputChannel = Channels.newChannel(inputStream);
526         FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(tmpFile);
527         FileChannel JavaDoc outputChannel = fos.getChannel();
528         ByteBuffer JavaDoc buffer = ByteBuffer.allocate(4096);
529         int readBytes;
530         while ((readBytes = inputChannel.read(buffer)) != -1) {
531             if (readBytes > 0) {
532                 buffer.flip();
533                 outputChannel.write(buffer);
534                 buffer.clear();
535             }
536         }
537         inputChannel.close();
538         outputChannel.close();
539         fos.close();
540     }
541
542     /**
543      * Add a dependency to a zip stream
544      *
545      * @param zipOutputStream
546      * @param dependency
547      */

548     private void zipDependency(ZipOutputStream JavaDoc zipOutputStream,
549         Dependency dependency) {
550         String JavaDoc jarName = dependency.getArtifactId()
551             + "-" + dependency.getVersion() + ".jar";
552         try {
553             if (!entries.contains(jarName)) {
554                 ZipEntry JavaDoc zipEntry = new ZipEntry JavaDoc(jarName);
555                 DataInputStream JavaDoc dis = new DataInputStream JavaDoc(new FileInputStream JavaDoc(
556                     new File JavaDoc(localRepository.getBasedir()
557                         + File.separator
558                         + dependency.getGroupId().replace(".", File.separator)
559                         + File.separator + dependency.getArtifactId()
560                         + File.separator + dependency.getVersion()
561                         + File.separator + jarName)));
562                 byte[] content = new byte[dis.available()];
563                 dis.readFully(content);
564                 zipOutputStream.putNextEntry(zipEntry);
565                 zipOutputStream.write(content);
566                 zipOutputStream.closeEntry();
567                 entries.add(jarName);
568                 if (verbose) {
569                     System.out.println(" "
570                         + jarName + " added to JBI archive");
571                 }
572             }
573         } catch (Exception JavaDoc e) {
574             entriesToExclude.add(jarName);
575             if (verbose) {
576                 System.out.println("Problem while adding "
577                     + jarName + " to JBI archive");
578             }
579         }
580     }
581 }
582
Popular Tags