1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.kathrynhuxtable.maven.plugins.imageGenerator;
21
22 import java.awt.Graphics;
23 import java.awt.image.BufferedImage;
24
25 import java.io.BufferedReader;
26 import java.io.BufferedWriter;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.FileNotFoundException;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34
35 import java.lang.reflect.Constructor;
36
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41
42 import javax.imageio.ImageIO;
43
44 import javax.swing.JComponent;
45 import javax.swing.JPanel;
46 import javax.swing.UIManager;
47
48 import javax.xml.parsers.DocumentBuilder;
49 import javax.xml.parsers.DocumentBuilderFactory;
50
51 import org.apache.maven.plugin.AbstractMojo;
52 import org.apache.maven.plugin.MojoExecutionException;
53
54 import org.w3c.dom.Document;
55 import org.w3c.dom.Element;
56 import org.w3c.dom.Node;
57 import org.w3c.dom.NodeList;
58
59
60
61
62
63
64
65
66
67
68
69 public class ImageGeneratorMojo extends AbstractMojo {
70
71
72
73
74
75
76
77 private File configFile;
78
79
80
81
82
83
84
85 private String lookAndFeel;
86
87
88
89
90
91
92
93 private File outputDirectory;
94
95
96
97
98
99
100
101 private File savedConfigFile;
102
103
104 private JPanel panel;
105
106
107
108
109
110
111 public void setConfigFile(File configFile) {
112 this.configFile = configFile;
113 }
114
115
116
117
118
119
120 public void setLookAndFeel(String lookAndFeel) {
121 this.lookAndFeel = lookAndFeel;
122 }
123
124
125
126
127
128
129 public void setOutputDirectory(File outputDirectory) {
130 this.outputDirectory = outputDirectory;
131 }
132
133
134
135
136
137
138 public void setSavedConfigFile(File savedConfigFile) {
139 this.savedConfigFile = savedConfigFile;
140 }
141
142
143
144
145 public void execute() throws MojoExecutionException {
146 Map<String, ImageInfo> config = parseConfigFile(configFile, true);
147 Map<String, ImageInfo> oldConfig = parseConfigFile(savedConfigFile, false);
148
149 createOutputDirectoryIfNecessary();
150
151 panel = null;
152
153 generateImageFiles(config, oldConfig);
154
155 copyConfigToOldConfig(configFile, savedConfigFile);
156 }
157
158
159
160
161
162
163
164
165 private void createUIIfNecessary() throws MojoExecutionException {
166 if (panel == null) {
167 try {
168 UIManager.setLookAndFeel(lookAndFeel);
169 } catch (Exception e) {
170 e.printStackTrace();
171 throw new MojoExecutionException("Unable to set look and feel " + lookAndFeel, e);
172 }
173
174 panel = new JPanel();
175 panel.setOpaque(true);
176 }
177 }
178
179
180
181
182
183
184
185
186
187
188 private void generateImageFiles(Map<String, ImageInfo> config, Map<String, ImageInfo> oldConfig) throws MojoExecutionException {
189 for (String filename : config.keySet()) {
190 ImageInfo info = config.get(filename);
191 ImageInfo oldInfo = oldConfig.get(filename);
192 File file = new File(outputDirectory, filename + ".png");
193
194 if (oldInfo == null || !file.exists() || !info.equals(oldInfo)) {
195 getLog().info("Creating image file " + filename);
196 createUIIfNecessary();
197 drawImage(file, info.className, info.width, info.height, info.panelWidth, info.panelHeight, info.args,
198 info.properties);
199 }
200 }
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 private void drawImage(File file, String className, int width, int height, int panelWidth, int panelHeight, Object[] args,
220 Map<String, Object> properties) throws MojoExecutionException {
221
222 JComponent c = createSwingObject(className, args);
223
224
225 for (String key : properties.keySet()) {
226 c.putClientProperty(key, properties.get(key));
227 }
228
229
230 BufferedImage image = paintToBufferedImage(c, width, height, panelWidth, panelHeight);
231
232
233 writeImageFile(file, image);
234 }
235
236
237
238
239
240
241
242
243
244
245
246 private JComponent createSwingObject(String className, Object... args) throws MojoExecutionException {
247 try {
248 Class<?> c = Class.forName(className);
249
250 Class<?>[] argClasses = new Class[args.length];
251
252 for (int i = 0; i < args.length; i++) {
253 argClasses[i] = args[i].getClass();
254 }
255
256 Constructor<?> constructor = c.getConstructor(argClasses);
257
258 if (constructor == null) {
259 throw new MojoExecutionException("Failed to find the constructor for the class: " + className);
260 }
261
262 return (JComponent) constructor.newInstance(args);
263 } catch (Exception e) {
264 throw new MojoExecutionException("Unable to create the object " + className + "(" + args + ")", e);
265 }
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280 private BufferedImage paintToBufferedImage(JComponent c, int width, int height, int panelWidth, int panelHeight) {
281 panel.removeAll();
282 panel.setSize(panelWidth, panelHeight);
283
284 panel.add(c);
285 c.setBounds((panelWidth - width) / 2, (panelHeight - height) / 2, width, height);
286
287 BufferedImage image = new BufferedImage(panelWidth, panelHeight, BufferedImage.TYPE_INT_ARGB);
288 Graphics g = image.createGraphics();
289
290 panel.paint(g);
291 return image;
292 }
293
294
295
296
297
298
299
300
301
302 private void writeImageFile(File file, BufferedImage image) throws MojoExecutionException {
303 try {
304 ImageIO.write(image, "png", file);
305 } catch (IOException e) {
306 throw new MojoExecutionException("Error writing image file " + file, e);
307 }
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 private Map<String, ImageInfo> parseConfigFile(File filename, boolean quitOnError) throws MojoExecutionException {
324 Map<String, ImageInfo> list = new HashMap<String, ImageInfo>();
325 InputStream configStream = openInputStream(filename, quitOnError);
326 Document doc = null;
327
328 if (configStream == null) {
329
330 return list;
331 }
332
333 try {
334 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
335 DocumentBuilder db = dbf.newDocumentBuilder();
336
337 doc = db.parse(configStream);
338 } catch (Exception e) {
339 closeInputStream(configStream);
340 if (quitOnError) {
341 throw new MojoExecutionException("Unable to parse XML config file " + filename, e);
342 }
343
344 return list;
345 }
346
347 doc.getDocumentElement().normalize();
348 NodeList nodeList = doc.getElementsByTagName("image");
349
350 for (int i = 0; i < nodeList.getLength(); i++) {
351 Node imageNode = nodeList.item(i);
352
353 if (imageNode.getNodeType() == Node.ELEMENT_NODE) {
354 ImageInfo info = new ImageInfo();
355 String imageFile = getImageInfo((Element) imageNode, info);
356
357 list.put(imageFile, info);
358 }
359 }
360
361 closeInputStream(configStream);
362
363 return list;
364 }
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 private InputStream openInputStream(File filename, boolean quitOnError) throws MojoExecutionException {
380 try {
381 return new FileInputStream(filename);
382 } catch (FileNotFoundException e) {
383 if (quitOnError) {
384 throw new MojoExecutionException("Unable to open file \"" + filename, e);
385 }
386
387 return null;
388 }
389 }
390
391
392
393
394
395
396 private void closeInputStream(InputStream stream) {
397 try {
398 stream.close();
399 } catch (IOException e) {
400
401 }
402 }
403
404
405
406
407
408
409
410
411 private void createOutputDirectoryIfNecessary() throws MojoExecutionException {
412 if (outputDirectory.exists()) {
413 if (!outputDirectory.isDirectory()) {
414 throw new MojoExecutionException("Output directory \"" + outputDirectory + "\" exists, but is not a directory.");
415 } else if (!outputDirectory.canWrite()) {
416 throw new MojoExecutionException("Output directory \"" + outputDirectory + "\" exists, but is not writable.");
417 }
418 } else if (!outputDirectory.mkdirs()) {
419 throw new MojoExecutionException("Output directory \"" + outputDirectory + "\" could not be created.");
420 }
421 }
422
423
424
425
426
427
428
429
430
431 private void copyConfigToOldConfig(File configFilename, File oldConfigFilename) throws MojoExecutionException {
432 BufferedReader reader = new BufferedReader(new InputStreamReader(openInputStream(configFilename, true)));
433
434 BufferedWriter writer = null;
435
436 try {
437 writer = new BufferedWriter(new FileWriter(oldConfigFilename));
438 } catch (IOException e) {
439 throw new MojoExecutionException("Unable to open for writing the file " + oldConfigFilename, e);
440 }
441
442 try {
443 for (String line = null; (line = reader.readLine()) != null;) {
444 writer.write(line);
445 writer.write("\n");
446 }
447 } catch (IOException e) {
448 throw new MojoExecutionException("Unable to write " + oldConfigFilename, e);
449 } finally {
450 try {
451 writer.close();
452 } catch (IOException e) {
453
454 }
455 }
456 }
457
458
459
460
461
462
463
464
465
466
467
468 private String getImageInfo(Element imageElem, ImageInfo info) throws MojoExecutionException {
469 String filename = imageElem.getAttribute("file");
470
471 String w = imageElem.getAttribute("width");
472 String h = imageElem.getAttribute("height");
473 String pw = imageElem.getAttribute("panelWidth");
474 String ph = imageElem.getAttribute("panelHeight");
475
476 if (pw.length() == 0) {
477 pw = w;
478 }
479
480 if (ph.length() == 0) {
481 ph = h;
482 }
483
484 info.className = imageElem.getAttribute("class");
485 info.width = Integer.parseInt(w);
486 info.height = Integer.parseInt(h);
487 info.panelWidth = Integer.parseInt(pw);
488 info.panelHeight = Integer.parseInt(ph);
489
490 List<Object> argList = new ArrayList<Object>();
491
492 NodeList nodeList = imageElem.getElementsByTagName("argument");
493
494 for (int i = 0; i < nodeList.getLength(); i++) {
495 Node node = nodeList.item(i);
496
497 if (node.getNodeType() == Node.ELEMENT_NODE) {
498 Element argElem = (Element) node;
499 String type = argElem.getAttribute("type");
500 String value = argElem.getAttribute("value");
501
502 argList.add(parseObject(type, value));
503 }
504 }
505
506 info.args = argList.toArray();
507
508 info.properties = new HashMap<String, Object>();
509
510 nodeList = imageElem.getElementsByTagName("clientProperty");
511
512 for (int i = 0; i < nodeList.getLength(); i++) {
513 Node node = nodeList.item(i);
514
515 if (node.getNodeType() == Node.ELEMENT_NODE) {
516 Element argElem = (Element) node;
517 String name = argElem.getAttribute("name");
518 String type = argElem.getAttribute("type");
519 String value = argElem.getAttribute("value");
520
521 info.properties.put(name, parseObject(type, value));
522 }
523 }
524
525 info.args = argList.toArray();
526
527 return filename;
528 }
529
530
531
532
533
534
535
536
537
538
539
540 private Object parseObject(String type, String value) throws MojoExecutionException {
541 Object obj = null;
542
543 if ("String".equals(type)) {
544 obj = value;
545 } else if ("Integer".equals(type)) {
546 obj = Integer.parseInt(value);
547 } else if ("Float".equals(type)) {
548 obj = Float.parseFloat(value);
549 } else if ("Double".equals(type)) {
550 obj = Double.parseDouble(value);
551 } else {
552 throw new MojoExecutionException("Unknown argument type: " + type);
553 }
554
555 return obj;
556 }
557
558
559
560
561 public static class ImageInfo {
562 String className;
563 int width;
564 int height;
565 int panelWidth;
566 int panelHeight;
567 Object[] args;
568 Map<String, Object> properties;
569
570
571
572
573 @Override
574 public boolean equals(Object obj) {
575 if (!(obj instanceof ImageInfo)) {
576 return false;
577 }
578
579 ImageInfo other = (ImageInfo) obj;
580
581 return (className.equals(other.className) && width == other.width && height == other.height && panelWidth == other.panelWidth
582 && panelHeight == other.panelHeight && argsEquals(other) && properties.equals(other.properties));
583 }
584
585
586
587
588
589
590
591
592
593 private boolean argsEquals(ImageInfo other) {
594 if (args.length != other.args.length) {
595 return false;
596 }
597
598 for (int i = 0; i < args.length; i++) {
599 if (!args[i].equals(other.args[i])) {
600 return false;
601 }
602 }
603
604 return true;
605 }
606 }
607 }