1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package net.sf.maventaglib;
25
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.lang.reflect.Method;
33 import java.lang.reflect.Modifier;
34 import java.text.MessageFormat;
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41
42 import javax.xml.parsers.DocumentBuilder;
43
44 import net.sf.maventaglib.util.XmlHelper;
45
46 import org.apache.commons.beanutils.PropertyUtils;
47 import org.apache.maven.plugin.AbstractMojo;
48 import org.apache.maven.plugin.MojoExecutionException;
49 import org.apache.maven.plugin.MojoFailureException;
50 import org.apache.maven.plugins.annotations.LifecyclePhase;
51 import org.apache.maven.plugins.annotations.Mojo;
52 import org.apache.maven.plugins.annotations.Parameter;
53 import org.codehaus.plexus.util.FileUtils;
54 import org.jdom2.input.DOMBuilder;
55 import org.jdom2.output.Format;
56 import org.jdom2.output.XMLOutputter;
57 import org.w3c.dom.Document;
58 import org.w3c.dom.Element;
59
60 import com.sun.tlddoc.tagfileparser.Attribute;
61 import com.sun.tlddoc.tagfileparser.Directive;
62 import com.sun.tlddoc.tagfileparser.javacc.ParseException;
63 import com.sun.tlddoc.tagfileparser.javacc.TagFile;
64
65
66
67
68
69
70
71 @Mojo(name="tldgenerate", defaultPhase=LifecyclePhase.GENERATE_RESOURCES)
72 public class TldGenerateMojo extends AbstractMojo
73 {
74
75
76
77
78 @Parameter(defaultValue="src/main/resources/META-INF/tags/")
79 private File tagDir;
80
81
82
83
84 @Parameter(defaultValue="${project.build.outputDirectory}/META-INF", required=true)
85 private File outputDir;
86
87
88
89
90 @Parameter(property="project.version", required=true)
91 private String version;
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 @Parameter
115 private List<Taglib> taglibs;
116
117
118
119
120 public void execute() throws MojoExecutionException, MojoFailureException
121 {
122 getLog().debug(MessageFormat.format(Messages.getString("Taglib.generating.tld"),
123 tagDir.getAbsolutePath() ));
124
125 try
126 {
127 generateTlds();
128 }
129 catch (IOException e)
130 {
131 throw new MojoExecutionException(e.getMessage(), e);
132 }
133
134 }
135
136
137
138
139
140 private void generateTlds() throws IOException, MojoExecutionException
141 {
142
143 List<Taglib> taglibsList = new ArrayList<Taglib>();
144
145 if (taglibs != null)
146 {
147 for (Taglib taglib : taglibs)
148 {
149
150
151 Taglib tlib = new Taglib();
152 try
153 {
154 PropertyUtils.copyProperties(tlib, taglib);
155 }
156 catch (Throwable e)
157 {
158 throw new MojoExecutionException(e.getMessage(), e);
159 }
160 taglibsList.add(tlib);
161 }
162 }
163
164 if (taglibsList == null || taglibsList.isEmpty())
165 {
166 taglibsList = new ArrayList<Taglib>();
167
168
169 if (tagDir.isDirectory())
170 {
171
172 List<File> tags = FileUtils.getFiles(tagDir, "**/*.tag", null);
173 tags.addAll(FileUtils.getFiles(tagDir, "**/*.tagx", null));
174
175 if (!tags.isEmpty())
176 {
177 Set<File> directories = new HashSet<File>();
178 for (File tag : tags)
179 {
180 directories.add(tag.getParentFile());
181 }
182
183 for (File dir : directories)
184 {
185 Taglib tlib = new Taglib();
186 tlib.setTagdir(dir);
187 tlib.setShortName(dir.getName());
188 tlib.setOutputname(dir.getName() + ".tld");
189 tlib.setUri(dir.getName());
190 tlib.setShortName("Tag library for tag file directory " + dir.getName());
191 taglibsList.add(tlib);
192 }
193 }
194 else
195 {
196 getLog().warn(MessageFormat.format(Messages.getString("Taglib.generating.notfound"),
197 tagDir.getAbsolutePath() ));
198 }
199 }
200 }
201
202 try
203 {
204 for (Taglib taglib : taglibsList)
205 {
206 doTaglib(taglib);
207 }
208 }
209 catch (Exception e)
210 {
211 throw new MojoExecutionException(e.getMessage(), e);
212 }
213 }
214
215
216
217
218
219
220
221 private void doTaglib(Taglib taglib) throws MojoExecutionException, FileNotFoundException, IOException
222 {
223 Document doc = getTLDDocument(taglib, XmlHelper.getDocumentBuilder());
224
225 if (taglib.getShortName() == null)
226 {
227 throw new MojoExecutionException("Missing \"shortName\" parameter for taglib " + taglib);
228 }
229
230 String tldName = taglib.getOutputname();
231 if (tldName == null)
232 {
233 tldName = taglib.getShortName() + ".tld";
234 }
235 if (!tldName.endsWith(".tld"))
236 {
237 tldName = tldName + ".tld";
238 }
239
240 File outputFile = new File(outputDir, tldName);
241 if (!(outputDir.mkdirs() || outputDir.isDirectory())) {
242 throw new IOException("Unable to create output directory " + outputDir.getAbsolutePath());
243 }
244
245 getLog().info(MessageFormat.format(Messages.getString("Taglib.generating.file"),
246 tldName, taglib.getShortName() ));
247
248 try (FileOutputStream fos = new FileOutputStream(outputFile))
249 {
250 XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
251 outputter.output(new DOMBuilder().build(doc), fos);
252 }
253 }
254
255 protected Document getTLDDocument(Taglib taglib, DocumentBuilder documentBuilder)
256
257 {
258 Document result = documentBuilder.newDocument();
259
260 Element taglibElement = createRootTaglibNode(result, taglib.getDescription(), taglib.getShortName(), taglib
261 .getUri());
262
263 if (taglib.getTagdir() != null && taglib.getTagdir().isDirectory())
264 {
265
266 String path = taglib.getTagdir().getAbsolutePath().replace(File.separatorChar, '/');
267 int index = path.indexOf("/META-INF/");
268 if (index != -1)
269 {
270 path = path.substring(index);
271 }
272 else
273 {
274 path = "unknown";
275 }
276 if (!path.endsWith("/"))
277 {
278 path += "/";
279 }
280
281 File[] files = taglib.getTagdir().listFiles();
282 if (files == null)
283 {
284 files = new File[0];
285 }
286 for (File tag : files)
287 {
288 if (!tag.isDirectory()
289 && (tag.getName().toLowerCase().endsWith(".tag") || tag.getName().toLowerCase().endsWith(".tagx")))
290 {
291 String tagName = tag.getName().substring(0, tag.getName().lastIndexOf('.'));
292 String tagPath = path + tag.getName();
293
294 Element tagFileElement = result.createElement("tag-file");
295 Element nameElement = result.createElement("name");
296 nameElement.appendChild(result.createTextNode(tagName));
297 tagFileElement.appendChild(nameElement);
298 Element pathElement = result.createElement("path");
299 pathElement.appendChild(result.createTextNode(tagPath));
300 tagFileElement.appendChild(pathElement);
301 taglibElement.appendChild(tagFileElement);
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319 try (InputStream is = new FileInputStream(tag))
320 {
321 TagFile tagFile = TagFile.parse(is);
322
323 for (Directive directive : tagFile.getDirectives())
324 {
325 if ("tag".equals(directive.getDirectiveName()))
326 {
327 for (Attribute attribute : directive.getAttributes())
328 {
329 if ("description".equals(attribute.getName())
330 || "display-name".equals(attribute.getName())
331 || "example".equals(attribute.getName()))
332 {
333 Element element = result.createElement(attribute.getName());
334 element.appendChild(result.createTextNode(attribute.getValue()));
335 tagFileElement.appendChild(element);
336 }
337
338 }
339
340 }
341
342 }
343
344 }
345 catch (IOException e)
346 {
347
348 e.printStackTrace();
349 }
350 catch (ParseException e)
351 {
352
353 e.printStackTrace();
354 }
355
356 }
357
358 }
359 }
360
361 Map<String, Integer> duplicateFunctions = new HashMap<String, Integer>();
362
363 if (taglib.getFunctionClasses() != null)
364 {
365 for (String functionClassString : taglib.getFunctionClasses())
366 {
367 Class<?> functionClass = null;
368 try
369 {
370 functionClass = Class.forName(functionClassString);
371
372 }
373 catch (Throwable e)
374 {
375 getLog().error(
376 "Unable to load function class "
377 + functionClassString
378 + ": "
379 + e.getClass().getName()
380 + " "
381 + e.getMessage(),
382 e);
383 continue;
384 }
385 Method[] declaredMethods = functionClass.getDeclaredMethods();
386
387 for (Method method : declaredMethods)
388 {
389 if (!Modifier.isStatic(method.getModifiers()) || !Modifier.isPublic(method.getModifiers()))
390 {
391
392 continue;
393 }
394
395 Element tagFileElement = result.createElement("function");
396
397 String functionName = method.getName();
398
399 if (duplicateFunctions.containsKey(functionName))
400 {
401 int currentNum = duplicateFunctions.get(functionName);
402 duplicateFunctions.put(functionName, currentNum + 1);
403 functionName = functionName + currentNum;
404 }
405 else
406 {
407 duplicateFunctions.put(functionName, 1);
408 }
409
410 Element nameElement = result.createElement("name");
411 nameElement.appendChild(result.createTextNode(functionName));
412 tagFileElement.appendChild(nameElement);
413
414 Element classElement = result.createElement("function-class");
415 classElement.appendChild(result.createTextNode(method.getDeclaringClass().getName()));
416 tagFileElement.appendChild(classElement);
417
418 StringBuffer parameterTypesString = new StringBuffer();
419 Class< ? >[] parameterTypes = method.getParameterTypes();
420
421 for (int p = 0; p < parameterTypes.length; p++)
422 {
423 Class< ? > param = parameterTypes[p];
424 parameterTypesString.append(nonPrimitiveName(param.getCanonicalName()));
425 if (parameterTypes.length - 1 > p)
426 {
427 parameterTypesString.append(", ");
428 }
429 }
430
431 Element signatureElement = result.createElement("function-signature");
432 signatureElement.appendChild(result.createTextNode(nonPrimitiveName(method
433 .getReturnType()
434 .getCanonicalName())
435 + " "
436 + method.getName()
437 + "("
438 + parameterTypesString.toString()
439 + ")"));
440 tagFileElement.appendChild(signatureElement);
441
442 taglibElement.appendChild(tagFileElement);
443
444 }
445
446 }
447 }
448
449 return result;
450 }
451
452 private String nonPrimitiveName(String string)
453 {
454 if ("int".equals(string))
455 {
456 return Integer.class.getName();
457 }
458 else if ("boolean".equals(string))
459 {
460 return Boolean.class.getName();
461 }
462 else if ("double".equals(string))
463 {
464 return Double.class.getName();
465 }
466 else if ("long".equals(string))
467 {
468 return Long.class.getName();
469 }
470 else if ("char".equals(string))
471 {
472 return Character.class.getName();
473 }
474
475 return string;
476 }
477
478 protected Element createRootTaglibNode(Document result, String description, String shortName, String uri)
479 {
480 Element taglibElement = result.createElementNS("http://java.sun.com/xml/ns/javaee", "taglib");
481 taglibElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://java.sun.com/xml/ns/javaee");
482 taglibElement.setAttributeNS(
483 "http://www.w3.org/2000/xmlns/",
484 "xmlns:xsi",
485 "http://www.w3.org/2001/XMLSchema-instance");
486 taglibElement.setAttributeNS(
487 "http://www.w3.org/2001/XMLSchema-instance",
488 "xsi:schemaLocation",
489 "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd");
490 taglibElement.setAttribute("version", "2.1");
491 result.appendChild(taglibElement);
492
493 Element descriptionElement = result.createElement("description");
494 descriptionElement.appendChild(result.createTextNode(description));
495 taglibElement.appendChild(descriptionElement);
496
497 Element tlibVersionElement = result.createElement("tlib-version");
498 tlibVersionElement.appendChild(result.createTextNode(version));
499 taglibElement.appendChild(tlibVersionElement);
500
501 Element shortNameElement = result.createElement("short-name");
502 shortNameElement.appendChild(result.createTextNode(shortName));
503 taglibElement.appendChild(shortNameElement);
504
505 Element uriElement = result.createElement("uri");
506 uriElement.appendChild(result.createTextNode(uri));
507 taglibElement.appendChild(uriElement);
508
509 return taglibElement;
510 }
511 }