View Javadoc

1   package org.apache.maven.plugins.shade.resource;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.OutputStream;
27  import java.io.Reader;
28  import java.io.Writer;
29  import java.util.Iterator;
30  import java.util.LinkedHashMap;
31  import java.util.Map;
32  import java.util.jar.JarEntry;
33  import java.util.jar.JarOutputStream;
34  
35  import org.codehaus.plexus.util.IOUtil;
36  import org.codehaus.plexus.util.ReaderFactory;
37  import org.codehaus.plexus.util.WriterFactory;
38  import org.codehaus.plexus.util.xml.Xpp3Dom;
39  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
40  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
41  
42  /**
43   * A resource processor that aggregates plexus <code>components.xml</code> files.
44   * 
45   */
46  public class ComponentsXmlResourceTransformer
47      implements ResourceTransformer
48  {
49      private Map components = new LinkedHashMap();
50  
51      public static final String COMPONENTS_XML_PATH = "META-INF/plexus/components.xml";
52  
53      public boolean canTransformResource( String resource )
54      {
55          return COMPONENTS_XML_PATH.equals( resource );
56      }
57  
58      public void processResource( InputStream is )
59          throws IOException
60      {
61          // We can't just read the stream because the plexus dom builder closes the stream
62  
63          File f = File.createTempFile( "maven-shade-plugin", "tmp" );
64  
65          f.deleteOnExit();
66  
67          OutputStream os = new FileOutputStream( f );
68  
69          IOUtil.copy( is, os );
70  
71          os.close();
72  
73          //
74  
75          Reader reader;
76  
77          Xpp3Dom newDom;
78  
79          try
80          {
81              reader = ReaderFactory.newXmlReader( f );
82  
83              newDom = Xpp3DomBuilder.build( reader );
84          }
85          catch ( Exception e )
86          {
87              throw new IOException( "Error parsing components.xml in " + is );
88          }
89  
90          // Only try to merge in components if there are some elements in the component-set
91          if ( newDom.getChild( "components" ) == null )
92          {
93              return;
94          }
95  
96          Xpp3Dom[] children = newDom.getChild( "components" ).getChildren( "component" );
97  
98          for ( int i = 0; i < children.length; i++ )
99          {
100             Xpp3Dom component = children[i];
101 
102             String role = component.getChild( "role" ).getValue();
103 
104             Xpp3Dom child = component.getChild( "role-hint" );
105 
106             String roleHint = child != null ? child.getValue() : "";
107 
108             String key = role + roleHint;
109             if ( components.containsKey( key ) )
110             {
111                 // TODO: use the tools in Plexus to merge these properly. For now, I just need an all-or-nothing
112                 // configuration carry over
113 
114                 Xpp3Dom dom = (Xpp3Dom) components.get( key );
115                 if ( dom.getChild( "configuration" ) != null )
116                 {
117                     component.addChild( dom.getChild( "configuration" ) );
118                 }
119             }
120 
121             components.put( key, component );
122         }
123     }
124 
125     public void modifyOutputStream( JarOutputStream jos )
126         throws IOException
127     {
128         Reader reader = ReaderFactory.newXmlReader( getTransformedResource() );
129 
130         jos.putNextEntry( new JarEntry( COMPONENTS_XML_PATH ) );
131 
132         IOUtil.copy( reader, jos );
133 
134         reader.close();
135 
136         components.clear();
137     }
138 
139     public boolean hasTransformedResource()
140     {
141         return components.size() > 0;
142     }
143 
144     public File getTransformedResource()
145         throws IOException
146     {
147         File f = File.createTempFile( "shade-maven-plugin-plx", "tmp" );
148 
149         f.deleteOnExit();
150 
151         Writer writer = WriterFactory.newXmlWriter( f );
152         try
153         {
154             Xpp3Dom dom = new Xpp3Dom( "component-set" );
155 
156             Xpp3Dom componentDom = new Xpp3Dom( "components" );
157 
158             dom.addChild( componentDom );
159 
160             for ( Iterator i = components.values().iterator(); i.hasNext(); )
161             {
162                 Xpp3Dom component = (Xpp3Dom) i.next();
163                 componentDom.addChild( component );
164             }
165 
166             Xpp3DomWriter.write( writer, dom );
167         }
168         finally
169         {
170             IOUtil.close( writer );
171         }
172 
173         return f;
174     }
175 
176 
177 }