comparison src/main/java/org/msgpack/template/builder/DefaultBuildContext.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.template.builder;
19
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Modifier;
24
25 import org.msgpack.*;
26 import org.msgpack.packer.Packer;
27 import org.msgpack.template.*;
28 import org.msgpack.unpacker.Unpacker;
29
30 import javassist.CannotCompileException;
31 import javassist.CtClass;
32 import javassist.CtConstructor;
33 import javassist.CtNewConstructor;
34 import javassist.NotFoundException;
35
36 @SuppressWarnings({ "rawtypes", "unchecked" })
37 public class DefaultBuildContext extends BuildContext<FieldEntry> {
38 protected FieldEntry[] entries;
39
40 protected Class<?> origClass;
41
42 protected String origName;
43
44 protected Template<?>[] templates;
45
46 public DefaultBuildContext(JavassistTemplateBuilder director) {
47 super(director);
48 }
49
50 public Template buildTemplate(Class targetClass, FieldEntry[] entries,
51 Template[] templates) {
52 this.entries = entries;
53 this.templates = templates;
54 this.origClass = targetClass;
55 this.origName = origClass.getName();
56 return build(origName);
57 }
58
59 protected void setSuperClass() throws CannotCompileException, NotFoundException {
60 tmplCtClass.setSuperclass(director.getCtClass(
61 JavassistTemplateBuilder.JavassistTemplate.class.getName()));
62 }
63
64 protected void buildConstructor() throws CannotCompileException,
65 NotFoundException {
66 // Constructor(Class targetClass, Template[] templates)
67 CtConstructor newCtCons = CtNewConstructor.make(
68 new CtClass[] {
69 director.getCtClass(Class.class.getName()),
70 director.getCtClass(Template.class.getName() + "[]")
71 }, new CtClass[0], tmplCtClass);
72 tmplCtClass.addConstructor(newCtCons);
73 }
74
75 protected Template buildInstance(Class<?> c) throws NoSuchMethodException,
76 InstantiationException, IllegalAccessException,
77 InvocationTargetException {
78 Constructor<?> cons = c.getConstructor(new Class[] { Class.class, Template[].class });
79 Object tmpl = cons.newInstance(new Object[] { origClass, templates });
80 return (Template) tmpl;
81 }
82
83 protected void buildMethodInit() {
84 }
85
86 protected String buildWriteMethodBody() {
87 resetStringBuilder();
88 buildString("\n{\n");
89
90 buildString(" if ($2 == null) {\n");
91 buildString(" if ($3) {\n");
92 buildString(" throw new %s(\"Attempted to write null\");\n", MessageTypeException.class.getName());
93 buildString(" }\n");
94 buildString(" $1.writeNil();\n");
95 buildString(" return;\n");
96 buildString(" }\n");
97
98 buildString(" %s _$$_t = (%s) $2;\n", origName, origName);
99 buildString(" $1.writeArrayBegin(%d);\n", entries.length);
100
101 for (int i = 0; i < entries.length; i++) {
102 FieldEntry e = entries[i];
103 if (!e.isAvailable()) {
104 buildString(" $1.writeNil();\n");
105 continue;
106 }
107 DefaultFieldEntry de = (DefaultFieldEntry) e;
108 boolean isPrivate = Modifier.isPrivate(de.getField().getModifiers());
109 Class<?> type = de.getType();
110 if (type.isPrimitive()) { // primitive types
111 if (!isPrivate) {
112 buildString(" $1.%s(_$$_t.%s);\n", primitiveWriteName(type), de.getName());
113 } else {
114 buildString(
115 " %s.writePrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
116 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
117 }
118 } else { // reference types
119 if (!isPrivate) {
120 buildString(" if (_$$_t.%s == null) {\n", de.getName());
121 } else {
122 buildString(
123 " if (%s.readPrivateField(_$$_t, %s.class, \"%s\") == null) {\n",
124 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName());
125 }
126 if (de.isNotNullable()) {
127 buildString(
128 " throw new %s(\"%s cannot be null by @NotNullable\");\n",
129 MessageTypeException.class.getName(), de.getName());
130 } else {
131 buildString(" $1.writeNil();\n");
132 }
133 buildString(" } else {\n");
134 if (!isPrivate) {
135 buildString(" templates[%d].write($1, _$$_t.%s);\n", i, de.getName());
136 } else {
137 buildString(
138 " %s.writePrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
139 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
140 }
141 buildString(" }\n");
142 }
143 }
144
145 buildString(" $1.writeArrayEnd();\n");
146 buildString("}\n");
147 return getBuiltString();
148 }
149
150 public static Object readPrivateField(Object target, Class targetClass, String fieldName) {
151 Field field = null;
152 try {
153 field = targetClass.getDeclaredField(fieldName);
154 field.setAccessible(true);
155 Object valueReference = field.get(target);
156 return valueReference;
157 } catch (Exception e) {
158 throw new MessageTypeException(e);
159 } finally {
160 if (field != null) {
161 field.setAccessible(false);
162 }
163 }
164 }
165
166 public static void writePrivateField(Packer packer, Object target,
167 Class targetClass, String fieldName, Template tmpl) {
168 Field field = null;
169 try {
170 field = targetClass.getDeclaredField(fieldName);
171 field.setAccessible(true);
172 Object valueReference = field.get(target);
173 tmpl.write(packer, valueReference);
174 } catch (Exception e) {
175 throw new MessageTypeException(e);
176 } finally {
177 if (field != null) {
178 field.setAccessible(false);
179 }
180 }
181 }
182
183 protected String buildReadMethodBody() {
184 resetStringBuilder();
185 buildString("\n{\n");
186
187 buildString(" if (!$3 && $1.trySkipNil()) {\n");
188 buildString(" return null;\n");
189 buildString(" }\n");
190
191 buildString(" %s _$$_t;\n", origName);
192 buildString(" if ($2 == null) {\n");
193 buildString(" _$$_t = new %s();\n", origName);
194 buildString(" } else {\n");
195 buildString(" _$$_t = (%s) $2;\n", origName);
196 buildString(" }\n");
197 buildString(" $1.readArrayBegin();\n");
198
199 int i;
200 for (i = 0; i < entries.length; i++) {
201 FieldEntry e = entries[i];
202 if (!e.isAvailable()) {
203 buildString(" $1.skip();\n");
204 continue;
205 }
206
207 if (e.isOptional()) {
208 buildString(" if ($1.trySkipNil()) {");
209 // if Optional and nil, then keep default value
210 buildString(" } else {\n");
211 }
212
213 DefaultFieldEntry de = (DefaultFieldEntry) e;
214 boolean isPrivate = Modifier.isPrivate(de.getField().getModifiers());
215 Class<?> type = de.getType();
216 if (type.isPrimitive()) {
217 if (!isPrivate) {
218 buildString(" _$$_t.%s = $1.%s();\n", de.getName(), primitiveReadName(type));
219 } else {
220 buildString(
221 " %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
222 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
223 }
224 } else {
225 if (!isPrivate) {
226 buildString(
227 " _$$_t.%s = (%s) this.templates[%d].read($1, _$$_t.%s);\n",
228 de.getName(), de.getJavaTypeName(), i, de.getName());
229 } else {
230 buildString(
231 " %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
232 DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
233 }
234 }
235
236 if (de.isOptional()) {
237 buildString(" }\n");
238 }
239 }
240
241 buildString(" $1.readArrayEnd();\n");
242 buildString(" return _$$_t;\n");
243
244 buildString("}\n");
245 return getBuiltString();
246 }
247
248 public static void readPrivateField(Unpacker unpacker, Object target,
249 Class targetClass, String fieldName, Template tmpl) {
250 Field field = null;
251 try {
252 field = targetClass.getDeclaredField(fieldName);
253 field.setAccessible(true);
254 Object fieldReference = field.get(target);
255 Object valueReference = tmpl.read(unpacker, fieldReference);
256 if (valueReference != fieldReference) {
257 field.set(target, valueReference);
258 }
259 } catch (Exception e) {
260 throw new MessageTypeException(e);
261 } finally {
262 if (field != null) {
263 field.setAccessible(false);
264 }
265 }
266 }
267
268 @Override
269 public void writeTemplate(Class<?> targetClass, FieldEntry[] entries,
270 Template[] templates, String directoryName) {
271 this.entries = entries;
272 this.templates = templates;
273 this.origClass = targetClass;
274 this.origName = origClass.getName();
275 write(origName, directoryName);
276 }
277
278 @Override
279 public Template loadTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) {
280 this.entries = entries;
281 this.templates = templates;
282 this.origClass = targetClass;
283 this.origName = origClass.getName();
284 return load(origName);
285 }
286 }