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.BufferedReader;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.InputStreamReader;
26  import java.io.OutputStreamWriter;
27  import java.io.PrintWriter;
28  import java.io.Writer;
29  import java.text.SimpleDateFormat;
30  import java.util.Date;
31  import java.util.Iterator;
32  import java.util.LinkedHashMap;
33  import java.util.LinkedHashSet;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Set;
37  import java.util.TreeSet;
38  import java.util.jar.JarEntry;
39  import java.util.jar.JarOutputStream;
40  
41  import org.codehaus.plexus.util.StringUtils;
42  
43  /**
44   * Merges <code>META-INF/NOTICE.TXT</code> files.
45   */
46  public class ApacheNoticeResourceTransformer
47      implements ResourceTransformer
48  {
49      Set entries = new LinkedHashSet();
50      Map organizationEntries = new LinkedHashMap();
51  
52      String projectName = ""; // MSHADE-101 :: NullPointerException when projectName is missing
53      boolean addHeader = true;
54  
55      String preamble1 =
56            "// ------------------------------------------------------------------\n"
57          + "// NOTICE file corresponding to the section 4d of The Apache License,\n"
58          + "// Version 2.0, in this case for ";
59  
60      String preamble2 = "\n// ------------------------------------------------------------------\n";
61  
62      String preamble3 = "This product includes software developed at\n";
63  
64      //defaults overridable via config in pom
65      String organizationName = "The Apache Software Foundation";
66      String organizationURL = "http://www.apache.org/";
67      String inceptionYear = "2006";
68  
69      String copyright;
70  
71      /**
72       * The file encoding of the <code>NOTICE</code> file.
73       */
74      String encoding;
75  
76      private static final String NOTICE_PATH = "META-INF/NOTICE";
77  
78      private static final String NOTICE_TXT_PATH = "META-INF/NOTICE.txt";
79  
80      public boolean canTransformResource( String resource )
81      {
82          if ( NOTICE_PATH.equalsIgnoreCase( resource ) || NOTICE_TXT_PATH.equalsIgnoreCase( resource ) )
83          {
84              return true;
85          }
86  
87          return false;
88      }
89  
90      public void processResource( String resource, InputStream is, List relocators )
91          throws IOException
92      {
93          if ( entries.isEmpty() )
94          {
95              String year = new SimpleDateFormat( "yyyy" ).format( new Date() );
96              if ( !inceptionYear.equals( year ) )
97              {
98                  year = inceptionYear + "-" + year;
99              }
100 
101 
102             //add headers
103             if ( addHeader ) 
104             {
105                 entries.add( preamble1 + projectName + preamble2 );
106             }
107             else
108             {
109                 entries.add( "" );
110             }
111             //fake second entry, we'll look for a real one later
112             entries.add( projectName + "\nCopyright " + year + " " + organizationName + "\n" );
113             entries.add( preamble3 + organizationName + " (" + organizationURL + ").\n" );
114         }
115 
116 
117         BufferedReader reader;
118         if ( StringUtils.isNotEmpty( encoding ) )
119         {
120             reader = new BufferedReader( new InputStreamReader( is, encoding ) );
121         }
122         else
123         {
124             reader = new BufferedReader( new InputStreamReader( is ) );
125         }
126 
127         String line = reader.readLine();
128         StringBuffer sb = new StringBuffer();
129         Set currentOrg = null;
130         int lineCount = 0;
131         while ( line != null )
132         {
133             String trimedLine = line.trim();
134 
135             if ( !trimedLine.startsWith( "//" ) )
136             {
137                 if ( trimedLine.length() > 0 )
138                 {
139                     if ( trimedLine.startsWith( "- " ) )
140                     {
141                         //resource-bundle 1.3 mode
142                         if ( lineCount == 1
143                             && sb.toString().indexOf( "This product includes/uses software(s) developed by" ) != -1 )
144                         {
145                             currentOrg = (Set) organizationEntries.get( sb.toString().trim() );
146                             if ( currentOrg == null )
147                             {
148                                 currentOrg = new TreeSet();
149                                 organizationEntries.put( sb.toString().trim(), currentOrg );
150                             }
151                             sb = new StringBuffer();
152                         }
153                         else if ( sb.length() > 0 && currentOrg != null )
154                         {
155                             currentOrg.add( sb.toString() );
156                             sb = new StringBuffer();
157                         }
158 
159                     }
160                     sb.append( line ).append( "\n" );
161                     lineCount++;
162                 }
163                 else
164                 {
165                     String ent = sb.toString();
166                     if ( ent.startsWith( projectName )
167                         && ent.indexOf( "Copyright " ) != -1 )
168                     {
169                         copyright = ent;
170                     }
171                     if ( currentOrg == null )
172                     {
173                         entries.add( ent );
174                     }
175                     else
176                     {
177                         currentOrg.add( ent );
178                     }
179                     sb = new StringBuffer();
180                     lineCount = 0;
181                     currentOrg = null;
182                 }
183             }
184 
185             line = reader.readLine();
186         }
187         if ( sb.length() > 0 ) 
188         {
189             if ( currentOrg == null )
190             {
191                 entries.add( sb.toString() );
192             }
193             else
194             {
195                 currentOrg.add( sb.toString() );
196             }
197         }
198     }
199 
200     public boolean hasTransformedResource()
201     {
202         return true;
203     }
204 
205     public void modifyOutputStream( JarOutputStream jos )
206         throws IOException
207     {
208         jos.putNextEntry( new JarEntry( NOTICE_PATH ) );
209 
210         Writer pow;
211         if ( StringUtils.isNotEmpty( encoding ) )
212         {
213             pow = new OutputStreamWriter( jos, encoding );
214         }
215         else
216         {
217             pow = new OutputStreamWriter( jos );
218         }
219         PrintWriter writer = new PrintWriter( pow );
220 
221         int count = 0;
222         for ( Iterator itr = entries.iterator() ; itr.hasNext() ; )
223         {
224             ++count;
225             String line = (String) itr.next();
226             if ( line.equals( copyright ) && count != 2 )
227             {
228                 continue;
229             }
230 
231             if ( count == 2 && copyright != null )
232             {
233                 writer.print( copyright );
234                 writer.print( '\n' );
235             }
236             else
237             {
238                 writer.print( line );
239                 writer.print( '\n' );
240             }
241             if ( count == 3 )
242             {
243                 //do org stuff
244                 for ( Iterator oit = organizationEntries.entrySet().iterator(); oit.hasNext(); )
245                 {
246                     Map.Entry entry = (Map.Entry) oit.next();
247                     writer.print( entry.getKey().toString() );
248                     writer.print( '\n' );
249                     Set entrySet = (Set) entry.getValue();
250                     for ( Iterator eit = entrySet.iterator(); eit.hasNext(); )
251                     {
252                         writer.print( eit.next().toString() );
253                     }
254                     writer.print( '\n' );
255                 }
256             }
257         }
258 
259         writer.flush();
260 
261         entries.clear();
262     }
263 }