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