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.LinkedHashMap;
35 import java.util.LinkedHashSet;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.TreeSet;
40 import java.util.jar.JarEntry;
41 import java.util.jar.JarOutputStream;
42
43
44
45
46 public class ApacheNoticeResourceTransformer
47 implements ResourceTransformer
48 {
49 Set<String> entries = new LinkedHashSet<String>();
50
51 Map<String, Set<String>> organizationEntries = new LinkedHashMap<String, Set<String>>();
52
53 String projectName = "";
54
55 boolean addHeader = true;
56
57 String preamble1 = "// ------------------------------------------------------------------\n"
58 + "// NOTICE file corresponding to the section 4d of The Apache License,\n"
59 + "// Version 2.0, in this case for ";
60
61 String preamble2 = "\n// ------------------------------------------------------------------\n";
62
63 String preamble3 = "This product includes software developed at\n";
64
65
66 String organizationName = "The Apache Software Foundation";
67
68 String organizationURL = "http://www.apache.org/";
69
70 String inceptionYear = "2006";
71
72 String copyright;
73
74
75
76
77 String encoding;
78
79 private static final String NOTICE_PATH = "META-INF/NOTICE";
80
81 private static final String NOTICE_TXT_PATH = "META-INF/NOTICE.txt";
82
83 public boolean canTransformResource( String resource )
84 {
85 if ( NOTICE_PATH.equalsIgnoreCase( resource ) || NOTICE_TXT_PATH.equalsIgnoreCase( resource ) )
86 {
87 return true;
88 }
89
90 return false;
91 }
92
93 public void processResource( String resource, InputStream is, List<Relocator> relocators )
94 throws IOException
95 {
96 if ( entries.isEmpty() )
97 {
98 String year = new SimpleDateFormat( "yyyy" ).format( new Date() );
99 if ( !inceptionYear.equals( year ) )
100 {
101 year = inceptionYear + "-" + year;
102 }
103
104
105 if ( addHeader )
106 {
107 entries.add( preamble1 + projectName + preamble2 );
108 }
109 else
110 {
111 entries.add( "" );
112 }
113
114 entries.add( projectName + "\nCopyright " + year + " " + organizationName + "\n" );
115 entries.add( preamble3 + organizationName + " (" + organizationURL + ").\n" );
116 }
117
118 BufferedReader reader;
119 if ( StringUtils.isNotEmpty( encoding ) )
120 {
121 reader = new BufferedReader( new InputStreamReader( is, encoding ) );
122 }
123 else
124 {
125 reader = new BufferedReader( new InputStreamReader( is ) );
126 }
127
128 String line = reader.readLine();
129 StringBuffer sb = new StringBuffer();
130 Set<String> currentOrg = null;
131 int lineCount = 0;
132 while ( line != null )
133 {
134 String trimedLine = line.trim();
135
136 if ( !trimedLine.startsWith( "//" ) )
137 {
138 if ( trimedLine.length() > 0 )
139 {
140 if ( trimedLine.startsWith( "- " ) )
141 {
142
143 if ( lineCount == 1
144 && sb.toString().indexOf( "This product includes/uses software(s) developed by" ) != -1 )
145 {
146 currentOrg = organizationEntries.get( sb.toString().trim() );
147 if ( currentOrg == null )
148 {
149 currentOrg = new TreeSet<String>();
150 organizationEntries.put( sb.toString().trim(), currentOrg );
151 }
152 sb = new StringBuffer();
153 }
154 else if ( sb.length() > 0 && currentOrg != null )
155 {
156 currentOrg.add( sb.toString() );
157 sb = new StringBuffer();
158 }
159
160 }
161 sb.append( line ).append( "\n" );
162 lineCount++;
163 }
164 else
165 {
166 String ent = sb.toString();
167 if ( ent.startsWith( projectName ) && 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 ( String line : entries )
223 {
224 ++count;
225 if ( line.equals( copyright ) && count != 2 )
226 {
227 continue;
228 }
229
230 if ( count == 2 && copyright != null )
231 {
232 writer.print( copyright );
233 writer.print( '\n' );
234 }
235 else
236 {
237 writer.print( line );
238 writer.print( '\n' );
239 }
240 if ( count == 3 )
241 {
242
243 for ( Map.Entry<String, Set<String>> entry : organizationEntries.entrySet() )
244 {
245 writer.print( entry.getKey() );
246 writer.print( '\n' );
247 for ( String l : entry.getValue() )
248 {
249 writer.print( l );
250 }
251 writer.print( '\n' );
252 }
253 }
254 }
255
256 writer.flush();
257
258 entries.clear();
259 }
260 }