1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.audit.generator;
18
19 import java.io.DataOutputStream;
20 import java.io.File;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.TreeSet;
31
32 import org.apache.logging.log4j.audit.util.NamingUtils;
33
34 import static org.apache.logging.log4j.audit.generator.Constants.*;
35
36
37
38
39 public final class ClassGenerator {
40
41 protected List<AccessorDefinition> beanMethods = new ArrayList<AccessorDefinition>();
42 private boolean isClass = true;
43 private String className;
44 private String parentClassName;
45 private String packageName;
46 private String baseFolder;
47 private String javadocComment;
48 private List<String> implementsDeclarations = new ArrayList<>();
49
50 private Set<String> importsDeclarations = new HashSet<String>();
51
52 private List<VariableDefinition> localVariables = new ArrayList<>();
53
54 private List<ConstructorDefinition> constructors = new ArrayList<>();
55
56 private List<MethodDefinition> methods = new ArrayList<>();
57
58 private boolean runPrewrite = false;
59
60 private boolean isAbstract = false;
61
62 private String visability = PUBLIC;
63
64 private String annotations = null;
65
66 private String code = null;
67
68 private String typeStatement = null;
69
70 public ClassGenerator(String className, String baseFolder) {
71 this.className = className;
72 this.baseFolder = baseFolder;
73 }
74
75 public String getTypeStatement() {
76 return typeStatement;
77 }
78
79 public void setTypeStatement(String typeStatement) {
80 this.typeStatement = typeStatement;
81 }
82
83
84
85
86
87
88
89
90 public String getCode() {
91 return code;
92 }
93
94 public void setCode(String code) {
95 this.code = code;
96 }
97
98 public void addBeanMethods(AccessorDefinition beanDefinition) {
99 beanMethods.add(beanDefinition);
100 }
101
102 public void addConstructor(ConstructorDefinition constructorDefinition) {
103 constructors.add(constructorDefinition);
104 }
105
106 public void addLocalVariable(VariableDefinition definition) {
107 localVariables.add(definition);
108 }
109
110 public void addMethod(MethodDefinition definition) {
111 methods.add(definition);
112 }
113
114 public void addSingelton(String name, List<String> parameters) {
115 if (Character.isUpperCase(name.charAt(0))) {
116 name = name.substring(0, 1).toLowerCase() + name.substring(1);
117 }
118
119 VariableDefinition definition = new VariableDefinition("private",
120 getClassName(), name, null);
121 definition.setMakeStatic(true);
122 addLocalVariable(definition);
123 addMethod(MethodDefinition.getStandardSingleton(getClassName(), name, parameters));
124 }
125
126 public String getAnnotations() {
127 return annotations;
128 }
129
130 public void setAnnotations(String annotations) {
131 this.annotations = annotations;
132 }
133
134 public List<AccessorDefinition> getBeanMethods() {
135 return beanMethods;
136 }
137
138 public String getClassName() {
139 return className;
140 }
141
142 public String getParentClassName() {
143 return parentClassName;
144 }
145
146 public void setParentClassName(String parentClassName) {
147 this.parentClassName = parentClassName;
148 }
149
150 public List<String> getImplements() {
151 return implementsDeclarations;
152 }
153
154 public Set<String> getImports() {
155 return importsDeclarations;
156 }
157
158 public List<MethodDefinition> getMethodDefinitions() {
159 return methods;
160 }
161
162 public String getPackageName() {
163 return packageName;
164 }
165
166 public void setPackageName(String packageName) {
167 this.packageName = packageName;
168 }
169
170 public List<VariableDefinition> getVariableDefinitions() {
171 return localVariables;
172 }
173
174 public String getVisability() {
175 return visability;
176 }
177
178 public void setVisability(String visability) {
179 this.visability = visability;
180 }
181
182 public boolean isAbstract() {
183 return isAbstract;
184 }
185
186 public void setAbstract(boolean isAbstract) {
187 this.isAbstract = isAbstract;
188 }
189
190 public boolean isClass() {
191 return isClass;
192 }
193
194 public void setClass(boolean isClass) {
195 this.isClass = isClass;
196 }
197
198
199
200
201
202 public void preWrite() {
203
204 }
205
206 public void generate() throws Exception {
207 StringBuilder sb = new StringBuilder(baseFolder);
208 if (getPackageName() != null) {
209 sb.append("/").append(getPackageName().replaceAll("\\.", "/"));
210 }
211 sb.append("/").append(NamingUtils.upperFirst(getClassName()))
212 .append(".java");
213 String fullPath = sb.toString();
214 System.out.println(fullPath);
215 File file = new File(fullPath);
216 DataOutputStream out = new DataOutputStream(openOutputStream(file));
217 out.writeBytes(getClassContents());
218 out.close();
219
220 }
221
222 public String getClassContents() throws Exception {
223 if (getClassName() == null) {
224 throw new Exception("Class name has to be set");
225 }
226
227 if (!runPrewrite) {
228 preWrite();
229 runPrewrite = true;
230 }
231
232 StringBuilder sb = new StringBuilder();
233 sb.append("package ").append(getPackageName()).append(";\n\n");
234 if (getImports() != null) {
235 List<String> list = new ArrayList<String>(getImports());
236 Collections.sort(list);
237 for (String element : list) {
238 sb.append("import ").append(element).append(";\n");
239 }
240 sb.append("\n");
241 }
242
243 sb.append("/**\n");
244 if (getJavadocComment() != null) {
245 sb.append(" * ").append(getJavadocComment());
246 }
247 sb.append("\n * @author generated");
248 sb.append("\n */\n");
249
250 if (annotations != null) {
251 sb.append(annotations);
252 sb.append("\n");
253 }
254
255 sb.append(getVisability());
256 if (isClass()) {
257 sb.append(" class ");
258 } else {
259 sb.append(" interface ");
260 }
261 sb.append(getClassName());
262 if (typeStatement != null) {
263 sb.append(" <").append(typeStatement).append("> ");
264 }
265
266 if (getParentClassName() != null && getParentClassName().length() > 0) {
267 sb.append(" extends ").append(getParentClassName());
268 }
269 if (getImplements() != null && getImplements().size() > 0) {
270 sb.append(" implements ");
271 boolean first = true;
272 for (String element : getImplements()) {
273 if (!first) {
274 sb.append(", ");
275 }
276 sb.append(element);
277 first = false;
278 }
279 }
280 sb.append(" {\n\n");
281 if (localVariables != null) {
282 Collections.sort(localVariables);
283 for (VariableDefinition element : localVariables) {
284 sb.append(element).append("\n");
285 }
286 }
287
288 if (constructors != null) {
289 Collections.sort(constructors);
290 for (ConstructorDefinition element : constructors) {
291 sb.append(element).append("\n\n");
292 }
293 }
294
295 if (beanMethods.size() > 0 && isClass()) {
296 MethodDefinition definition = new MethodDefinition("String",
297 "toString");
298 StringBuilder buffer = new StringBuilder();
299 buffer.append("\tStringBuilder sb = new StringBuilder();");
300 buffer.append("\n\tsb.append(super.toString());");
301 for (AccessorDefinition element : beanMethods) {
302 buffer.append("\n\tsb.append(\", ");
303 buffer.append(element.getName())
304 .append("=\").append(")
305 .append(NamingUtils.getAccessorName(element.getName(),
306 element.getType())).append("());");
307 }
308 buffer.append("\n\treturn sb.toString();");
309 definition.setContent(buffer.toString());
310 methods.add(definition);
311 }
312
313 if (methods != null) {
314 Collections.sort(methods);
315 for (MethodDefinition element : methods) {
316 sb.append(element).append("\n\n");
317 }
318 }
319
320 if (code != null) {
321 sb.append(code).append("\n");
322 }
323
324 sb.append("}");
325 return sb.toString();
326 }
327
328 public String getJavadocComment() {
329 return javadocComment;
330 }
331
332 public void setJavadocComment(String javadocComment) {
333 this.javadocComment = javadocComment;
334 }
335
336 private OutputStream openOutputStream(File file) throws IOException {
337 if (file.exists()) {
338 if (file.isDirectory()) {
339 throw new IOException("File '" + file + "' exists but is a directory");
340 }
341 if (!file.canWrite()) {
342 throw new IOException("File '" + file + "' cannot be written to");
343 }
344 } else {
345 final File parent = file.getParentFile();
346 if (parent != null) {
347 if (!parent.mkdirs() && !parent.isDirectory()) {
348 throw new IOException("Directory '" + parent + "' could not be created");
349 }
350 }
351 }
352 return new FileOutputStream(file, false);
353 }
354
355 }