1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.codehaus.modello.plugin.velocity;
20
21 import java.io.IOException;
22 import java.io.Writer;
23 import java.nio.charset.StandardCharsets;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.Map;
28 import java.util.Objects;
29 import java.util.Properties;
30 import org.apache.velocity.Template;
31 import org.apache.velocity.VelocityContext;
32 import org.apache.velocity.runtime.RuntimeInstance;
33 import org.codehaus.modello.ModelloException;
34 import org.codehaus.modello.ModelloParameterConstants;
35 import org.codehaus.modello.model.Model;
36 import org.codehaus.modello.model.Version;
37 import org.codehaus.modello.plugin.AbstractModelloGenerator;
38 import org.codehaus.plexus.util.io.CachingWriter;
39
40 public class VelocityGenerator extends AbstractModelloGenerator {
41 public static final String VELOCITY_TEMPLATES = "modello.velocity.template";
42
43 public static final String VELOCITY_PARAMETERS = "modello.velocity.parameters";
44
45 @Override
46 public void generate(Model model, Properties parameters) throws ModelloException {
47 try {
48 Map<String, String> params = (Map) Objects.requireNonNull(parameters.get(VELOCITY_PARAMETERS));
49 String templates = getParameter(parameters, VELOCITY_TEMPLATES);
50 String output = getParameter(parameters, ModelloParameterConstants.OUTPUT_DIRECTORY);
51
52 Properties props = new Properties();
53 props.put("resource.loader.file.path", getParameter(parameters, "basedir"));
54 RuntimeInstance velocity = new RuntimeInstance();
55 velocity.init(props);
56
57 VelocityContext context = new VelocityContext();
58 for (Map.Entry<Object, Object> prop : parameters.entrySet()) {
59 context.put(prop.getKey().toString(), prop.getValue());
60 }
61 for (Map.Entry<String, String> prop : params.entrySet()) {
62 context.put(prop.getKey(), prop.getValue());
63 }
64 Version version = new Version(getParameter(parameters, ModelloParameterConstants.VERSION));
65 context.put("version", version);
66 context.put("model", model);
67 context.put("Helper", new Helper(version));
68
69 for (String templatePath : templates.split(",")) {
70 Template template = velocity.getTemplate(templatePath);
71
72 try (Writer w = new RedirectingWriter(Paths.get(output))) {
73 template.merge(context, w);
74 }
75 }
76 } catch (Exception e) {
77 throw new ModelloException("Unable to run velocity template", e);
78 }
79 }
80
81 static class RedirectingWriter extends Writer {
82 Path dir;
83 StringBuilder sb = new StringBuilder();
84 Writer current;
85
86 RedirectingWriter(Path dir) {
87 this.dir = dir;
88 }
89
90 @Override
91 public void write(char[] cbuf, int off, int len) throws IOException {
92 for (int i = 0; i < len; i++) {
93 if (cbuf[off + i] == '\n') {
94 if (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\r') {
95 sb.setLength(sb.length() - 1);
96 }
97 writeLine(sb.toString());
98 sb.setLength(0);
99 } else {
100 sb.append(cbuf[off + i]);
101 }
102 }
103 }
104
105 protected void writeLine(String line) throws IOException {
106 if (line.startsWith("#MODELLO-VELOCITY#REDIRECT ")) {
107 String file = line.substring("#MODELLO-VELOCITY#REDIRECT ".length());
108 if (current != null) {
109 current.close();
110 }
111 Path out = dir.resolve(file);
112 Files.createDirectories(out.getParent());
113 current = new CachingWriter(out, StandardCharsets.UTF_8);
114 } else if (current != null) {
115 current.write(line);
116 current.write("\n");
117 }
118 }
119
120 @Override
121 public void flush() throws IOException {
122 if (current != null) {
123 current.flush();
124 }
125 }
126
127 @Override
128 public void close() throws IOException {
129 if (current != null) {
130 current.close();
131 current = null;
132 }
133 }
134 }
135 }