1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package net.sourceforge.jenesis4java.jaloppy;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 import de.hunsicker.jalopy.Jalopy;
40 import de.hunsicker.jalopy.Jalopy.State;
41 import de.hunsicker.jalopy.storage.Convention;
42 import de.hunsicker.jalopy.storage.ConventionDefaults;
43 import de.hunsicker.jalopy.storage.ConventionKeys;
44 import de.hunsicker.jalopy.storage.History;
45 import net.sourceforge.jenesis4java.CodeWriter;
46 import net.sourceforge.jenesis4java.CompilationUnit;
47 import net.sourceforge.jenesis4java.CompilationUnitEncoder;
48 import net.sourceforge.jenesis4java.impl.MCodeWriter;
49
50 import java.io.*;
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53
54 import static java.nio.charset.StandardCharsets.UTF_8;
55
56
57
58
59
60
61
62
63 public class JenesisJalopyEncoder implements CompilationUnitEncoder {
64
65 private static final Logger LOGGER = Logger.getLogger(JenesisJalopyEncoder.class.getName());
66
67 final private String jalopyConfigAsResourceOrFile;
68
69 private Jalopy jalopy;
70
71 public JenesisJalopyEncoder() {
72 this(System.getProperty("jenesis.encoder.jalopyconfig", "META-INF/jalopy.xml"));
73 }
74
75 public JenesisJalopyEncoder(String jalopyConfigAsResourceOrFile) {
76 this.jalopyConfigAsResourceOrFile = jalopyConfigAsResourceOrFile;
77 }
78
79 @Override
80 public void encode(CompilationUnit unit) {
81
82
83 PrintWriter fout = null;
84 try {
85
86
87
88 File file = new File(getFileName(unit));
89
90
91
92
93 File dir = file.getParentFile();
94
95
96 if (!dir.exists()) {
97 if (!dir.mkdirs()) {
98 throw new RuntimeException("could not create directory: " + dir.getCanonicalPath());
99 }
100 }
101 StringWriter stringWriter;
102 BufferedWriter bufferedWriter;
103
104
105
106 stringWriter = new StringWriter();
107 bufferedWriter = new BufferedWriter(stringWriter);
108
109
110
111 fout = new PrintWriter(bufferedWriter);
112
113
114 CodeWriter out = new MCodeWriter(fout);
115
116
117 unit.toCode(out);
118
119
120 fout.close();
121 fout = null;
122
123 String javaSource = stringWriter.toString();
124 String formatedSource = formatFile(file, javaSource);
125 if (formatedSource != null) {
126 javaSource = formatedSource;
127 }
128 writeIfChanged(javaSource, file);
129 } catch (IOException ioex) {
130 ioex.printStackTrace();
131 } finally {
132 if (fout != null) {
133 try {
134 fout.close();
135 } catch (Exception ex) {
136 throw new RuntimeException(ex);
137 }
138 }
139 }
140 }
141
142 private Jalopy createJalopy(Jalopy jalopy) {
143 InputStream in;
144 try {
145 in = this.getClass().getClassLoader().getResourceAsStream(jalopyConfigAsResourceOrFile);
146 Convention.importSettings(in, Convention.EXTENSION_XML);
147 } catch (IOException ex) {
148 in = null;
149 }
150 if (in == null) {
151 try {
152 File configFile = new File(jalopyConfigAsResourceOrFile);
153 in = new FileInputStream(configFile);
154 Convention.importSettings(in, Convention.EXTENSION_XML);
155 } catch (IOException ex) {
156 throw new RuntimeException("could NOT find a Jalopy config (as resource and file) " + jalopyConfigAsResourceOrFile, ex);
157 }
158 }
159
160 Convention settings = Convention.getInstance();
161
162 jalopy.setFileFormat("auto");
163
164 jalopy.setInspect(settings.getBoolean(ConventionKeys.INSPECTOR, ConventionDefaults.INSPECTOR));
165
166 jalopy.setHistoryPolicy(History.Policy.DISABLED);
167
168 History.Method historyMethod = History.Method.valueOf(settings.get(ConventionKeys.HISTORY_METHOD, ConventionDefaults.HISTORY_METHOD));
169
170 jalopy.setHistoryMethod(historyMethod);
171
172 jalopy.setBackup(settings.getInt(ConventionKeys.BACKUP_LEVEL, ConventionDefaults.BACKUP_LEVEL) > 0);
173
174 jalopy.setForce(settings.getBoolean(ConventionKeys.FORCE_FORMATTING, ConventionDefaults.FORCE_FORMATTING));
175
176 return jalopy;
177 }
178
179 private String formatFile(File file, String source) {
180 if (getJalopy() != null) {
181 try {
182 Reader inputReader = new StringReader(source);
183 Writer formattedWriter = new StringWriter();
184 if (!file.exists() && !file.createNewFile()) {
185 throw new RuntimeException("Could not access File");
186 }
187 getJalopy().setInput(inputReader, file.getCanonicalPath());
188 getJalopy().setOutput(formattedWriter);
189 getJalopy().format();
190 logMessage(jalopy, file.getCanonicalPath());
191 if (jalopy.getState() == Jalopy.State.OK || jalopy.getState() == Jalopy.State.PARSED) {
192 return formattedWriter.toString();
193 } else {
194 resetJalopy();
195 throw new RuntimeException("Could not format java file due to Jalopy State " + jalopy.getState());
196
197 }
198 } catch (Exception e) {
199 resetJalopy();
200 throw new RuntimeException("Could not format java file due to Exception", e);
201
202 }
203 }
204 return null;
205 }
206
207
208
209
210 private String getFileContents(File file) throws IOException {
211
212 InputStreamReader fr = new InputStreamReader(new FileInputStream(file), UTF_8);
213 StringWriter sr = new StringWriter();
214
215 try {
216 char[] buf = new char[4096];
217 int len = 0;
218 while (len != -1) {
219 try {
220 len = fr.read(buf, 0, buf.length);
221 } catch (EOFException eof) {
222 break;
223 }
224 if (len != -1) {
225 sr.write(buf, 0, len);
226 }
227 }
228
229 fr.close();
230 sr.close();
231
232 return sr.toString();
233
234 } finally {
235 try {
236 fr.close();
237 } catch (IOException ioe) {
238 LOGGER.log(Level.WARNING, "Exception during InputStreamReader.close(). ", ioe);
239 }
240 }
241 }
242
243 private String getFileName(CompilationUnit unit) {
244
245
246
247 StringBuilder file;
248
249
250 if (unit.getCodebase() != null && unit.getCodebase().length() > 0) {
251
252 file = new StringBuilder(unit.getCodebase());
253
254 if (!unit.getCodebase().endsWith(Character.toString(File.separatorChar))) {
255
256 file.append(File.separatorChar);
257 }
258 } else {
259 file = new StringBuilder();
260 }
261
262
263 if (unit.getNamespace() != null) {
264
265 String pkg = unit.getNamespace().getName();
266 if (pkg != null) {
267
268 file.append(pkg.replace('.', java.io.File.separatorChar));
269 }
270 }
271
272
273 String topLevelTypeName = unit.getTopLevelType().getName();
274 int indexOfGeneric = topLevelTypeName.indexOf('<');
275 if (indexOfGeneric > 0) {
276 topLevelTypeName = topLevelTypeName.substring(0, indexOfGeneric).trim();
277 }
278
279 file.append(java.io.File.separatorChar).append(topLevelTypeName).append(".java");
280
281
282 return file.toString();
283 }
284
285 private Jalopy getJalopy() {
286 if (jalopy == null && jalopyConfigAsResourceOrFile != null) {
287 jalopy = createJalopy(new Jalopy());
288 }
289 return jalopy;
290 }
291
292
293
294
295
296 private void resetJalopy() {
297 jalopy = null;
298 }
299
300 private void writeIfChanged(String newFileContents, File file) throws IOException {
301 String oldFileContents = getFileContents(file);
302 if (!oldFileContents.equals(newFileContents)) {
303 FileOutputStream outStream = new FileOutputStream(file);
304 OutputStreamWriter writer = new OutputStreamWriter(outStream, UTF_8);
305 writer.write(newFileContents);
306 writer.close();
307 outStream.close();
308 logMessage("INFO", "File " + file.getCanonicalPath() + " was written to disk");
309 }
310 }
311
312 private void logMessage(Jalopy jalopy, String message) {
313 State state = jalopy.getState();
314 if (state == Jalopy.State.OK) {
315 logMessage("DEBUG", message + " formatted correctly.");
316 } else if (state == Jalopy.State.WARN) {
317 logMessage("WARN", message + " formatted with warnings.");
318 } else if (state == Jalopy.State.ERROR) {
319 logMessage("ERROR", message + " could not be formatted.");
320 } else {
321 logMessage("INFO", message + " formatted with unknown state (" + state + ")");
322 }
323 }
324
325 private void logMessage(String level, String message) {
326 System.out.println(level + " " + message);
327 }
328 }