comparison src/main/java/org/msgpack/util/TemplatePrecompiler.java @ 0:cb825acd883a

first commit
author sugi
date Sat, 18 Oct 2014 15:06:15 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:cb825acd883a
1 //
2 // MessagePack for Java
3 //
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 package org.msgpack.util;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Properties;
26 import java.util.logging.Logger;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29
30 import javax.tools.DiagnosticCollector;
31 import javax.tools.JavaCompiler;
32 import javax.tools.JavaFileManager;
33 import javax.tools.JavaFileObject;
34 import javax.tools.StandardLocation;
35 import javax.tools.ToolProvider;
36
37 import org.msgpack.template.TemplateRegistry;
38 import org.msgpack.template.builder.JavassistTemplateBuilder;
39
40 /**
41 * This class is a template precompiler, which is used for saving templates that
42 * <code>TemplateBuilder</code> generated. It saves templates as .class files.
43 * Application enables to load the .class files and use templates.
44 *
45 */
46 public class TemplatePrecompiler {
47
48 private static final Logger LOG = Logger.getLogger(TemplatePrecompiler.class.getName());
49
50 public static final String DEST = "msgpack.template.destdir";
51
52 public static final String DEFAULT_DEST = ".";
53
54 public static void saveTemplates(final String[] classNames)
55 throws IOException, ClassNotFoundException {
56 // TODO #MN
57 TemplateRegistry registry = new TemplateRegistry(null);
58 List<String> ret = new ArrayList<String>();
59 for (String className : classNames) {
60 matchClassNames(ret, className);
61 }
62 List<Class<?>> ret0 = toClass(ret);
63 for (Class<?> c : ret0) {
64 saveTemplateClass(registry, c);
65 }
66 }
67
68 @SuppressWarnings("serial")
69 private static void matchClassNames(List<String> ret, final String className)
70 throws IOException {
71 String packageName = className.substring(0, className.lastIndexOf('.'));
72 String relativedName = className.substring(
73 className.lastIndexOf('.') + 1, className.length());
74 String patName = relativedName.replace("*", "(\\w+)");
75 Pattern pat = Pattern.compile(patName);
76
77 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
78 JavaFileManager fm = compiler.getStandardFileManager(
79 new DiagnosticCollector<JavaFileObject>(), null, null);
80 HashSet<JavaFileObject.Kind> kind = new HashSet<JavaFileObject.Kind>() {
81 {
82 add(JavaFileObject.Kind.CLASS);
83 }
84 };
85
86 for (JavaFileObject f : fm.list(StandardLocation.PLATFORM_CLASS_PATH, packageName, kind, false)) {
87 String relatived0 = f.getName();
88 String name0 = relatived0.substring(0, relatived0.length() - ".class".length());
89 Matcher m = pat.matcher(name0);
90 if (m.matches()) {
91 String name = packageName + '.' + name0;
92 if (!ret.contains(name)) {
93 ret.add(name);
94 }
95 }
96 }
97 }
98
99 private static List<Class<?>> toClass(List<String> classNames)
100 throws ClassNotFoundException {
101 List<Class<?>> ret = new ArrayList<Class<?>>(classNames.size());
102 ClassLoader cl = TemplatePrecompiler.class.getClassLoader();
103 for (String className : classNames) {
104 Class<?> c = cl.loadClass(className);
105 ret.add(c);
106 }
107 return ret;
108 }
109
110 public static void saveTemplateClasses(TemplateRegistry registry, Class<?>[] targetClasses)
111 throws IOException {
112 for (Class<?> c : targetClasses) {
113 saveTemplateClass(registry, c);
114 }
115 }
116
117 public static void saveTemplateClass(TemplateRegistry registry, Class<?> targetClass)
118 throws IOException {
119 LOG.info("Saving template of " + targetClass.getName() + "...");
120 Properties props = System.getProperties();
121 String distDirName = getDirName(props, DEST, DEFAULT_DEST);
122 if (targetClass.isEnum()) {
123 throw new UnsupportedOperationException(
124 "Not supported enum type yet: " + targetClass.getName());
125 } else {
126 new JavassistTemplateBuilder(registry).writeTemplate(targetClass,
127 distDirName);
128 }
129 LOG.info("Saved .class file of template class of " + targetClass.getName());
130 }
131
132 public static boolean deleteTemplateClass(Class<?> targetClass)
133 throws IOException {
134 LOG.info("Deleting template of " + targetClass.getName() + "...");
135 Properties props = System.getProperties();
136 String distDirName = getDirName(props, DEST, DEFAULT_DEST);
137 String targetClassName = targetClass.getName();
138 String targetClassFileName = targetClassName.replace('.',
139 File.separatorChar) + "_$$_Template.class";
140 File targetFile = new File(distDirName + File.separatorChar
141 + targetClassFileName);
142 boolean deleted = false;
143 if (!targetFile.isDirectory() && targetFile.exists()) {
144 deleted = targetFile.delete();
145 }
146 LOG.info("Deleted .class file of template class of " + targetClass.getName());
147 return deleted;
148 }
149
150 private static String getDirName(Properties props, String dirName, String defaultDirName)
151 throws IOException {
152 String dName = props.getProperty(dirName, defaultDirName);
153 File d = new File(dName);
154 if (!d.isDirectory() && !d.exists()) {
155 throw new IOException("Directory not exists: " + dName);
156 }
157 return d.getAbsolutePath();
158 }
159
160 public static void main(final String[] args) throws Exception {
161 TemplatePrecompiler.saveTemplates(args);
162 }
163 }