From 27b89b237bb8aded199fb89dce40ca89924540e4 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Mon, 4 Apr 2011 01:59:13 +0900 Subject: [PATCH] java: prototyped TemplateClassWriter, which is program for writing class file of generated tmplate class --- .../main/java/org/msgpack/MessagePack.java | 7 +- .../template/JavassistTemplateBuilder.java | 114 ++++++++++++++++-- .../template/ReflectionTemplateBuilder.java | 31 ++++- .../org/msgpack/template/TemplateBuilder.java | 79 +++++++++++- .../msgpack/template/TemplateClassWriter.java | 28 +++++ .../msgpack/template/TemplateRegistry.java | 8 +- 6 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 java/src/main/java/org/msgpack/template/TemplateClassWriter.java diff --git a/java/src/main/java/org/msgpack/MessagePack.java b/java/src/main/java/org/msgpack/MessagePack.java index f3a73c06..4bb5d2ca 100644 --- a/java/src/main/java/org/msgpack/MessagePack.java +++ b/java/src/main/java/org/msgpack/MessagePack.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import org.msgpack.template.TemplateRegistry; import org.msgpack.template.TemplateBuilder; +import org.msgpack.template.TemplateClassWriter; import org.msgpack.template.FieldList; public class MessagePack { @@ -146,6 +147,10 @@ public class MessagePack { } } + public static void write(Class target, String directoryName) { + TemplateClassWriter.write(target, directoryName); + } + public static void register(Class target) { TemplateRegistry.register(target); } diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java index a4d2e4db..a4ef98ff 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -122,9 +122,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder { this.director = director; } + protected void write(final String className, final String directoryName) { + try { + reset(className, false); + buildClass(); + buildConstructor(); + buildMethodInit(); + buildPackMethod(); + buildUnpackMethod(); + buildConvertMethod(); + writeClassFile(directoryName); + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } + protected void writeClassFile(final String directoryName) throws CannotCompileException, IOException { + tmplCtClass.writeFile(directoryName); + } + protected Template build(final String className) { try { - reset(className); + reset(className, true); buildClass(); buildConstructor(); buildMethodInit(); @@ -143,8 +167,12 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } - protected void reset(String className) { - tmplName = className + "_$$_Template" + director.nextSeqId(); + protected void reset(String className, boolean isBuilt) { + if (isBuilt) { + tmplName = className + "_$$_Template" + director.nextSeqId(); + } else { + tmplName = className + "_$$_Template"; + } tmplCtClass = director.makeCtClass(tmplName); } @@ -254,6 +282,15 @@ public class JavassistTemplateBuilder extends TemplateBuilder { super(director); } + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, + Template[] templates, final String directoryName) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + write(this.origName, directoryName); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries, Template[] templates) { this.entries = entries; this.templates = templates; @@ -279,6 +316,22 @@ public class JavassistTemplateBuilder extends TemplateBuilder { this.tmplCtClass.addConstructor(newCtCons); } + protected Template buildInstance(Class targetClass, Class tmplClass, Template[] tmpls) { + try { + Constructor cons = tmplClass.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + targetClass, + tmpls + }); + return (Template)tmpl; + } catch (Exception e) { + throw new TemplateBuildException(e); + } + } + protected Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Constructor cons = c.getConstructor(new Class[] { Class.class, @@ -544,7 +597,39 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } + @Override + public Class loadTemplateClass(Class targetClass) { + String tmplClassName = targetClass.getName() + "_$$_Template"; + ClassLoader cl = this.getClass().getClassLoader();// TODO + try { + return cl.loadClass(tmplClassName); + } catch (ClassNotFoundException e) { + LOG.debug("Tmplate class not found: " + tmplClassName); + return null; + } + } + + @Override + public Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + return bc.buildInstance(targetClass, tmplClass, tmpls); + } + + @Override + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, String directoryName) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + bc.writeTemplateClass(targetClass, entries, tmpls, directoryName); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + return bc.buildTemplate(targetClass, entries, tmpls); + } + + private static Template[] toTemplates(FieldEntry[] from) { // FIXME private / packagefields //for(FieldEntry e : entries) { // Field f = e.getField(); @@ -554,9 +639,9 @@ public class JavassistTemplateBuilder extends TemplateBuilder { // } //} - Template[] tmpls = new Template[entries.length]; - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + Template[] tmpls = new Template[from.length]; + for(int i=0; i < from.length; i++) { + FieldEntry e = from[i]; if(!e.isAvailable()) { tmpls[i] = null; } else { @@ -564,9 +649,7 @@ public class JavassistTemplateBuilder extends TemplateBuilder { tmpls[i] = tmpl; } } - - BuildContext bc = new BuildContext(this); - return bc.buildTemplate(targetClass, entries, tmpls); + return tmpls; } static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate { @@ -575,10 +658,21 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { return new JavassistOrdinalEnumTemplate(entries); } + @Override + public void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");//TODO + } + public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { if(dim == 1) { if(baseClass == boolean.class) { diff --git a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java index 03ff2067..e48bceac 100644 --- a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -373,6 +373,22 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public Class loadTemplateClass(Class targetClass) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + + @Override + public Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + + @Override + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, + String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries) { for(FieldEntry e : entries) { Field f = e.getField(); @@ -448,11 +464,16 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeOrdinalEnumTemplateClass(Class targetClass, + Enum[] entires, String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { return new ReflectionOrdinalEnumTemplate(entries); } - static class ReflectionObjectArrayTemplate extends AbstractTemplate { private Class componentClass; private Template elementTemplate; @@ -536,6 +557,12 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { if(dim == 1) { if(baseClass == boolean.class) { diff --git a/java/src/main/java/org/msgpack/template/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/TemplateBuilder.java index e3d25b29..f0a32089 100644 --- a/java/src/main/java/org/msgpack/template/TemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/TemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -107,37 +107,81 @@ public abstract class TemplateBuilder { } } + // Override this method + public abstract Class loadTemplateClass(Class targetClass); + + // Override this method + public abstract Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries); + + // Override this method + public abstract void writeTemplateClass(Class targetClass, FieldEntry[] entries, String directoryName); + // Override this method public abstract Template buildTemplate(Class targetClass, FieldEntry[] entries); + // Override this method + public abstract void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName); + // Override this method public abstract Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries); + // Override this method + public abstract void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName); + // Override this method public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim); + public Template initializeTemplate(Class targetClass, Class tmplClass) { + return initializeTemplate(targetClass, tmplClass, readFieldEntries(targetClass, readImplicitFieldOption(targetClass))); + } + + public void writeTemplateClass(Class targetClass, FieldList fList, String directoryName) throws NoSuchFieldException { + checkValidation(targetClass); + writeTemplateClass(targetClass, convertFieldEntries(targetClass, fList), directoryName); + } public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { checkValidation(targetClass); return buildTemplate(targetClass, convertFieldEntries(targetClass, flist)); } + public void writeTemplateClass(Class targetClass, FieldOption implicitOption, String directoryName) { + checkValidation(targetClass); + writeTemplateClass(targetClass, readFieldEntries(targetClass, implicitOption), directoryName); + } + public Template buildTemplate(Class targetClass, FieldOption implicitOption) { checkValidation(targetClass); return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption)); } + public void writeTemplateClass(Class targetClass, final String directoryName) { + FieldOption implicitOption = readImplicitFieldOption(targetClass); + writeTemplateClass(targetClass, implicitOption, directoryName); + } + public Template buildTemplate(Class targetClass) { FieldOption implicitOption = readImplicitFieldOption(targetClass); return buildTemplate(targetClass, implicitOption); } + public void writeOrdinalEnumTemplateClass(Class targetClass, String directoryName) { + checkOrdinalEnumValidation(targetClass); + Enum[] entries = (Enum[])targetClass.getEnumConstants(); + writeOrdinalEnumTemplateClass(targetClass, entries, directoryName); + } + public Template buildOrdinalEnumTemplate(Class targetClass) { checkOrdinalEnumValidation(targetClass); Enum[] entries = (Enum[])targetClass.getEnumConstants(); return buildOrdinalEnumTemplate(targetClass, entries); } + public void writeArrayTemplateClass(Type arrayType, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public Template buildArrayTemplate(Type arrayType) { Type baseType; Class baseClass; @@ -195,22 +239,51 @@ public abstract class TemplateBuilder { instance = builder; } + public static Class load(Class targetClass) { + return instance.loadTemplateClass(targetClass); + } + + public static Template initialize(Class targetClass, Class tmplClass) { + return instance.initializeTemplate(targetClass, tmplClass); + } + + public static void writeClass(Class targetClass, String directoryName) { + instance.writeTemplateClass(targetClass, directoryName); + } + public static Template build(Class targetClass) { return instance.buildTemplate(targetClass); } + public static void writeClass(Class targetClass, FieldOption implicitOption, String directoryName) { + instance.writeTemplateClass(targetClass, implicitOption, directoryName); + } + public static Template build(Class targetClass, FieldOption implicitOption) { return instance.buildTemplate(targetClass, implicitOption); } - public static Template build(Class targetClass, FieldList flist) throws NoSuchFieldException { - return instance.buildTemplate(targetClass, flist); + public static void writeClass(Class targetClass, FieldList fList, String directoryName) + throws NoSuchFieldException { + instance.writeTemplateClass(targetClass, fList, directoryName); + } + + public static Template build(Class targetClass, FieldList fList) throws NoSuchFieldException { + return instance.buildTemplate(targetClass, fList); + } + + public static void writeOrdinalEnumClass(Class targetClass, String directoryName) { + instance.writeOrdinalEnumTemplateClass(targetClass, directoryName); } public static Template buildOrdinalEnum(Class targetClass) { return instance.buildOrdinalEnumTemplate(targetClass); } + public static void writeArrayClass(Type arrayType, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public static Template buildArray(Type arrayType) { return instance.buildArrayTemplate(arrayType); } diff --git a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java new file mode 100644 index 00000000..2ead9048 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java @@ -0,0 +1,28 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2011 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.template; + +public class TemplateClassWriter { + public static void write(Class target, String directoryName) { + if(target.isEnum()) { + throw new UnsupportedOperationException("Not supported yet."); + } else { + TemplateBuilder.writeClass(target, directoryName); + } + } +} diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index 3f98fb46..ef377efa 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackDelegate; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.Template; -import org.msgpack.Templates; public class TemplateRegistry { private static Map map; @@ -111,6 +110,11 @@ public class TemplateRegistry { Class target = (Class)targetType; + Class tmplClass = TemplateBuilder.load(target); + if (tmplClass != null) { + return TemplateBuilder.initialize(target, tmplClass); + } + if(target.isArray()) { // FIXME can't distinguish type-erased T<>[]? tmpl = TemplateBuilder.buildArray(target);