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