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