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