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 org.apache.maven.plugins.shade.relocation.Relocator;
23  import org.codehaus.plexus.util.IOUtil;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.ByteArrayOutputStream;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.jar.JarEntry;
33  import java.util.jar.JarOutputStream;
34  
35  /**
36   * Resources transformer that appends entries in META-INF/services resources into
37   * a single resource. For example, if there are several META-INF/services/org.apache.maven.project.ProjectBuilder
38   * resources spread across many JARs the individual entries will all be concatenated into a single
39   * META-INF/services/org.apache.maven.project.ProjectBuilder resource packaged into the resultant JAR produced
40   * by the shading process.
41   *
42   * @author jvanzyl
43   */
44  public class ServicesResourceTransformer
45      implements ResourceTransformer
46  {
47  
48      private static final String SERVICES_PATH = "META-INF/services";
49  
50      private Map<String, ServiceStream> serviceEntries = new HashMap<String, ServiceStream>();
51  
52      public boolean canTransformResource( String resource )
53      {
54          if ( resource.startsWith( SERVICES_PATH ) )
55          {
56              return true;
57          }
58  
59          return false;
60      }
61  
62      public void processResource( String resource, InputStream is, List<Relocator> relocators )
63          throws IOException
64      {
65          ServiceStream out = serviceEntries.get( resource );
66          if ( out == null )
67          {
68              out = new ServiceStream();
69              serviceEntries.put( resource, out );
70          }
71  
72          out.append( is );
73          is.close();
74      }
75  
76      public boolean hasTransformedResource()
77      {
78          return serviceEntries.size() > 0;
79      }
80  
81      public void modifyOutputStream( JarOutputStream jos )
82          throws IOException
83      {
84          for ( Map.Entry<String, ServiceStream> entry : serviceEntries.entrySet() )
85          {
86              String key = entry.getKey();
87              ServiceStream data = entry.getValue();
88  
89              jos.putNextEntry( new JarEntry( key ) );
90              IOUtil.copy( data.toInputStream(), jos );
91              data.reset();
92          }
93      }
94  
95      static class ServiceStream
96          extends ByteArrayOutputStream
97      {
98  
99          public ServiceStream()
100         {
101             super( 1024 );
102         }
103 
104         public void append( InputStream is )
105             throws IOException
106         {
107             if ( count > 0 && buf[count - 1] != '\n' && buf[count - 1] != '\r' )
108             {
109                 write( '\n' );
110             }
111 
112             IOUtil.copy( is, this );
113         }
114 
115         public InputStream toInputStream()
116         {
117             return new ByteArrayInputStream( buf, 0, count );
118         }
119 
120     }
121 
122 }