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  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Properties;
32  import java.util.jar.JarEntry;
33  import java.util.jar.JarOutputStream;
34  
35  /**
36   * Aggregate Apache Groovy extension modules descriptors
37   */
38  public class GroovyResourceTransformer
39      extends AbstractCompatibilityTransformer
40  {
41  
42      static final String EXT_MODULE_NAME_LEGACY = "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule";
43  
44      // Since Groovy 2.5.x/Java 9 META-INF/services may only be used by Service Providers
45      static final String EXT_MODULE_NAME = "META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule";
46  
47      private List<String> extensionClassesList = new ArrayList<>();
48  
49      private List<String> staticExtensionClassesList = new ArrayList<>();
50  
51      private String extModuleName = "no-module-name";
52  
53      private String extModuleVersion = "1.0";
54  
55      private long time = Long.MIN_VALUE;
56  
57      @Override
58      public boolean canTransformResource( String resource )
59      {
60          return EXT_MODULE_NAME.equals( resource ) || EXT_MODULE_NAME_LEGACY.equals( resource );
61      }
62  
63      @Override
64      public void processResource( String resource, InputStream is, List<Relocator> relocators, long time )
65          throws IOException
66      {
67          Properties out = new Properties();
68          try ( InputStream props = is )
69          {
70              out.load( props );
71          }
72          String extensionClasses = out.getProperty( "extensionClasses", "" ).trim();
73          if ( extensionClasses.length() > 0 )
74          {
75              append( extensionClasses, extensionClassesList );
76          }
77          String staticExtensionClasses = out.getProperty( "staticExtensionClasses", "" ).trim();
78          if ( staticExtensionClasses.length() > 0 )
79          {
80              append( staticExtensionClasses, staticExtensionClassesList );
81          }
82          if ( time > this.time )
83          {
84              this.time = time;        
85          }
86      }
87  
88      private void append( String entry, List<String> list )
89      {
90          if ( entry != null )
91          {
92              Collections.addAll( list, entry.split( "\\s*,\\s*" ) );
93          }
94      }
95  
96      @Override
97      public boolean hasTransformedResource()
98      {
99          return extensionClassesList.size() > 0 && staticExtensionClassesList.size() > 0;
100     }
101 
102     @Override
103     public void modifyOutputStream( JarOutputStream os )
104         throws IOException
105     {
106         if ( hasTransformedResource() )
107         {
108             JarEntry jarEntry = new JarEntry( EXT_MODULE_NAME );
109             jarEntry.setTime( time );
110             os.putNextEntry( jarEntry );
111 
112             Properties desc = new Properties();
113             desc.put( "moduleName", extModuleName );
114             desc.put( "moduleVersion", extModuleVersion );
115             if ( extensionClassesList.size() > 0 )
116             {
117                 desc.put( "extensionClasses", join( extensionClassesList ) );
118             }
119             if ( staticExtensionClassesList.size() > 0 )
120             {
121                 desc.put( "staticExtensionClasses", join( staticExtensionClassesList ) );
122             }
123             desc.store( os, null );
124         }
125     }
126 
127     private String join( Collection<String> strings )
128     {
129         Iterator<String> it = strings.iterator();
130         switch ( strings.size() )
131         {
132             case 0:
133                 return "";
134             case 1:
135                 return it.next();
136             default:
137                 StringBuilder buff = new StringBuilder( it.next() );
138                 while ( it.hasNext() )
139                 {
140                     buff.append( "," ).append( it.next() );
141                 }
142                 return buff.toString();
143         }
144     }
145 
146     public void setExtModuleName( String extModuleName )
147     {
148         this.extModuleName = extModuleName;
149     }
150 
151     public void setExtModuleVersion( String extModuleVersion )
152     {
153         this.extModuleVersion = extModuleVersion;
154     }
155 }