1 package org.apache.maven.doxia.macro.snippet;
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.doxia.macro.AbstractMacro;
23 import org.apache.maven.doxia.macro.Macro;
24 import org.apache.maven.doxia.macro.MacroExecutionException;
25 import org.apache.maven.doxia.macro.MacroRequest;
26 import org.apache.maven.doxia.sink.Sink;
27 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
28 import org.codehaus.plexus.component.annotations.Component;
29 import org.codehaus.plexus.util.StringUtils;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.net.MalformedURLException;
34 import java.net.URL;
35 import java.util.HashMap;
36 import java.util.Map;
37
38
39
40
41 @Component( role = Macro.class, hint = "snippet" )
42 public class SnippetMacro
43 extends AbstractMacro
44 {
45
46
47
48 private static Map<String, String> cache = new HashMap<>();
49
50 private static final int HOUR = 60;
51
52
53
54
55 private long timeout = HOUR * HOUR * 1000;
56
57
58
59
60 private static Map<String, Long> timeCached = new HashMap<>();
61
62
63
64
65 private boolean debug = false;
66
67
68
69
70 private boolean ignoreDownloadError = true;
71
72
73 public void execute( Sink sink, MacroRequest request )
74 throws MacroExecutionException
75 {
76 String id = (String) request.getParameter( "id" );
77
78 String urlParam = (String) request.getParameter( "url" );
79
80 String fileParam = (String) request.getParameter( "file" );
81
82 String debugParam = (String) request.getParameter( "debug" );
83
84 if ( debugParam != null )
85 {
86 this.debug = Boolean.parseBoolean( debugParam );
87 }
88
89 String ignoreDownloadErrorParam = (String) request.getParameter( "ignoreDownloadError" );
90
91 if ( ignoreDownloadErrorParam != null )
92 {
93 this.ignoreDownloadError = Boolean.parseBoolean( ignoreDownloadErrorParam );
94 }
95
96 boolean verbatim = true;
97
98 String verbatimParam = (String) request.getParameter( "verbatim" );
99
100 if ( verbatimParam != null && !"".equals( verbatimParam ) )
101 {
102 verbatim = Boolean.valueOf( verbatimParam );
103 }
104
105 String encoding = (String) request.getParameter( "encoding" );
106
107 URL url;
108
109 if ( !StringUtils.isEmpty( urlParam ) )
110 {
111 try
112 {
113 url = new URL( urlParam );
114 }
115 catch ( MalformedURLException e )
116 {
117 throw new IllegalArgumentException( urlParam + " is a malformed URL" );
118 }
119 }
120 else if ( !StringUtils.isEmpty( fileParam ) )
121 {
122 File f = new File( fileParam );
123
124 if ( !f.isAbsolute() )
125 {
126 f = new File( request.getBasedir(), fileParam );
127 }
128
129 try
130 {
131 url = f.toURI().toURL();
132 }
133 catch ( MalformedURLException e )
134 {
135 throw new IllegalArgumentException( fileParam + " is a malformed URL" );
136 }
137 }
138 else
139 {
140 throw new IllegalArgumentException( "Either the 'url' or the 'file' param has to be given." );
141 }
142
143 StringBuffer snippet;
144
145 try
146 {
147 snippet = getSnippet( url, encoding, id );
148 }
149 catch ( IOException e )
150 {
151 throw new MacroExecutionException( "Error reading snippet", e );
152 }
153
154 if ( verbatim )
155 {
156 sink.verbatim( SinkEventAttributeSet.BOXED );
157
158 sink.text( snippet.toString() );
159
160 sink.verbatim_();
161 }
162 else
163 {
164 sink.rawText( snippet.toString() );
165 }
166 }
167
168
169
170
171
172
173
174
175
176
177 private StringBuffer getSnippet( URL url, String encoding, String id )
178 throws IOException
179 {
180 StringBuffer result;
181
182 String cachedSnippet = getCachedSnippet( url, id );
183
184 if ( cachedSnippet != null )
185 {
186 result = new StringBuffer( cachedSnippet );
187
188 if ( debug )
189 {
190 result.append( "(Served from cache)" );
191 }
192 }
193 else
194 {
195 try
196 {
197 result = new SnippetReader( url, encoding ).readSnippet( id );
198 cacheSnippet( url, id, result.toString() );
199 if ( debug )
200 {
201 result.append( "(Fetched from url, cache content " ).append( cache ).append( ")" );
202 }
203 }
204 catch ( IOException e )
205 {
206 if ( ignoreDownloadError )
207 {
208 getLog().debug( "IOException which reading " + url + ": " + e );
209 result =
210 new StringBuffer( "Error during retrieving content skip as ignoreDownloadError activated." );
211 }
212 else
213 {
214 throw e;
215 }
216 }
217 }
218 return result;
219 }
220
221
222
223
224
225
226
227
228 private String getCachedSnippet( URL url, String id )
229 {
230 if ( isCacheTimedout( url, id ) )
231 {
232 removeFromCache( url, id );
233 }
234 return cache.get( globalSnippetId( url, id ) );
235 }
236
237
238
239
240
241
242
243
244
245 boolean isCacheTimedout( URL url, String id )
246 {
247 return timeInCache( url, id ) >= timeout;
248 }
249
250
251
252
253
254
255
256
257 long timeInCache( URL url, String id )
258 {
259 return System.currentTimeMillis() - getTimeCached( url, id );
260 }
261
262
263
264
265
266
267
268
269 long getTimeCached( URL url, String id )
270 {
271 String globalId = globalSnippetId( url, id );
272
273 return timeCached.containsKey( globalId ) ? timeCached.get( globalId ) : 0;
274 }
275
276
277
278
279
280
281
282 private void removeFromCache( URL url, String id )
283 {
284 String globalId = globalSnippetId( url, id );
285
286 timeCached.remove( globalId );
287
288 cache.remove( globalId );
289 }
290
291
292
293
294
295
296
297
298
299 private String globalSnippetId( URL url, String id )
300 {
301 if ( StringUtils.isEmpty( id ) )
302 {
303 return url.toString();
304 }
305
306 return url + " " + id;
307 }
308
309
310
311
312
313
314
315
316 public void cacheSnippet( URL url, String id, String content )
317 {
318 cache.put( globalSnippetId( url, id ), content );
319
320 timeCached.put( globalSnippetId( url, id ), System.currentTimeMillis() );
321 }
322
323
324
325
326
327
328 public void setCacheTimeout( int time )
329 {
330 this.timeout = time;
331 }
332 }