0
|
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.template.builder;
|
|
19
|
|
20 import java.lang.Thread;
|
|
21 import java.lang.reflect.Type;
|
|
22 import java.util.logging.Level;
|
|
23 import java.util.logging.Logger;
|
|
24
|
|
25 import javassist.ClassPool;
|
|
26 import javassist.CtClass;
|
|
27 import javassist.LoaderClassPath;
|
|
28 import javassist.NotFoundException;
|
|
29
|
|
30 import org.msgpack.template.FieldOption;
|
|
31 import org.msgpack.template.Template;
|
|
32 import org.msgpack.template.AbstractTemplate;
|
|
33 import org.msgpack.template.TemplateRegistry;
|
|
34
|
|
35 @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
36 public class JavassistTemplateBuilder extends AbstractTemplateBuilder {
|
|
37
|
|
38 private static Logger LOG = Logger.getLogger(JavassistTemplateBuilder.class.getName());
|
|
39
|
|
40 public static abstract class JavassistTemplate<T> extends AbstractTemplate<T> {
|
|
41 public Class<T> targetClass;
|
|
42 public Template<?>[] templates;
|
|
43
|
|
44 public JavassistTemplate(Class<T> targetClass, Template<?>[] templates) {
|
|
45 this.targetClass = targetClass;
|
|
46 this.templates = templates;
|
|
47 }
|
|
48 }
|
|
49
|
|
50 protected ClassPool pool;
|
|
51
|
|
52 protected int seqId = 0;
|
|
53
|
|
54 public JavassistTemplateBuilder(TemplateRegistry registry) {
|
|
55 super(registry);
|
|
56 pool = new ClassPool();
|
|
57 boolean appended = false;
|
|
58 ClassLoader cl = null;
|
|
59 try {
|
|
60 cl = Thread.currentThread().getContextClassLoader();
|
|
61 if (cl != null) {
|
|
62 pool.appendClassPath(new LoaderClassPath(cl));
|
|
63 appended = true;
|
|
64 }
|
|
65 } catch (SecurityException e) {
|
|
66 LOG.fine("Cannot append a search path of context classloader");
|
|
67 e.printStackTrace();
|
|
68 }
|
|
69 try {
|
|
70 ClassLoader cl2 = getClass().getClassLoader();
|
|
71 if (cl2 != null && cl2 != cl) {
|
|
72 pool.appendClassPath(new LoaderClassPath(cl2));
|
|
73 appended = true;
|
|
74 }
|
|
75 } catch (SecurityException e) {
|
|
76 LOG.fine("Cannot append a search path of classloader");
|
|
77 e.printStackTrace();
|
|
78 }
|
|
79 if (!appended) {
|
|
80 pool.appendSystemPath();
|
|
81 }
|
|
82 }
|
|
83
|
|
84 @Override
|
|
85 public boolean matchType(Type targetType, boolean hasAnnotation) {
|
|
86 Class<?> targetClass = (Class<?>) targetType;
|
|
87 boolean matched = matchAtClassTemplateBuilder(targetClass, hasAnnotation);
|
|
88 if (matched && LOG.isLoggable(Level.FINE)) {
|
|
89 LOG.fine("matched type: " + targetClass.getName());
|
|
90 }
|
|
91 return matched;
|
|
92 }
|
|
93
|
|
94 public void addClassLoader(ClassLoader cl) {
|
|
95 pool.appendClassPath(new LoaderClassPath(cl));
|
|
96 }
|
|
97
|
|
98 protected CtClass makeCtClass(String className) {
|
|
99 return pool.makeClass(className);
|
|
100 }
|
|
101
|
|
102 protected CtClass getCtClass(String className) throws NotFoundException {
|
|
103 return pool.get(className);
|
|
104 }
|
|
105
|
|
106 protected int nextSeqId() {
|
|
107 return seqId++;
|
|
108 }
|
|
109
|
|
110 protected BuildContext createBuildContext() {
|
|
111 return new DefaultBuildContext(this);
|
|
112 }
|
|
113
|
|
114 @Override
|
|
115 public <T> Template<T> buildTemplate(Class<T> targetClass, FieldEntry[] entries) {
|
|
116 Template<?>[] tmpls = toTemplate(entries);
|
|
117 BuildContext bc = createBuildContext();
|
|
118 return bc.buildTemplate(targetClass, entries, tmpls);
|
|
119 }
|
|
120
|
|
121 private Template<?>[] toTemplate(FieldEntry[] from) {
|
|
122 Template<?>[] tmpls = new Template<?>[from.length];
|
|
123 for (int i = 0; i < from.length; ++i) {
|
|
124 FieldEntry e = from[i];
|
|
125 if (!e.isAvailable()) {
|
|
126 tmpls[i] = null;
|
|
127 } else {
|
|
128 Template<?> tmpl = registry.lookup(e.getGenericType());
|
|
129 tmpls[i] = tmpl;
|
|
130 }
|
|
131 }
|
|
132 return tmpls;
|
|
133 }
|
|
134
|
|
135 @Override
|
|
136 public void writeTemplate(Type targetType, String directoryName) {
|
|
137 Class<?> targetClass = (Class<?>) targetType;
|
|
138 checkClassValidation(targetClass);
|
|
139 FieldOption implicitOption = getFieldOption(targetClass);
|
|
140 FieldEntry[] entries = toFieldEntries(targetClass, implicitOption);
|
|
141 writeTemplate(targetClass, entries, directoryName);
|
|
142 }
|
|
143
|
|
144 private void writeTemplate(Class<?> targetClass, FieldEntry[] entries, String directoryName) {
|
|
145 Template[] tmpls = toTemplate(entries);
|
|
146 BuildContext bc = createBuildContext();
|
|
147 bc.writeTemplate(targetClass, entries, tmpls, directoryName);
|
|
148 }
|
|
149
|
|
150 @Override
|
|
151 public <T> Template<T> loadTemplate(Type targetType) {
|
|
152 // FIXME #MN must consider how to load "reference cycle class" in next
|
|
153 // version
|
|
154 Class<T> targetClass = (Class) targetType;
|
|
155 //checkClassValidation(targetClass);
|
|
156 try {
|
|
157 // check loadable
|
|
158 String tmplName = targetClass.getName() + "_$$_Template";
|
|
159 ClassLoader cl = targetClass.getClassLoader();
|
|
160 if (cl != null) {
|
|
161 cl.loadClass(tmplName);
|
|
162 } else {
|
|
163 return null;
|
|
164 }
|
|
165 } catch (ClassNotFoundException e) {
|
|
166 return null;
|
|
167 }
|
|
168 FieldOption implicitOption = getFieldOption(targetClass);
|
|
169 FieldEntry[] entries = toFieldEntries(targetClass, implicitOption);
|
|
170 Template<?>[] tmpls = toTemplate(entries);
|
|
171 BuildContext bc = createBuildContext();
|
|
172 return bc.loadTemplate(targetClass, entries, tmpls);
|
|
173 }
|
|
174 }
|