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