View Javadoc

1   /*
2    *  jDTAUS Core Container Mojo
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.core.container.mojo;
22  
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.jar.JarEntry;
31  import java.util.jar.JarOutputStream;
32  import javax.xml.bind.JAXBException;
33  import org.apache.maven.plugins.shade.resource.ResourceTransformer;
34  import org.jdtaus.core.container.ContainerError;
35  import org.jdtaus.core.container.ContextError;
36  import org.jdtaus.core.container.MissingModuleException;
37  import org.jdtaus.core.container.Model;
38  import org.jdtaus.core.container.ModelError;
39  import org.jdtaus.core.container.ModelFactory;
40  import org.jdtaus.core.container.mojo.model.ModelManager;
41  import org.jdtaus.core.container.mojo.model.container.Implementation;
42  import org.jdtaus.core.container.mojo.model.container.Message;
43  import org.jdtaus.core.container.mojo.model.container.MessageReference;
44  import org.jdtaus.core.container.mojo.model.container.Messages;
45  import org.jdtaus.core.container.mojo.model.container.Module;
46  import org.jdtaus.core.container.mojo.model.container.Modules;
47  import org.jdtaus.core.container.mojo.model.container.ObjectFactory;
48  
49  /**
50   * {@code ResourceTransformer} implementation for use with the
51   * {@code maven-shade-plugin} for merging container models.
52   *
53   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
54   * @version $JDTAUS: ContainerResourceTransformer.java 8743 2012-10-07 03:06:20Z schulte $
55   *
56   * @see <a href="http://maven.apache.org/plugins/maven-shade-plugin/index.html">maven-shade-plugin</a>
57   * @plexus.component role="org.apache.maven.plugins.shade.resource.ResourceTransformer"
58   *                   role-hint="jDTAUS Container Transformer"
59   */
60  public class ContainerResourceTransformer implements ResourceTransformer
61  {
62  
63      /** Location to transform. */
64      private String location = "META-INF/jdtaus/module.xml";
65  
66      /**
67       * Name of the module to merge all modules in or {@code null} to not merge
68       * a single module.
69       */
70      private String mergeModule;
71  
72      /** Processed models. */
73      private Modules modules;
74  
75      /** @plexus.requirement */
76      private ModelManager modelManager = new ModelManager();
77  
78      /** Creates a new {@code ContainerResourceTransformer} instance. */
79      public ContainerResourceTransformer()
80      {
81          super();
82      }
83  
84      /**
85       * Gets the {@code ModelManager} instance.
86       *
87       * @return the {@code ModelManager} instance.
88       */
89      protected ModelManager getModelManager()
90      {
91          return this.modelManager;
92      }
93  
94      public boolean canTransformResource( final String resource )
95      {
96          return this.location.equals( resource );
97      }
98  
99      public void processResource( final InputStream in ) throws IOException
100     {
101         try
102         {
103             if ( this.modules == null )
104             {
105                 this.modules = new ObjectFactory().createModulesElement();
106                 this.modules.setModelVersion( "1.4" );
107             }
108 
109             final Object o = this.getModelManager().
110                 getContainerUnmarshaller().unmarshal( in );
111 
112             if ( o instanceof Module )
113             {
114                 this.modules.getModule().add( o );
115             }
116             else if ( o instanceof Modules )
117             {
118                 this.modules.getModule().
119                     addAll( ( (Modules) o ).getModule() );
120 
121             }
122         }
123         catch ( final JAXBException e )
124         {
125             final IOException ioe = new IOException( e.getMessage() );
126             ioe.initCause( e );
127             throw ioe;
128         }
129     }
130 
131     public void processResource( final String resource, final InputStream in,
132                                  final List relocations ) throws IOException
133     {
134         this.processResource( in );
135     }
136 
137     public boolean hasTransformedResource()
138     {
139         return this.modules != null && this.modules.getModule().size() > 0;
140     }
141 
142     public void modifyOutputStream( final JarOutputStream out )
143         throws IOException
144     {
145         final ClassLoader currentLoader =
146             Thread.currentThread().getContextClassLoader();
147 
148         try
149         {
150             final ResourceLoader resourceLoader =
151                 new ResourceLoader( this.getClass().getClassLoader() );
152 
153             for ( final Iterator it = this.modules.getModule().iterator();
154                   it.hasNext(); )
155             {
156                 final Module module = (Module) it.next();
157                 final File tmpFile =
158                     File.createTempFile( "jdtaus-container-mojo", ".xml" );
159 
160                 tmpFile.deleteOnExit();
161 
162                 final OutputStream s = new FileOutputStream( tmpFile );
163 
164                 this.getModelManager().getContainerMarshaller().
165                     marshal( module, s );
166 
167                 s.close();
168 
169                 resourceLoader.addResource( this.location,
170                                             tmpFile.toURI().toURL() );
171 
172             }
173 
174             Thread.currentThread().setContextClassLoader( resourceLoader );
175             AbstractContainerMojo.enableThreadContextClassLoader();
176             final Model model = ModelFactory.newModel();
177             AbstractContainerMojo.disableThreadContextClassLoader();
178 
179             final Modules linkedModules = this.getModelManager().
180                 getContainerModel( model.getModules() );
181 
182             out.putNextEntry( new JarEntry( this.location ) );
183 
184             if ( this.mergeModule != null )
185             {
186                 final Module mergedModule =
187                     this.findModule( linkedModules, this.mergeModule );
188 
189                 if ( mergedModule == null )
190                 {
191                     throw new MissingModuleException( this.mergeModule );
192                 }
193 
194                 for ( final Iterator it = linkedModules.getModule().iterator();
195                       it.hasNext(); )
196                 {
197                     final Module current = (Module) it.next();
198                     if ( !current.getName().equals( this.mergeModule ) )
199                     {
200                         // Ignore modules not introduced as a resource.
201                         if ( this.findModule( this.modules,
202                                               current.getName() ) != null )
203                         {
204                             this.mergeModule( mergedModule, current );
205                         }
206 
207                         it.remove();
208                     }
209                 }
210 
211                 this.getModelManager().getContainerMarshaller().
212                     marshal( mergedModule, out );
213 
214             }
215             else
216             {
217                 this.getModelManager().getContainerMarshaller().
218                     marshal( linkedModules, out );
219 
220             }
221 
222             this.modules = null;
223         }
224         catch ( final Exception e )
225         {
226             final IOException ioe = new IOException( e.getMessage() );
227             ioe.initCause( e );
228             throw ioe;
229         }
230         catch ( final ModelError e )
231         {
232             final IOException ioe = new IOException( e.getMessage() );
233             ioe.initCause( e );
234             throw ioe;
235         }
236         catch ( final ContextError e )
237         {
238             final IOException ioe = new IOException( e.getMessage() );
239             ioe.initCause( e );
240             throw ioe;
241         }
242         catch ( final ContainerError e )
243         {
244             final IOException ioe = new IOException( e.getMessage() );
245             ioe.initCause( e );
246             throw ioe;
247         }
248         finally
249         {
250             Thread.currentThread().setContextClassLoader( currentLoader );
251         }
252     }
253 
254     private Module findModule( final Modules modules, final String name )
255     {
256         Module module = null;
257 
258         for ( final Iterator it = modules.getModule().iterator();
259               it.hasNext(); )
260         {
261             final Module current = (Module) it.next();
262             if ( current.getName().equals( name ) )
263             {
264                 module = current;
265                 break;
266             }
267         }
268 
269         return module;
270     }
271 
272     private Message findMessage( final Messages messages, final String name )
273     {
274         Message message = null;
275 
276         for ( final Iterator it = messages.getMessage().iterator();
277               it.hasNext(); )
278         {
279             final Message current = (Message) it.next();
280             if ( current.getName().equals( name ) )
281             {
282                 message = current;
283                 break;
284             }
285         }
286 
287         return message;
288     }
289 
290     private void mergeModule( final Module mergedModule, final Module module )
291         throws JAXBException
292     {
293         final ObjectFactory f = new ObjectFactory();
294 
295         if ( module.getSpecifications() != null )
296         {
297             if ( mergedModule.getSpecifications() == null )
298             {
299                 mergedModule.setSpecifications( f.createSpecifications() );
300             }
301 
302             mergedModule.getSpecifications().getSpecification().
303                 addAll( module.getSpecifications().getSpecification() );
304 
305         }
306 
307         if ( module.getProperties() != null )
308         {
309             if ( mergedModule.getProperties() == null )
310             {
311                 mergedModule.setProperties( f.createProperties() );
312             }
313 
314             mergedModule.getProperties().getProperty().
315                 addAll( module.getProperties().getProperty() );
316 
317         }
318 
319         if ( module.getImplementations() != null )
320         {
321             if ( mergedModule.getImplementations() == null )
322             {
323                 mergedModule.setImplementations( f.createImplementations() );
324             }
325 
326             for ( final Iterator it = module.getImplementations().
327                 getImplementation().iterator(); it.hasNext(); )
328             {
329                 final Implementation impl = (Implementation) it.next();
330                 if ( impl.getMessages() != null )
331                 {
332                     for ( final Iterator m = impl.getMessages().getReference().
333                         iterator(); m.hasNext(); )
334                     {
335                         final MessageReference ref =
336                             (MessageReference) m.next();
337 
338                         final Message message =
339                             this.findMessage( module.getMessages(),
340                                               ref.getName() );
341 
342                         impl.getMessages().getMessage().add( message );
343 
344                         m.remove();
345                     }
346                 }
347             }
348 
349             mergedModule.getImplementations().getImplementation().
350                 addAll( module.getImplementations().getImplementation() );
351 
352         }
353 
354 //        if ( module.getMessages() != null )
355 //        {
356 //            if ( mergedModule.getMessages() == null )
357 //            {
358 //                mergedModule.setMessages( f.createMessages() );
359 //            }
360 //
361 //            for ( Iterator it = module.getMessages().getMessage().iterator();
362 //                  it.hasNext(); )
363 //            {
364 //                final Message current = (Message) it.next();
365 //                mergedModule.getMessages().getMessage().add( current );
366 //            }
367 //        }
368     }
369 
370 }