Mercurial > hg > Members > sugi > MessagePack-java
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/msgpack/util/TemplatePrecompiler.java Sat Oct 18 15:06:15 2014 +0900 @@ -0,0 +1,163 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009 - 2013 FURUHASHI Sadayuki +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.util; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import org.msgpack.template.TemplateRegistry; +import org.msgpack.template.builder.JavassistTemplateBuilder; + +/** + * This class is a template precompiler, which is used for saving templates that + * <code>TemplateBuilder</code> generated. It saves templates as .class files. + * Application enables to load the .class files and use templates. + * + */ +public class TemplatePrecompiler { + + private static final Logger LOG = Logger.getLogger(TemplatePrecompiler.class.getName()); + + public static final String DEST = "msgpack.template.destdir"; + + public static final String DEFAULT_DEST = "."; + + public static void saveTemplates(final String[] classNames) + throws IOException, ClassNotFoundException { + // TODO #MN + TemplateRegistry registry = new TemplateRegistry(null); + List<String> ret = new ArrayList<String>(); + for (String className : classNames) { + matchClassNames(ret, className); + } + List<Class<?>> ret0 = toClass(ret); + for (Class<?> c : ret0) { + saveTemplateClass(registry, c); + } + } + + @SuppressWarnings("serial") + private static void matchClassNames(List<String> ret, final String className) + throws IOException { + String packageName = className.substring(0, className.lastIndexOf('.')); + String relativedName = className.substring( + className.lastIndexOf('.') + 1, className.length()); + String patName = relativedName.replace("*", "(\\w+)"); + Pattern pat = Pattern.compile(patName); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + JavaFileManager fm = compiler.getStandardFileManager( + new DiagnosticCollector<JavaFileObject>(), null, null); + HashSet<JavaFileObject.Kind> kind = new HashSet<JavaFileObject.Kind>() { + { + add(JavaFileObject.Kind.CLASS); + } + }; + + for (JavaFileObject f : fm.list(StandardLocation.PLATFORM_CLASS_PATH, packageName, kind, false)) { + String relatived0 = f.getName(); + String name0 = relatived0.substring(0, relatived0.length() - ".class".length()); + Matcher m = pat.matcher(name0); + if (m.matches()) { + String name = packageName + '.' + name0; + if (!ret.contains(name)) { + ret.add(name); + } + } + } + } + + private static List<Class<?>> toClass(List<String> classNames) + throws ClassNotFoundException { + List<Class<?>> ret = new ArrayList<Class<?>>(classNames.size()); + ClassLoader cl = TemplatePrecompiler.class.getClassLoader(); + for (String className : classNames) { + Class<?> c = cl.loadClass(className); + ret.add(c); + } + return ret; + } + + public static void saveTemplateClasses(TemplateRegistry registry, Class<?>[] targetClasses) + throws IOException { + for (Class<?> c : targetClasses) { + saveTemplateClass(registry, c); + } + } + + public static void saveTemplateClass(TemplateRegistry registry, Class<?> targetClass) + throws IOException { + LOG.info("Saving template of " + targetClass.getName() + "..."); + Properties props = System.getProperties(); + String distDirName = getDirName(props, DEST, DEFAULT_DEST); + if (targetClass.isEnum()) { + throw new UnsupportedOperationException( + "Not supported enum type yet: " + targetClass.getName()); + } else { + new JavassistTemplateBuilder(registry).writeTemplate(targetClass, + distDirName); + } + LOG.info("Saved .class file of template class of " + targetClass.getName()); + } + + public static boolean deleteTemplateClass(Class<?> targetClass) + throws IOException { + LOG.info("Deleting template of " + targetClass.getName() + "..."); + Properties props = System.getProperties(); + String distDirName = getDirName(props, DEST, DEFAULT_DEST); + String targetClassName = targetClass.getName(); + String targetClassFileName = targetClassName.replace('.', + File.separatorChar) + "_$$_Template.class"; + File targetFile = new File(distDirName + File.separatorChar + + targetClassFileName); + boolean deleted = false; + if (!targetFile.isDirectory() && targetFile.exists()) { + deleted = targetFile.delete(); + } + LOG.info("Deleted .class file of template class of " + targetClass.getName()); + return deleted; + } + + private static String getDirName(Properties props, String dirName, String defaultDirName) + throws IOException { + String dName = props.getProperty(dirName, defaultDirName); + File d = new File(dName); + if (!d.isDirectory() && !d.exists()) { + throw new IOException("Directory not exists: " + dName); + } + return d.getAbsolutePath(); + } + + public static void main(final String[] args) throws Exception { + TemplatePrecompiler.saveTemplates(args); + } +}