java: Merged takezoux2's branch for 'MessagePack for Scala'

This commit is contained in:
Muga Nishizawa
2011-04-06 00:50:58 +09:00
62 changed files with 12109 additions and 873 deletions

17
java/msgpack.iml Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
</component>
</module>

View File

@@ -81,6 +81,20 @@
<connectionUrl>scm:git://github.com/msgpack/msgpack.git</connectionUrl>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -132,12 +146,14 @@
<id>msgpack.org</id>
<name>Repository at msgpack.org</name>
<url>file://${project.build.directory}/website/maven2/</url>
<!--<url>${deploy-release-url}</url>-->
</repository>
<snapshotRepository>
<uniqueVersion>true</uniqueVersion>
<id>msgpack.org</id>
<name>Repository at msgpack.org</name>
<url>file://${project.build.directory}/website/maven2/</url>
<!--<url>${deploy-snapshot-url}</url>-->
</snapshotRepository>
</distributionManagement>

View File

@@ -22,7 +22,6 @@ import java.io.InputStream;
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;

View File

@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ignore {
}

View File

@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Index {
int value();

View File

@@ -0,0 +1,35 @@
//
// 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.msgpack.template.FieldOption;
/**
* Annotation for java beans class
* @author takeshita
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessagePackBeans {
FieldOption value() default FieldOption.DEFAULT;
}

View File

@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Nullable {
}

View File

@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Optional {
}

View File

@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Required {
}

View File

@@ -0,0 +1,143 @@
//
// 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;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import org.msgpack.*;
/**
* Field entry for Java beans property.
* @author takeshita
*
*/
public class BeansFieldEntry implements IFieldEntry {
PropertyDescriptor desc;
FieldOption option = FieldOption.DEFAULT;
public BeansFieldEntry(PropertyDescriptor desc) {
this.desc = desc;
}
@Override
public String getName() {
return desc.getDisplayName();
}
public String getGetterName(){
return desc.getReadMethod().getName();
}
public String getSetterName(){
return desc.getWriteMethod().getName();
}
@Override
public Class<?> getType() {
return desc.getPropertyType();
}
@Override
public String getJavaTypeName() {
Class<?> type = getType();
if(type.isArray()) {
return arrayTypeToString(type);
} else {
return type.getName();
}
}
static String arrayTypeToString(Class<?> type) {
int dim = 1;
Class<?> baseType = type.getComponentType();
while(baseType.isArray()) {
baseType = baseType.getComponentType();
dim += 1;
}
StringBuilder sb = new StringBuilder();
sb.append(baseType.getName());
for (int i = 0; i < dim; ++i) {
sb.append("[]");
}
return sb.toString();
}
@Override
public Type getGenericType() {
return desc.getReadMethod().getGenericReturnType();
}
@Override
public FieldOption getOption() {
return option;
}
public void setOption(FieldOption option){
this.option = option;
}
@Override
public boolean isAvailable() {
return option != FieldOption.IGNORE;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isRequired()
*/
@Override
public boolean isRequired() {
return option == FieldOption.REQUIRED;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isOptional()
*/
@Override
public boolean isOptional() {
return option == FieldOption.OPTIONAL;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isNullable()
*/
@Override
public boolean isNullable() {
return option == FieldOption.NULLABLE;
}
public Object get(Object target){
try {
return desc.getReadMethod().invoke(target);
} catch (IllegalArgumentException e) {
throw new MessageTypeException(e);
} catch (IllegalAccessException e) {
throw new MessageTypeException(e);
} catch (InvocationTargetException e) {
throw new MessageTypeException(e);
}
}
public void set(Object target , Object value){
try {
desc.getWriteMethod().invoke(target, value);
} catch (IllegalArgumentException e) {
throw new MessageTypeException(e);
} catch (IllegalAccessException e) {
throw new MessageTypeException(e);
} catch (InvocationTargetException e) {
throw new MessageTypeException(e);
}
}
}

View File

@@ -0,0 +1,188 @@
//
// 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;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.msgpack.annotation.Ignore;
import org.msgpack.annotation.Index;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.Nullable;
import org.msgpack.annotation.Optional;
import org.msgpack.annotation.Required;
/**
* List up Java beans property methods.
* @author takeshita
*
*/
public class BeansFieldEntryReader implements IFieldEntryReader{
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
List<FieldList.Entry> src = flist.getList();
FieldEntry[] result = new FieldEntry[src.size()];
for(int i=0; i < src.size(); i++) {
FieldList.Entry s = src.get(i);
if(s.isAvailable()) {
result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
} else {
result[i] = new FieldEntry();
}
}
return result;
}
@Override
public IFieldEntry[] readFieldEntries(Class<?> targetClass,
FieldOption implicitOption) {
BeanInfo desc;
try {
desc = Introspector.getBeanInfo(targetClass);
} catch (IntrospectionException e1) {
throw new TemplateBuildException("Class must be java beans class:" + targetClass.getName());
}
PropertyDescriptor[] props = desc.getPropertyDescriptors();
ArrayList<PropertyDescriptor> list = new ArrayList<PropertyDescriptor>();
for(int i = 0;i < props.length;i++){
PropertyDescriptor pd = props[i];
if(!isIgnoreProp(pd)){
list.add(pd);
}
}
props = new PropertyDescriptor[list.size()];
list.toArray(props);
BeansFieldEntry[] entries = new BeansFieldEntry[props.length];
for(int i = 0;i < props.length;i++){
PropertyDescriptor p = props[i];
int index = readPropIndex(p);
if(index >= 0){
if(entries[index] != null){
throw new TemplateBuildException("duplicated index: "+index);
}
if(index >= entries.length){
throw new TemplateBuildException("invalid index: "+index);
}
entries[index] = new BeansFieldEntry(p);
props[index] = null;
}
}
int insertIndex = 0;
for(int i = 0;i < props.length;i++){
PropertyDescriptor p = props[i];
if(p != null){
while(entries[insertIndex] != null){
insertIndex++;
}
entries[insertIndex] = new BeansFieldEntry(p);
}
}
for(int i = 0;i < entries.length;i++){
BeansFieldEntry e = entries[i];
FieldOption op = readPropOption(e.desc, implicitOption);
e.setOption(op);
}
return entries;
}
public FieldOption readImplicitFieldOption(Class<?> targetClass) {
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
if(a == null) {
return FieldOption.DEFAULT;
}
return a.value();
}
private FieldOption readPropOption(PropertyDescriptor desc, FieldOption implicitOption) {
FieldOption forGetter = readMethodOption(desc.getReadMethod());
if(forGetter != FieldOption.DEFAULT){
return forGetter;
}
FieldOption forSetter = readMethodOption(desc.getWriteMethod());
if(forSetter != FieldOption.DEFAULT){
return forSetter;
}else{
return implicitOption;
}
}
private FieldOption readMethodOption(Method method){
if(isAnnotated(method, Ignore.class)) {
return FieldOption.IGNORE;
} else if(isAnnotated(method, Required.class)) {
return FieldOption.REQUIRED;
} else if(isAnnotated(method, Optional.class)) {
return FieldOption.OPTIONAL;
} else if(isAnnotated(method, Nullable.class)) {
if(method.getDeclaringClass().isPrimitive()) {
return FieldOption.REQUIRED;
} else {
return FieldOption.NULLABLE;
}
}
return FieldOption.DEFAULT;
}
private int readPropIndex(PropertyDescriptor desc) {
int forGetter = readMethodIndex(desc.getReadMethod());
if(forGetter >= 0){
return forGetter;
}
int forSetter = readMethodIndex(desc.getWriteMethod());
return forSetter;
}
private int readMethodIndex(Method method){
Index a = method.getAnnotation(Index.class);
if(a == null) {
return -1;
} else {
return a.value();
}
}
private boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
boolean isIgnoreProp(PropertyDescriptor desc){
if(desc == null)return true;
Method getter = desc.getReadMethod();
Method setter = desc.getWriteMethod();
return getter == null ||
setter == null ||
!Modifier.isPublic(getter.getModifiers()) ||
!Modifier.isPublic(setter.getModifiers()) ||
isAnnotated(getter,Ignore.class) ||
isAnnotated(setter, Ignore.class);
}
}

View File

@@ -0,0 +1,338 @@
//
// 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;
import java.io.IOException;
import java.lang.reflect.Field;
import org.msgpack.AbstractTemplate;
import org.msgpack.MessagePackObject;
import org.msgpack.MessageTypeException;
import org.msgpack.Packer;
import org.msgpack.Template;
import org.msgpack.Unpacker;
import org.msgpack.template.ReflectionTemplateBuilder.BooleanFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.ByteFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.DoubleFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.FloatFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.IntFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.LongFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.NullFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.ObjectFieldEntry;
import org.msgpack.template.ReflectionTemplateBuilder.ShortFieldEntry;
import org.msgpack.template.builder.CustomTemplateBuilder;
/**
* Class for building java reflection template builder for java beans class.
* @author takeshita
*
*/
public class BeansReflectionTemplateBuilder extends CustomTemplateBuilder{
IFieldEntryReader reader = new BeansFieldEntryReader();
public BeansReflectionTemplateBuilder(){}
@Override
public IFieldEntryReader getFieldEntryReader(){
return reader;
}
static class ReflectionEntry{
BeansFieldEntry entry;
public ReflectionEntry(BeansFieldEntry entry){
this.entry = entry;
}
public void pack(Object value , Packer packer) throws IOException{
packer.pack(value);
}
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
entry.set(target, obj.convert(entry.getType()));
}
public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException {
entry.set(target, unpacker.unpack(entry.getType()));
}
public void setNull(Object target){
entry.set(target, null);
}
public boolean isRequired(){
return entry.isRequired();
}
public boolean isNullable(){
return entry.isNullable();
}
public boolean isAvailable(){
return entry.isAvailable();
}
public boolean isOptional(){
return entry.isOptional();
}
public Object get(Object target){
return entry.get(target);
}
}
static class ObjectFieldEntry extends ReflectionEntry{
Template template;
public ObjectFieldEntry(BeansFieldEntry entry,Template template){
super(entry);
this.template = template;
}
public void pack(Object value , Packer packer) throws IOException{
template.pack(packer,value);
}
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
Class<Object> type = (Class<Object>)entry.getType();
Object fieldReference = entry.get(target);
Object valueReference = template.convert(obj, fieldReference);
if(valueReference != fieldReference) {
entry.set(target, valueReference);
}
}
public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException {
Class<Object> type = (Class<Object>)entry.getType();
Object fieldReference = entry.get(target);
Object valueReference = template.unpack(unpacker, fieldReference);
if(valueReference != fieldReference) {
entry.set(target, valueReference);
}
}
}
static class BeansReflectionTemplate extends AbstractTemplate{
Class<?> targetClass;
ReflectionEntry[] entries = null;
protected int minimumArrayLength;
public BeansReflectionTemplate(
Class<?> targetClass,
ReflectionEntry[] entries){
this.targetClass = targetClass;
this.entries = entries;
this.minimumArrayLength = 0;
for(int i=0; i < entries.length; i++) {
ReflectionEntry e = entries[i];
if(e.isRequired() || e.isNullable()) {
this.minimumArrayLength = i+1;
}
}
}
@Override
public void pack(Packer pk, Object target) throws IOException {
pk.packArray(entries.length);
for(ReflectionEntry e : entries){
if(!e.isAvailable()){
pk.packNil();
continue;
}
Object obj = e.get(target);
if(obj == null) {
if(!e.isNullable() && !e.isOptional()) {
throw new MessageTypeException();
}
pk.packNil();
} else {
pk.pack(obj);
}
}
}
@Override
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
try {
if(to == null) {
to = targetClass.newInstance();
}
int length = pac.unpackArray();
if(length < minimumArrayLength) {
throw new MessageTypeException();
}
int i;
for(i=0; i < minimumArrayLength; i++) {
ReflectionEntry e = entries[i];
if(!e.isAvailable()) {
pac.unpackObject();
continue;
}
if(pac.tryUnpackNull()) {
if(e.isRequired()) {
// Required + nil => exception
throw new MessageTypeException();
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
e.setNull(to);
}
} else {
e.unpack(to,pac);
//e.set(to, pac.unpack(e.getType()));
}
}
int max = length < entries.length ? length : entries.length;
for(; i < max; i++) {
ReflectionEntry e = entries[i];
if(!e.isAvailable()) {
pac.unpackObject();
continue;
}
if(pac.tryUnpackNull()) {
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
} else {
e.unpack(to, pac);
//e.set(to, pac.unpack(e.getType()));
}
}
// latter entries are all Optional + nil => keep default value
for(; i < length; i++) {
pac.unpackObject();
}
return to;
} catch (MessageTypeException e) {
throw e;
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new MessageTypeException(e);
}
}
@Override
public Object convert(MessagePackObject from, Object to)
throws MessageTypeException {
try {
if(to == null) {
to = targetClass.newInstance();
}
MessagePackObject[] array = from.asArray();
int length = array.length;
if(length < minimumArrayLength) {
throw new MessageTypeException();
}
int i;
for(i=0; i < minimumArrayLength; i++) {
ReflectionEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
MessagePackObject obj = array[i];
if(obj.isNil()) {
if(e.isRequired()) {
// Required + nil => exception
throw new MessageTypeException();
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
e.setNull(to);
//e.set(to,null);
}
} else {
e.convert(to, obj);
//e.set(to, from.convert(e.getType()));
}
}
int max = length < entries.length ? length : entries.length;
for(; i < max; i++) {
ReflectionEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
MessagePackObject obj = array[i];
if(obj.isNil()) {
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
} else {
e.convert(to, obj);
//e.set(to, obj.convert(e.getType()));
}
}
// latter entries are all Optional + nil => keep default value
return to;
} catch (MessageTypeException e) {
throw e;
} catch (Exception e) {
throw new MessageTypeException(e);
}
}
}
@Override
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
ReflectionEntry[] refEntries = new ReflectionEntry[entries.length];
for(int i = 0;i < entries.length;i++){
BeansFieldEntry e = (BeansFieldEntry)entries[i];
Class<?> type = e.getType();
if(type.equals(boolean.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(byte.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(short.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(int.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(long.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(float.class)) {
refEntries[i] = new ReflectionEntry(e);
} else if(type.equals(double.class)) {
refEntries[i] = new ReflectionEntry(e);
} else {
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
refEntries[i] = new ObjectFieldEntry(e, tmpl);
}
}
return new BeansReflectionTemplate(targetClass,refEntries);
}
}

View File

@@ -0,0 +1,143 @@
//
// 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;
import java.io.IOException;
import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.List;
import java.util.ArrayList;
import java.util.EnumSet;
import org.msgpack.*;
import org.msgpack.annotation.*;
public class FieldEntry implements IFieldEntry {
private Field field;
private FieldOption option;
public FieldEntry() {
this.field = null;
this.option = FieldOption.IGNORE;
}
public FieldEntry(FieldEntry e) {
this.field = e.field;
this.option = e.option;
}
public FieldEntry(Field field, FieldOption option) {
this.field = field;
this.option = option;
}
public Field getField() {
return field;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#getName()
*/
@Override
public String getName() {
return field.getName();
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#getType()
*/
@Override
public Class<?> getType() {
return field.getType();
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#getJavaTypeName()
*/
@Override
public String getJavaTypeName() {
Class<?> type = field.getType();
if(type.isArray()) {
return arrayTypeToString(type);
} else {
return type.getName();
}
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#getGenericType()
*/
@Override
public Type getGenericType() {
return field.getGenericType();
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#getOption()
*/
@Override
public FieldOption getOption() {
return option;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isAvailable()
*/
@Override
public boolean isAvailable() {
return option != FieldOption.IGNORE;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isRequired()
*/
@Override
public boolean isRequired() {
return option == FieldOption.REQUIRED;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isOptional()
*/
@Override
public boolean isOptional() {
return option == FieldOption.OPTIONAL;
}
/* (non-Javadoc)
* @see org.msgpack.template.IFieldEntry#isNullable()
*/
@Override
public boolean isNullable() {
return option == FieldOption.NULLABLE;
}
static String arrayTypeToString(Class<?> type) {
int dim = 1;
Class<?> baseType = type.getComponentType();
while(baseType.isArray()) {
baseType = baseType.getComponentType();
dim += 1;
}
StringBuilder sb = new StringBuilder();
sb.append(baseType.getName());
for (int i = 0; i < dim; ++i) {
sb.append("[]");
}
return sb.toString();
}
}

View File

@@ -0,0 +1,182 @@
//
// 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;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.msgpack.annotation.Ignore;
import org.msgpack.annotation.Index;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.Nullable;
import org.msgpack.annotation.Optional;
import org.msgpack.annotation.Required;
public class FieldEntryReader implements IFieldEntryReader{
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
List<FieldList.Entry> src = flist.getList();
FieldEntry[] result = new FieldEntry[src.size()];
for(int i=0; i < src.size(); i++) {
FieldList.Entry s = src.get(i);
if(s.isAvailable()) {
result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
} else {
result[i] = new FieldEntry();
}
}
return result;
}
@Override
public IFieldEntry[] readFieldEntries(Class<?> targetClass,
FieldOption implicitOption) {
Field[] allFields = readAllFields(targetClass);
/* index:
* @Index(0) int field_a; // 0
* int field_b; // 1
* @Index(3) int field_c; // 3
* int field_d; // 4
* @Index(2) int field_e; // 2
* int field_f; // 5
*/
List<FieldEntry> indexed = new ArrayList<FieldEntry>();
int maxIndex = -1;
for(Field f : allFields) {
FieldOption opt = readFieldOption(f, implicitOption);
if(opt == FieldOption.IGNORE) {
// skip
continue;
}
int index = readFieldIndex(f, maxIndex);
if(indexed.size() > index && indexed.get(index) != null) {
throw new TemplateBuildException("duplicated index: "+index);
}
if(index < 0) {
throw new TemplateBuildException("invalid index: "+index);
}
while(indexed.size() <= index) {
indexed.add(null);
}
indexed.set(index, new FieldEntry(f, opt));
if(maxIndex < index) {
maxIndex = index;
}
}
FieldEntry[] result = new FieldEntry[maxIndex+1];
for(int i=0; i < indexed.size(); i++) {
FieldEntry e = indexed.get(i);
if(e == null) {
result[i] = new FieldEntry();
} else {
result[i] = e;
}
}
return result;
}
public FieldOption readImplicitFieldOption(Class<?> targetClass) {
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
if(a == null) {
return FieldOption.DEFAULT;
}
return a.value();
}
private Field[] readAllFields(Class<?> targetClass) {
// order: [fields of super class, ..., fields of this class]
List<Field[]> succ = new ArrayList<Field[]>();
int total = 0;
for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) {
Field[] fields = c.getDeclaredFields();
total += fields.length;
succ.add(fields);
}
Field[] result = new Field[total];
int off = 0;
for(int i=succ.size()-1; i >= 0; i--) {
Field[] fields = succ.get(i);
System.arraycopy(fields, 0, result, off, fields.length);
off += fields.length;
}
return result;
}
private static FieldOption readFieldOption(Field field, FieldOption implicitOption) {
int mod = field.getModifiers();
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
return FieldOption.IGNORE;
}
if(isAnnotated(field, Ignore.class)) {
return FieldOption.IGNORE;
} else if(isAnnotated(field, Required.class)) {
return FieldOption.REQUIRED;
} else if(isAnnotated(field, Optional.class)) {
return FieldOption.OPTIONAL;
} else if(isAnnotated(field, Nullable.class)) {
if(field.getDeclaringClass().isPrimitive()) {
return FieldOption.REQUIRED;
} else {
return FieldOption.NULLABLE;
}
}
if(implicitOption != FieldOption.DEFAULT) {
return implicitOption;
}
// default mode:
// transient : Ignore
// public : Required
// others : Ignore
if(Modifier.isTransient(mod)) {
return FieldOption.IGNORE;
} else if(Modifier.isPublic(mod)) {
return FieldOption.REQUIRED;
} else {
return FieldOption.IGNORE;
}
}
private static int readFieldIndex(Field field, int maxIndex) {
Index a = field.getAnnotation(Index.class);
if(a == null) {
return maxIndex + 1;
} else {
return a.value();
}
}
private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
}

View File

@@ -43,19 +43,19 @@ public class FieldList {
return option;
}
boolean isAvailable() {
public boolean isAvailable() {
return this.option != FieldOption.IGNORE;
}
boolean isRequired() {
public boolean isRequired() {
return this.option == FieldOption.REQUIRED;
}
boolean isOptional() {
public boolean isOptional() {
return this.option == FieldOption.OPTIONAL;
}
boolean isNullable() {
public boolean isNullable() {
return this.option == FieldOption.NULLABLE;
}
}
@@ -89,7 +89,7 @@ public class FieldList {
}
}
List<Entry> getList() {
public List<Entry> getList() {
return list;
}
}

View File

@@ -0,0 +1,42 @@
//
// 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;
import java.lang.reflect.Type;
public interface IFieldEntry {
public abstract String getName();
public abstract Class<?> getType();
public abstract String getJavaTypeName();
public abstract Type getGenericType();
public abstract FieldOption getOption();
public abstract boolean isAvailable();
public abstract boolean isRequired();
public abstract boolean isOptional();
public abstract boolean isNullable();
}

View File

@@ -0,0 +1,25 @@
//
// 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 interface IFieldEntryReader {
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException;
public IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption);
public FieldOption readImplicitFieldOption(Class<?> targetClass) ;
}

View File

@@ -17,28 +17,21 @@
//
package org.msgpack.template;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.Thread;
import org.msgpack.*;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.msgpack.template.builder.CustomTemplateBuilder;
import org.msgpack.template.javassist.*;
public class JavassistTemplateBuilder extends TemplateBuilder {
public class JavassistTemplateBuilder extends CustomTemplateBuilder {
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
private static JavassistTemplateBuilder instance;
@@ -54,12 +47,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
getInstance().pool.appendClassPath(new LoaderClassPath(cl));
}
private JavassistTemplateBuilder() {
IFieldEntryReader reader = new FieldEntryReader();
public void setFieldEntryReader(IFieldEntryReader reader){
this.reader = reader;
}
BuildContextFactory buildContextFactory = new BuildContextFactory() {
@Override
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) {
return new BuildContext(builder);
}
};
public void setBuildContextFactory(BuildContextFactory factory){
this.buildContextFactory = factory;
}
public JavassistTemplateBuilder() {
pool = new ClassPool();
boolean appended = false;
ClassLoader cl = null;
try {
Thread.currentThread().getContextClassLoader();
cl = Thread.currentThread().getContextClassLoader();
if (cl != null) {
pool.appendClassPath(new LoaderClassPath(cl));
appended = true;
@@ -80,556 +94,38 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
pool.appendSystemPath();
}
}
/**
* Replace FieldEntryReader and BuilderContextFactory.
* you can replace field entry rules and generated codes easily.
* @param reader
* @param buildContextFactory
*/
public JavassistTemplateBuilder(IFieldEntryReader reader,BuildContextFactory buildContextFactory ){
this();
this.reader = reader;
this.buildContextFactory = buildContextFactory;
}
protected ClassPool pool;
private int seqId = 0;
CtClass makeCtClass(String className) {
public CtClass makeCtClass(String className) {
return pool.makeClass(className);
}
CtClass getCtClass(String className) throws NotFoundException {
public CtClass getCtClass(String className) throws NotFoundException {
return pool.get(className);
}
int nextSeqId() {
public int nextSeqId() {
return seqId++;
}
private static abstract class BuildContextBase {
protected JavassistTemplateBuilder director;
protected String tmplName;
protected CtClass tmplCtClass;
protected abstract void setSuperClass() throws CannotCompileException, NotFoundException;
protected abstract void buildConstructor() throws CannotCompileException, NotFoundException;
protected void buildMethodInit() { }
protected abstract String buildPackMethodBody();
protected abstract String buildUnpackMethodBody();
protected abstract String buildConvertMethodBody();
protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException;
public BuildContextBase(JavassistTemplateBuilder director) {
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, true);
buildClass();
buildConstructor();
buildMethodInit();
buildPackMethod();
buildUnpackMethod();
buildConvertMethod();
return buildInstance(createClass());
} 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 reset(String className, boolean isBuilt) {
if (isBuilt) {
tmplName = className + "_$$_Template" + director.nextSeqId();
} else {
tmplName = className + "_$$_Template";
}
tmplCtClass = director.makeCtClass(tmplName);
}
protected void buildClass() throws CannotCompileException, NotFoundException {
setSuperClass();
tmplCtClass.addInterface(director.getCtClass(Template.class.getName()));
}
protected void buildPackMethod() throws CannotCompileException, NotFoundException {
String mbody = buildPackMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = CtClass.voidType;
String mname = "pack";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(Packer.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(IOException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected void buildUnpackMethod() throws CannotCompileException, NotFoundException {
String mbody = buildUnpackMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = director.getCtClass(Object.class.getName());
String mname = "unpack";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(Unpacker.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(MessageTypeException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected void buildConvertMethod() throws CannotCompileException, NotFoundException {
String mbody = buildConvertMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = director.getCtClass(Object.class.getName());
String mname = "convert";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(MessagePackObject.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(MessageTypeException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected Class<?> createClass() throws CannotCompileException {
return (Class<?>) tmplCtClass.toClass(null, null);
}
protected StringBuilder stringBuilder = null;
protected void resetStringBuilder() {
stringBuilder = new StringBuilder();
}
protected void buildString(String str) {
stringBuilder.append(str);
}
protected void buildString(String format, Object... args) {
stringBuilder.append(String.format(format, args));
}
protected String getBuiltString() {
if(stringBuilder == null) {
return null;
}
return stringBuilder.toString();
}
}
public static abstract class JavassistTemplate extends AbstractTemplate {
public Class<?> targetClass;
public Template[] templates;
public JavassistTemplate(Class<?> targetClass, Template[] templates) {
this.targetClass = targetClass;
this.templates = templates;
}
}
private static class BuildContext extends BuildContextBase {
protected FieldEntry[] entries;
protected Class<?> origClass;
protected String origName;
protected Template[] templates;
protected int minimumArrayLength;
public BuildContext(JavassistTemplateBuilder director) {
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;
this.origClass = targetClass;
this.origName = this.origClass.getName();
return build(this.origName);
}
protected void setSuperClass() throws CannotCompileException, NotFoundException {
this.tmplCtClass.setSuperclass(
director.getCtClass(JavassistTemplate.class.getName()));
}
protected void buildConstructor() throws CannotCompileException, NotFoundException {
// Constructor(Class targetClass, Template[] templates)
CtConstructor newCtCons = CtNewConstructor.make(
new CtClass[] {
director.getCtClass(Class.class.getName()),
director.getCtClass(Template.class.getName()+"[]")
},
new CtClass[0],
this.tmplCtClass);
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,
Template[].class
});
Object tmpl = cons.newInstance(new Object[] {
this.origClass,
this.templates
});
return (Template)tmpl;
}
protected void buildMethodInit() {
this.minimumArrayLength = 0;
for(int i=0; i < entries.length; i++) {
FieldEntry e = entries[i];
if(e.isRequired() || e.isNullable()) {
this.minimumArrayLength = i+1;
}
}
}
protected String buildPackMethodBody() {
resetStringBuilder();
buildString("{");
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
buildString("$1.packArray(%d);", entries.length);
for(int i=0; i < entries.length; i++) {
FieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.packNil();");
continue;
}
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName());
} else {
buildString("if(_$$_t.%s == null) {", e.getName());
if(!e.isNullable() && !e.isOptional()) {
buildString("throw new %s();", MessageTypeException.class.getName());
} else {
buildString("$1.packNil();");
}
buildString("} else {");
buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName());
buildString("}");
}
}
buildString("}");
return getBuiltString();
}
protected String buildUnpackMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("int length = $1.unpackArray();");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
int i;
for(i=0; i < this.minimumArrayLength; i++) {
FieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s = null;", e.getName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
FieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("for(int i=%d; i < length; i++) {", i);
buildString(" $1.unpackObject();");
buildString("}");
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
protected String buildConvertMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
buildString("int length = array.length;");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
buildString("%s obj;", MessagePackObject.class.getName());
int i;
for(i=0; i < this.minimumArrayLength; i++) {
FieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s = null;", e.getName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
FieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
protected String primitivePackName(Class<?> type) {
if(type == boolean.class) {
return "packBoolean";
} else if(type == byte.class) {
return "packByte";
} else if(type == short.class) {
return "packShort";
} else if(type == int.class) {
return "packInt";
} else if(type == long.class) {
return "packLong";
} else if(type == float.class) {
return "packFloat";
} else if(type == double.class) {
return "packDouble";
}
return null;
}
protected String primitiveUnpackName(Class<?> type) {
if(type == boolean.class) {
return "unpackBoolean";
} else if(type == byte.class) {
return "unpackByte";
} else if(type == short.class) {
return "unpackShort";
} else if(type == int.class) {
return "unpackInt";
} else if(type == long.class) {
return "unpackLong";
} else if(type == float.class) {
return "unpackFloat";
} else if(type == double.class) {
return "unpackDouble";
}
return null;
}
protected String primitiveConvertName(Class<?> type) {
if(type == boolean.class) {
return "asBoolean";
} else if(type == byte.class) {
return "asByte";
} else if(type == short.class) {
return "asShort";
} else if(type == int.class) {
return "asInt";
} else if(type == long.class) {
return "asLong";
} else if(type == float.class) {
return "asFloat";
} else if(type == double.class) {
return "asDouble";
}
return null;
}
}
@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) {
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
// FIXME private / packagefields
//for(FieldEntry e : entries) {
// Field f = e.getField();
@@ -639,9 +135,9 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
// }
//}
Template[] tmpls = new Template[from.length];
for(int i=0; i < from.length; i++) {
FieldEntry e = from[i];
Template[] tmpls = new Template[entries.length];
for(int i=0; i < entries.length; i++) {
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
tmpls[i] = null;
} else {
@@ -649,9 +145,22 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
tmpls[i] = tmpl;
}
}
return tmpls;
BuildContextBase bc = getBuildContextFacotry().createBuildContext(this);
return bc.buildTemplate(targetClass, entries, tmpls);
}
@Override
public IFieldEntryReader getFieldEntryReader() {
return reader;
}
public BuildContextFactory getBuildContextFacotry() {
return buildContextFactory;
}
/*
static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate {
JavassistOrdinalEnumTemplate(Enum<?>[] entries) {
super(entries);
@@ -704,6 +213,6 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
}
}
}*/
}

View File

@@ -18,21 +18,21 @@
package org.msgpack.template;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.Map;
import java.util.HashMap;
import org.msgpack.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectionTemplateBuilder extends TemplateBuilder {
private static ReflectionTemplateBuilder instance;
public synchronized static ReflectionTemplateBuilder getInstance() {
if(instance == null) {
instance = new ReflectionTemplateBuilder();
}
return instance;
import org.msgpack.*;
import org.msgpack.template.builder.CustomTemplateBuilder;
public class ReflectionTemplateBuilder extends CustomTemplateBuilder {
IFieldEntryReader reader = new FieldEntryReader();
@Override
public IFieldEntryReader getFieldEntryReader(){
return reader;
}
private ReflectionTemplateBuilder() {
public ReflectionTemplateBuilder() {
}
static abstract class ReflectionFieldEntry extends FieldEntry {
@@ -373,25 +373,10 @@ 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();
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
// TODO Now it is simply cast.
for(IFieldEntry e : entries) {
Field f = ((FieldEntry)e).getField();
int mod = f.getModifiers();
if(!Modifier.isPublic(mod)) {
f.setAccessible(true);
@@ -400,7 +385,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
for(int i=0; i < entries.length; i++) {
FieldEntry e = entries[i];
FieldEntry e = (FieldEntry)entries[i];
Class<?> type = e.getType();
if(!e.isAvailable()) {
res[i] = new NullFieldEntry(e);
@@ -426,171 +411,5 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
return new ReflectionTemplate(targetClass, res);
}
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
protected Enum<?>[] entries;
protected Map<Enum<?>, Integer> reverse;
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
this.entries = entries;
this.reverse = new HashMap<Enum<?>, Integer>();
for(int i=0; i < entries.length; i++) {
this.reverse.put(entries[i], i);
}
}
public void pack(Packer pk, Object target) throws IOException {
Integer ord = reverse.get(target);
if(ord == null) {
throw new MessageTypeException();
}
pk.pack((int)ord);
}
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
int ord = pac.unpackInt();
if(entries.length <= ord) {
throw new MessageTypeException();
}
return entries[ord];
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
int ord = from.asInt();
if(entries.length <= ord) {
throw new MessageTypeException();
}
return entries[ord];
}
}
@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;
public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) {
this.componentClass = componentClass;
this.elementTemplate = elementTemplate;
}
public void pack(Packer pk, Object target) throws IOException {
if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) {
throw new MessageTypeException();
}
Object[] array = (Object[])target;
int length = array.length;
pk.packArray(length);
for(int i=0; i < length; i++) {
elementTemplate.pack(pk, array[i]);
}
}
public Object unpack(Unpacker pac, Object to) throws IOException {
int length = pac.unpackArray();
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = elementTemplate.unpack(pac, null);
}
return array;
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
MessagePackObject[] src = from.asArray();
int length = src.length;
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = elementTemplate.convert(src[i], null);
}
return array;
}
}
static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate {
private Class<?> componentClass;
private Template componentTemplate;
public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) {
this.componentClass = componentClass;
this.componentTemplate = componentTemplate;
}
Class<?> getComponentClass() {
return componentClass;
}
public void pack(Packer pk, Object target) throws IOException {
Object[] array = (Object[])target;
int length = array.length;
pk.packArray(length);
for(int i=0; i < length; i++) {
componentTemplate.pack(pk, array[i]);
}
}
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
int length = pac.unpackArray();
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = componentTemplate.unpack(pac, null);
}
return array;
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
MessagePackObject[] src = from.asArray();
int length = src.length;
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = componentTemplate.convert(src[i], null);
}
return array;
}
}
@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) {
return BooleanArrayTemplate.getInstance();
} else if(baseClass == short.class) {
return ShortArrayTemplate.getInstance();
} else if(baseClass == int.class) {
return IntArrayTemplate.getInstance();
} else if(baseClass == long.class) {
return LongArrayTemplate.getInstance();
} else if(baseClass == float.class) {
return FloatArrayTemplate.getInstance();
} else if(baseClass == double.class) {
return DoubleArrayTemplate.getInstance();
} else {
Template baseTemplate = TemplateRegistry.lookup(genericBaseType);
return new ReflectionObjectArrayTemplate(baseClass, baseTemplate);
}
} else if(dim == 2) {
Class<?> componentClass = Array.newInstance(baseClass, 0).getClass();
Template componentTemplate = buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1);
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
} else {
ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate)
buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1);
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
}
}
}

View File

@@ -26,32 +26,54 @@ import java.lang.annotation.Annotation;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.MessagePackDelegate;
import org.msgpack.annotation.MessagePackOrdinalEnum;
import org.msgpack.template.builder.BuilderSelectorRegistry;
import org.msgpack.template.builder.CustomTemplateBuilder;
import org.msgpack.template.builder.TemplateBuilder;
import org.msgpack.Template;
public class TemplateRegistry {
private static Map<Type, Template> map;
private static Map<Type, GenericTemplate> genericMap;
private static BuilderSelectorRegistry builderSelectorRegistry;
static {
map = new HashMap<Type, Template>();
genericMap = new HashMap<Type, GenericTemplate>();
BuiltInTemplateLoader.load();
builderSelectorRegistry = BuilderSelectorRegistry.getInstance();
}
public static void register(Class<?> target) { // auto-detect
if(target.isEnum()) {
TemplateBuilder builder = builderSelectorRegistry.select(target);
if(builder != null){
register(target,builder.buildTemplate(target));
}else{
register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target));
}
/*if(target.isEnum()) {
register(target, TemplateBuilder.buildOrdinalEnum(target));
} else {
register(target, TemplateBuilder.build(target));
}
}*/
}
public static void register(Class<?> target, FieldOption implicitOption) {
register(target, TemplateBuilder.build(target, implicitOption));
TemplateBuilder builder = builderSelectorRegistry.select(target);
if(builder != null && builder instanceof CustomTemplateBuilder){
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption));
}else{
throw new TemplateBuildException("cannot build template with filed option");
}
}
public static void register(Class<?> target, FieldList flist) throws NoSuchFieldException {
register(target, TemplateBuilder.build(target, flist));
TemplateBuilder builder = builderSelectorRegistry.select(target);
if(builder != null && builder instanceof CustomTemplateBuilder){
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist));
}else{
throw new TemplateBuildException("cannot build template with filed list");
}
}
public static synchronized void register(Type rawType, Template tmpl) {
@@ -101,7 +123,7 @@ public class TemplateRegistry {
return tmpl;
}
if(targetType instanceof GenericArrayType) {
/*if(targetType instanceof GenericArrayType) {
// GenericArrayType is not a Class<?>
tmpl = TemplateBuilder.buildArray(targetType);
register(targetType, tmpl);
@@ -135,7 +157,17 @@ public class TemplateRegistry {
tmpl = TemplateBuilder.buildOrdinalEnum(target);
register(target, tmpl);
return tmpl;
}*/
// find match TemplateBuilder
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType);
if(builder != null){
tmpl = builder.buildTemplate(targetType);
register(targetType,tmpl);
return tmpl;
}
Class<?> target = (Class<?>)targetType;
for(Class<?> i : target.getInterfaces()) {
tmpl = map.get(i);
@@ -156,7 +188,7 @@ public class TemplateRegistry {
}
if(forceBuild) {
tmpl = TemplateBuilder.build(target);
tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target);
register(target, tmpl);
return tmpl;
}
@@ -204,8 +236,5 @@ public class TemplateRegistry {
return ao.getAnnotation(with) != null;
}
public static void setTemplateBuilder(TemplateBuilder builder) {
TemplateBuilder.setInstance(builder);
}
}

View File

@@ -0,0 +1,190 @@
//
// 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.builder;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.msgpack.AbstractTemplate;
import org.msgpack.MessagePackObject;
import org.msgpack.MessageTypeException;
import org.msgpack.Packer;
import org.msgpack.Template;
import org.msgpack.Unpacker;
import org.msgpack.template.BooleanArrayTemplate;
import org.msgpack.template.DoubleArrayTemplate;
import org.msgpack.template.FloatArrayTemplate;
import org.msgpack.template.IFieldEntry;
import org.msgpack.template.IFieldEntryReader;
import org.msgpack.template.IntArrayTemplate;
import org.msgpack.template.LongArrayTemplate;
import org.msgpack.template.ShortArrayTemplate;
import org.msgpack.template.TemplateRegistry;
public class ArrayTemplateBuilder extends TemplateBuilder {
static class ReflectionObjectArrayTemplate extends AbstractTemplate {
private Class<?> componentClass;
private Template elementTemplate;
public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) {
this.componentClass = componentClass;
this.elementTemplate = elementTemplate;
}
public void pack(Packer pk, Object target) throws IOException {
if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) {
throw new MessageTypeException();
}
Object[] array = (Object[])target;
int length = array.length;
pk.packArray(length);
for(int i=0; i < length; i++) {
elementTemplate.pack(pk, array[i]);
}
}
public Object unpack(Unpacker pac, Object to) throws IOException {
int length = pac.unpackArray();
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = elementTemplate.unpack(pac, null);
}
return array;
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
MessagePackObject[] src = from.asArray();
int length = src.length;
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = elementTemplate.convert(src[i], null);
}
return array;
}
}
static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate {
private Class<?> componentClass;
private Template componentTemplate;
public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) {
this.componentClass = componentClass;
this.componentTemplate = componentTemplate;
}
Class<?> getComponentClass() {
return componentClass;
}
public void pack(Packer pk, Object target) throws IOException {
Object[] array = (Object[])target;
int length = array.length;
pk.packArray(length);
for(int i=0; i < length; i++) {
componentTemplate.pack(pk, array[i]);
}
}
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
int length = pac.unpackArray();
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = componentTemplate.unpack(pac, null);
}
return array;
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
MessagePackObject[] src = from.asArray();
int length = src.length;
Object[] array = (Object[])Array.newInstance(componentClass, length);
for(int i=0; i < length; i++) {
array[i] = componentTemplate.convert(src[i], null);
}
return array;
}
}
@Override
public Template buildTemplate(Type arrayType) {
Type baseType;
Class<?> baseClass;
int dim = 1;
if(arrayType instanceof GenericArrayType) {
GenericArrayType type = (GenericArrayType)arrayType;
baseType = type.getGenericComponentType();
while(baseType instanceof GenericArrayType) {
baseType = ((GenericArrayType)baseType).getGenericComponentType();
dim += 1;
}
if(baseType instanceof ParameterizedType) {
baseClass = (Class<?>)((ParameterizedType)baseType).getRawType();
} else {
baseClass = (Class<?>)baseType;
}
} else {
Class<?> type = (Class<?>)arrayType;
baseClass = type.getComponentType();
while(baseClass.isArray()) {
baseClass = baseClass.getComponentType();
dim += 1;
}
baseType = baseClass;
}
return toTemplate(arrayType, baseType, baseClass, dim);
}
private Template toTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) {
if(dim == 1) {
if(baseClass == boolean.class) {
return BooleanArrayTemplate.getInstance();
} else if(baseClass == short.class) {
return ShortArrayTemplate.getInstance();
} else if(baseClass == int.class) {
return IntArrayTemplate.getInstance();
} else if(baseClass == long.class) {
return LongArrayTemplate.getInstance();
} else if(baseClass == float.class) {
return FloatArrayTemplate.getInstance();
} else if(baseClass == double.class) {
return DoubleArrayTemplate.getInstance();
} else {
Template baseTemplate = TemplateRegistry.lookup(genericBaseType);
return new ReflectionObjectArrayTemplate(baseClass, baseTemplate);
}
} else if(dim == 2) {
Class<?> componentClass = Array.newInstance(baseClass, 0).getClass();
Template componentTemplate = toTemplate(arrayType, genericBaseType, baseClass, dim-1);
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
} else {
ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate)
toTemplate(arrayType, genericBaseType, baseClass, dim-1);
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
}
}
}

View File

@@ -0,0 +1,52 @@
//
// 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.builder;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import org.msgpack.Template;
public class ArrayTemplateBuilderSelector implements BuilderSelector {
public static final String NAME = "ArrayTemplateBuilder";
@Override
public String getName(){
return NAME;
}
@Override
public boolean matchType(Type targetType) {
if(targetType instanceof GenericArrayType){
return true;
}
Class<?> targetClass = (Class<?>)targetType;
return targetClass.isArray();
}
ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder();
@Override
public TemplateBuilder getTemplateBuilder(Type target) {
return templateBuilder;
}
}

View File

@@ -0,0 +1,44 @@
//
// 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.builder;
import java.lang.reflect.Type;
/**
* Match condition for TemplateBuilder.
* @author takeshita
*
*/
public interface BuilderSelector {
/**
* Name of this.
* @return
*/
public String getName();
public abstract boolean matchType(Type targetType);
public abstract TemplateBuilder getTemplateBuilder(Type targetType);
}

View File

@@ -0,0 +1,230 @@
//
// 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.builder;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
import org.msgpack.template.BeansFieldEntryReader;
import org.msgpack.template.BeansReflectionTemplateBuilder;
import org.msgpack.template.JavassistTemplateBuilder;
import org.msgpack.template.ReflectionTemplateBuilder;
import org.msgpack.template.javassist.BeansBuildContext;
import org.msgpack.template.javassist.BuildContext;
import org.msgpack.template.javassist.BuildContextBase;
import org.msgpack.template.javassist.BuildContextFactory;
/**
* Registry for BuilderSelectors.
* You can modify BuilderSelector chain throw this class.
*
* @author takeshita
*
*/
public class BuilderSelectorRegistry {
private static BuilderSelectorRegistry instance = new BuilderSelectorRegistry();
static{
initForJava();
}
public static BuilderSelectorRegistry getInstance(){
return instance;
}
TemplateBuilder forceBuilder;
List<BuilderSelector> builderSelectors = new LinkedList<BuilderSelector>();
private BuilderSelectorRegistry(){
}
/**
* initialize BuilderSelectors for basic java enviroment.
*/
private static void initForJava(){
instance.append(new ArrayTemplateBuilderSelector());
if(isSupportJavassist()){
instance.append(
new MessagePackMessageBuilderSelector(
new JavassistTemplateBuilder()));
instance.forceBuilder = new JavassistTemplateBuilder();
//Java beans
instance.append(new MessagePackBeansBuilderSelector(
new JavassistTemplateBuilder(
new BeansFieldEntryReader(),
new BuildContextFactory() {
@Override
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) {
return new BeansBuildContext(builder);
}
}
)));
}else{
instance.append(
new MessagePackMessageBuilderSelector(
new ReflectionTemplateBuilder()));
instance.forceBuilder = new ReflectionTemplateBuilder();
//Java beans
instance.append(new MessagePackBeansBuilderSelector(
new BeansReflectionTemplateBuilder()));
}
instance.append(new MessagePackOrdinalEnumBuilderSelector());
instance.append(new EnumBuilderSelector());
}
public static boolean isSupportJavassist(){
try {
return System.getProperty("java.vm.name").equals("Dalvik");
} catch (Exception e) {
return true;
}
}
/**
* Check whether same name BuilderSelector is registered.
* @param builderSelectorName
* @return
*/
public boolean contains(String builderSelectorName){
for(BuilderSelector bs : builderSelectors){
if(bs.getName().equals(builderSelectorName)){
return true;
}
}
return false;
}
/**
* Append BuilderSelector to tail
* @param builderSelector
*/
public void append(BuilderSelector builderSelector){
if(contains(builderSelector.getName())){
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
}
this.builderSelectors.add(builderSelector);
}
/**
* Insert BuiderSelector to head
* @param builderSelector
*/
public void prepend(BuilderSelector builderSelector){
if(contains(builderSelector.getName())){
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
}
if(builderSelectors.size() > 0){
this.builderSelectors.add(0, builderSelector);
}else{
this.builderSelectors.add(builderSelector);
}
}
/**
* Insert BuilderSelector
* @param index
* @param builderSelector
*/
public void insert(int index,BuilderSelector builderSelector){
if(contains(builderSelector.getName())){
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
}
if(builderSelectors.size() > 0){
this.builderSelectors.add(index, builderSelector);
}else{
this.builderSelectors.add(builderSelector);
}
}
/**
* Replace same name BuilderSelector
* @param builderSelector
*/
public void replace(BuilderSelector builderSelector){
String name = builderSelector.getName();
int index = getIndex(name);
builderSelectors.add(index, builderSelector);
builderSelectors.remove(index + 1);
}
/**
* Insert the BuilderSelector before BuilderSelector named "builderSelectorName".
* @param builderSelectorName
* @param builderSelector
*/
public void insertBefore(String builderSelectorName,BuilderSelector builderSelector){
int index = getIndex(builderSelectorName);
builderSelectors.add(index,builderSelector);
}
/**
* Insert the BuilderSelector after BuilderSelector named "builderSelectorName".
* @param builderSelectorName
* @param builderSelector
*/
public void insertAfter(String builderSelectorName,BuilderSelector builderSelector){
int index = getIndex(builderSelectorName);
if(index + 1 == builderSelectors.size()){
builderSelectors.add(builderSelector);
}else{
builderSelectors.add(index + 1 , builderSelector);
}
}
private int getIndex(String builderSelectorName){
int index = 0;
for(BuilderSelector bs : builderSelectors){
if(bs.getName().equals(builderSelectorName)){
break;
}
index++;
}
if(index >= builderSelectors.size()){
throw new RuntimeException(
String.format("BuilderSelector named %s does not exist",builderSelectorName));
}
return index;
}
public TemplateBuilder select(Type target){
for(BuilderSelector selector : builderSelectors){
if(selector.matchType(target)){
return selector.getTemplateBuilder(target);
}
}
return null;
}
public TemplateBuilder getForceBuilder() {
return forceBuilder;
}
public void setForceBuilder(TemplateBuilder forceBuilder) {
this.forceBuilder = forceBuilder;
}
}

View File

@@ -0,0 +1,70 @@
//
// 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.builder;
import java.lang.reflect.Type;
import org.msgpack.Template;
import org.msgpack.template.FieldList;
import org.msgpack.template.FieldOption;
import org.msgpack.template.IFieldEntry;
import org.msgpack.template.IFieldEntryReader;
import org.msgpack.template.TemplateBuildException;
import org.msgpack.template.javassist.BuildContextFactory;
public abstract class CustomTemplateBuilder extends TemplateBuilder {
public abstract IFieldEntryReader getFieldEntryReader();
public abstract Template buildTemplate(Class<?> targetClass , IFieldEntry[] entries);
public Template buildTemplate(Class<?> targetClass ,FieldOption implicitOption ){
checkValidation(targetClass);
return buildTemplate(targetClass,
getFieldEntryReader().readFieldEntries(targetClass, implicitOption));
}
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
checkValidation(targetClass);
return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist));
}
@Override
public Template buildTemplate(Type targetType) {
Class<?> targetClass = (Class<?>)targetType;
IFieldEntryReader reader = getFieldEntryReader();
FieldOption implicitOption = reader.readImplicitFieldOption(targetClass);
checkValidation(targetClass);
IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption);
return buildTemplate(targetClass,entries);
}
private void checkValidation(Class<?> targetClass) {
if(targetClass.isInterface()) {
throw new TemplateBuildException("cannot build template of interface");
}
if(targetClass.isArray()) {
throw new TemplateBuildException("cannot build template of array class");
}
if(targetClass.isPrimitive()) {
throw new TemplateBuildException("cannot build template of primitive type");
}
}
}

View File

@@ -0,0 +1,43 @@
//
// 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.builder;
import java.lang.reflect.Type;
public class EnumBuilderSelector implements BuilderSelector {
public static final String NAME = "EnumTemplateBuilder";
public String getName(){
return NAME;
}
@Override
public boolean matchType(Type targetType) {
return ((Class<?>)targetType).isEnum();
}
OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder();
@Override
public TemplateBuilder getTemplateBuilder(Type targetType) {
return builder;
}
}

View File

@@ -0,0 +1,57 @@
//
// 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.builder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import org.msgpack.annotation.MessagePackBeans;
import org.msgpack.annotation.MessagePackMessage;
public class MessagePackBeansBuilderSelector implements BuilderSelector{
public static final String NAME = "MessagePackBeansTemplateBuilder";
TemplateBuilder builder;
public MessagePackBeansBuilderSelector(TemplateBuilder builder){
this.builder = builder;
}
public String getName(){
return NAME;
}
@Override
public boolean matchType(Type targetType) {
Class<?> target = (Class<?>)targetType;
return isAnnotated(target, MessagePackBeans.class);
}
@Override
public TemplateBuilder getTemplateBuilder(Type targetType) {
return builder;
}
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
}

View File

@@ -0,0 +1,55 @@
//
// 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.builder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import org.msgpack.annotation.MessagePackMessage;
public class MessagePackMessageBuilderSelector implements BuilderSelector{
public static final String NAME = "MessagePackMessageTemplateBuilder";
TemplateBuilder builder;
public MessagePackMessageBuilderSelector(TemplateBuilder builder){
this.builder = builder;
}
public String getName(){
return NAME;
}
@Override
public boolean matchType(Type targetType) {
Class<?> target = (Class<?>)targetType;
return isAnnotated(target, MessagePackMessage.class);
}
@Override
public TemplateBuilder getTemplateBuilder(Type targetType) {
return builder;
}
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
}

View File

@@ -0,0 +1,51 @@
//
// 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.builder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import org.msgpack.annotation.MessagePackOrdinalEnum;
public class MessagePackOrdinalEnumBuilderSelector implements BuilderSelector {
public static final String NAME = "MessagePackOrdinalEnumBuilderTemplate";
public String getName(){
return NAME;
}
@Override
public boolean matchType(Type targetType) {
Class<?> target = (Class<?>)targetType;
return isAnnotated(target, MessagePackOrdinalEnum.class);
}
OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder();
@Override
public TemplateBuilder getTemplateBuilder(Type targetType) {
return builder;
}
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
}

View File

@@ -0,0 +1,85 @@
//
// 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.builder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.msgpack.AbstractTemplate;
import org.msgpack.MessagePackObject;
import org.msgpack.MessageTypeException;
import org.msgpack.Packer;
import org.msgpack.Template;
import org.msgpack.Unpacker;
import org.msgpack.template.TemplateBuildException;
public class OrdinalEnumTemplateBuilder extends TemplateBuilder{
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
protected Enum<?>[] entries;
protected Map<Enum<?>, Integer> reverse;
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
this.entries = entries;
this.reverse = new HashMap<Enum<?>, Integer>();
for(int i=0; i < entries.length; i++) {
this.reverse.put(entries[i], i);
}
}
public void pack(Packer pk, Object target) throws IOException {
Integer ord = reverse.get(target);
if(ord == null) {
throw new MessageTypeException();
}
pk.pack((int)ord);
}
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
int ord = pac.unpackInt();
if(entries.length <= ord) {
throw new MessageTypeException();
}
return entries[ord];
}
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
int ord = from.asInt();
if(entries.length <= ord) {
throw new MessageTypeException();
}
return entries[ord];
}
}
@Override
public Template buildTemplate(Type targetType) {
Class<?> targetClass = (Class<?>)targetType;
checkOrdinalEnumValidation(targetClass);
Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants();
return new ReflectionOrdinalEnumTemplate(entries);
}
private void checkOrdinalEnumValidation(Class<?> targetClass) {
if(!targetClass.isEnum()) {
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
}
}
}

View File

@@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
package org.msgpack.template.builder;
import java.io.IOException;
import java.lang.reflect.*;
@@ -25,89 +25,19 @@ import java.util.ArrayList;
import java.util.EnumSet;
import org.msgpack.*;
import org.msgpack.annotation.*;
import org.msgpack.template.FieldList;
import org.msgpack.template.FieldOption;
import org.msgpack.template.IFieldEntry;
import org.msgpack.template.IFieldEntryReader;
import org.msgpack.template.JavassistTemplateBuilder;
import org.msgpack.template.ReflectionTemplateBuilder;
public abstract class TemplateBuilder {
public static class FieldEntry {
private Field field;
private FieldOption option;
public FieldEntry() {
this.field = null;
this.option = FieldOption.IGNORE;
}
public FieldEntry(FieldEntry e) {
this.field = e.field;
this.option = e.option;
}
public FieldEntry(Field field, FieldOption option) {
this.field = field;
this.option = option;
}
public Field getField() {
return field;
}
public String getName() {
return field.getName();
}
public Class<?> getType() {
return field.getType();
}
public String getJavaTypeName() {
Class<?> type = field.getType();
if(type.isArray()) {
return arrayTypeToString(type);
} else {
return type.getName();
}
}
public Type getGenericType() {
return field.getGenericType();
}
public FieldOption getOption() {
return option;
}
public boolean isAvailable() {
return option != FieldOption.IGNORE;
}
public boolean isRequired() {
return option == FieldOption.REQUIRED;
}
public boolean isOptional() {
return option == FieldOption.OPTIONAL;
}
public boolean isNullable() {
return option == FieldOption.NULLABLE;
}
static String arrayTypeToString(Class<?> type) {
int dim = 1;
Class<?> baseType = type.getComponentType();
while(baseType.isArray()) {
baseType = baseType.getComponentType();
dim += 1;
}
StringBuilder sb = new StringBuilder();
sb.append(baseType.getName());
for (int i = 0; i < dim; ++i) {
sb.append("[]");
}
return sb.toString();
}
}
public abstract Template buildTemplate(Type targetType);
/*
// Override this method
<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java
public abstract Class<?> loadTemplateClass(Class<?> targetClass);
// Override this method
@@ -118,6 +48,9 @@ public abstract class TemplateBuilder {
// Override this method
public abstract Template buildTemplate(Class<?> targetClass, FieldEntry[] entries);
=======
public abstract Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries);
>>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java
// Override this method
public abstract void writeOrdinalEnumTemplateClass(Class<?> targetClass, Enum<?>[] entires, String directoryName);
@@ -131,6 +64,7 @@ public abstract class TemplateBuilder {
// Override this method
public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim);
<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java
public Template initializeTemplate(Class<?> targetClass, Class<?> tmplClass) {
return initializeTemplate(targetClass, tmplClass, readFieldEntries(targetClass, readImplicitFieldOption(targetClass)));
@@ -140,10 +74,14 @@ public abstract class TemplateBuilder {
checkValidation(targetClass);
writeTemplateClass(targetClass, convertFieldEntries(targetClass, fList), directoryName);
}
=======
public abstract IFieldEntryReader getFieldEntryReader();
>>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
checkValidation(targetClass);
return buildTemplate(targetClass, convertFieldEntries(targetClass, flist));
return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist));
}
public void writeTemplateClass(Class<?> targetClass, FieldOption implicitOption, String directoryName) {
@@ -153,7 +91,7 @@ public abstract class TemplateBuilder {
public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) {
checkValidation(targetClass);
return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption));
return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption));
}
public void writeTemplateClass(Class<?> targetClass, final String directoryName) {
@@ -162,7 +100,7 @@ public abstract class TemplateBuilder {
}
public Template buildTemplate(Class<?> targetClass) {
FieldOption implicitOption = readImplicitFieldOption(targetClass);
FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass);
return buildTemplate(targetClass, implicitOption);
}
@@ -217,8 +155,24 @@ public abstract class TemplateBuilder {
return ((Class<?>)arrayType).getComponentType();
}
}
private void checkValidation(Class<?> targetClass) {
if(targetClass.isInterface()) {
throw new TemplateBuildException("cannot build template of interface");
}
if(targetClass.isArray()) {
throw new TemplateBuildException("cannot build template of array class");
}
if(targetClass.isPrimitive()) {
throw new TemplateBuildException("cannot build template of primitive type");
}
}
private void checkOrdinalEnumValidation(Class<?> targetClass) {
if(!targetClass.isEnum()) {
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
}
}
private static TemplateBuilder instance;
static {
instance = selectDefaultTemplateBuilder();
@@ -235,7 +189,7 @@ public abstract class TemplateBuilder {
return JavassistTemplateBuilder.getInstance();
}
synchronized static void setInstance(TemplateBuilder builder) {
public synchronized static void setInstance(TemplateBuilder builder) {
instance = builder;
}
@@ -286,9 +240,9 @@ public abstract class TemplateBuilder {
public static Template buildArray(Type arrayType) {
return instance.buildArrayTemplate(arrayType);
}
}*/
/*
private static void checkValidation(Class<?> targetClass) {
if(targetClass.isInterface()) {
throw new TemplateBuildException("cannot build template of interface");
@@ -305,10 +259,10 @@ public abstract class TemplateBuilder {
if(!targetClass.isEnum()) {
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
}
}
}*/
static FieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
/*
static IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
List<FieldList.Entry> src = flist.getList();
FieldEntry[] result = new FieldEntry[src.size()];
for(int i=0; i < src.size(); i++) {
@@ -320,9 +274,9 @@ public abstract class TemplateBuilder {
}
}
return result;
}
static FieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) {
}*/
/*static IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) {
Field[] allFields = readAllFields(targetClass);
/* index:
@@ -332,7 +286,7 @@ public abstract class TemplateBuilder {
* int field_d; // 4
* @Index(2) int field_e; // 2
* int field_f; // 5
*/
*//*
List<FieldEntry> indexed = new ArrayList<FieldEntry>();
int maxIndex = -1;
for(Field f : allFields) {
@@ -372,8 +326,8 @@ public abstract class TemplateBuilder {
}
return result;
}
}*/
/*
private static Field[] readAllFields(Class<?> targetClass) {
// order: [fields of super class, ..., fields of this class]
List<Field[]> succ = new ArrayList<Field[]>();
@@ -449,6 +403,6 @@ public abstract class TemplateBuilder {
private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
return ao.getAnnotation(with) != null;
}
}*/
}

View File

@@ -0,0 +1,289 @@
//
// 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.javassist;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.Thread;
import org.msgpack.*;
import org.msgpack.template.*;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.ClassClassPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BeansBuildContext extends BuildContextBase<BeansFieldEntry> {
protected BeansFieldEntry[] entries;
protected Class<?> origClass;
protected String origName;
protected Template[] templates;
protected int minimumArrayLength;
public BeansBuildContext(JavassistTemplateBuilder director) {
super(director);
}
public Template buildTemplate(Class<?> targetClass, BeansFieldEntry[] entries, Template[] templates) {
this.entries = entries;
this.templates = templates;
this.origClass = targetClass;
this.origName = this.origClass.getName();
return build(this.origName);
}
protected void setSuperClass() throws CannotCompileException, NotFoundException {
this.tmplCtClass.setSuperclass(
director.getCtClass(JavassistTemplate.class.getName()));
}
protected void buildConstructor() throws CannotCompileException, NotFoundException {
// Constructor(Class targetClass, Template[] templates)
CtConstructor newCtCons = CtNewConstructor.make(
new CtClass[] {
director.getCtClass(Class.class.getName()),
director.getCtClass(Template.class.getName()+"[]")
},
new CtClass[0],
this.tmplCtClass);
this.tmplCtClass.addConstructor(newCtCons);
}
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<?> cons = c.getConstructor(new Class[] {
Class.class,
Template[].class
});
Object tmpl = cons.newInstance(new Object[] {
this.origClass,
this.templates
});
return (Template)tmpl;
}
protected void buildMethodInit() {
this.minimumArrayLength = 0;
for(int i=0; i < entries.length; i++) {
IFieldEntry e = entries[i];
if(e.isRequired() || e.isNullable()) {
this.minimumArrayLength = i+1;
}
}
}
protected String buildPackMethodBody() {
resetStringBuilder();
buildString("{");
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
buildString("$1.packArray(%d);", entries.length);
for(int i=0; i < entries.length; i++) {
BeansFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.packNil();");
continue;
}
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("$1.%s(_$$_t.%s());", primitivePackName(type), e.getGetterName());
} else {
buildString("if(_$$_t.%s() == null) {", e.getGetterName());
if(!e.isNullable() && !e.isOptional()) {
buildString("throw new %s();", MessageTypeException.class.getName());
} else {
buildString("$1.packNil();");
}
buildString("} else {");
buildString(" this.templates[%d].pack($1, _$$_t.%s());", i, e.getGetterName());
buildString("}");
}
}
buildString("}");
return getBuiltString();
}
protected String buildUnpackMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("int length = $1.unpackArray();");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
int i;
for(i=0; i < this.minimumArrayLength; i++) {
BeansFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s(null);", e.getSetterName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.set%s( $1.%s() );", e.getName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.set%s( (%s)this.templates[%d].unpack($1, _$$_t.get%s()) );", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
BeansFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s( $1.%s() );", e.getSetterName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.%s( (%s)this.templates[%d].unpack($1, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("for(int i=%d; i < length; i++) {", i);
buildString(" $1.unpackObject();");
buildString("}");
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
protected String buildConvertMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
buildString("int length = array.length;");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
buildString("%s obj;", MessagePackObject.class.getName());
int i;
for(i=0; i < this.minimumArrayLength; i++) {
BeansFieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s( null );", e.getSetterName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
BeansFieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
}

View File

@@ -0,0 +1,289 @@
//
// 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.javassist;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.Thread;
import org.msgpack.*;
import org.msgpack.template.*;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.ClassClassPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BuildContext extends BuildContextBase<FieldEntry> {
protected IFieldEntry[] entries;
protected Class<?> origClass;
protected String origName;
protected Template[] templates;
protected int minimumArrayLength;
public BuildContext(JavassistTemplateBuilder director) {
super(director);
}
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) {
this.entries = entries;
this.templates = templates;
this.origClass = targetClass;
this.origName = this.origClass.getName();
return build(this.origName);
}
protected void setSuperClass() throws CannotCompileException, NotFoundException {
this.tmplCtClass.setSuperclass(
director.getCtClass(JavassistTemplate.class.getName()));
}
protected void buildConstructor() throws CannotCompileException, NotFoundException {
// Constructor(Class targetClass, Template[] templates)
CtConstructor newCtCons = CtNewConstructor.make(
new CtClass[] {
director.getCtClass(Class.class.getName()),
director.getCtClass(Template.class.getName()+"[]")
},
new CtClass[0],
this.tmplCtClass);
this.tmplCtClass.addConstructor(newCtCons);
}
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<?> cons = c.getConstructor(new Class[] {
Class.class,
Template[].class
});
Object tmpl = cons.newInstance(new Object[] {
this.origClass,
this.templates
});
return (Template)tmpl;
}
protected void buildMethodInit() {
this.minimumArrayLength = 0;
for(int i=0; i < entries.length; i++) {
IFieldEntry e = entries[i];
if(e.isRequired() || e.isNullable()) {
this.minimumArrayLength = i+1;
}
}
}
protected String buildPackMethodBody() {
resetStringBuilder();
buildString("{");
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
buildString("$1.packArray(%d);", entries.length);
for(int i=0; i < entries.length; i++) {
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.packNil();");
continue;
}
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName());
} else {
buildString("if(_$$_t.%s == null) {", e.getName());
if(!e.isNullable() && !e.isOptional()) {
buildString("throw new %s();", MessageTypeException.class.getName());
} else {
buildString("$1.packNil();");
}
buildString("} else {");
buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName());
buildString("}");
}
}
buildString("}");
return getBuiltString();
}
protected String buildUnpackMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("int length = $1.unpackArray();");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
int i;
for(i=0; i < this.minimumArrayLength; i++) {
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s = null;", e.getName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
buildString("$1.unpackObject();");
continue;
}
buildString("if($1.tryUnpackNull()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("for(int i=%d; i < length; i++) {", i);
buildString(" $1.unpackObject();");
buildString("}");
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
protected String buildConvertMethodBody() {
resetStringBuilder();
buildString("{ ");
buildString("%s _$$_t;", this.origName);
buildString("if($2 == null) {");
buildString(" _$$_t = new %s();", this.origName);
buildString("} else {");
buildString(" _$$_t = (%s)$2;", this.origName);
buildString("}");
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
buildString("int length = array.length;");
buildString("if(length < %d) {", this.minimumArrayLength);
buildString(" throw new %s();", MessageTypeException.class.getName());
buildString("}");
buildString("%s obj;", MessagePackObject.class.getName());
int i;
for(i=0; i < this.minimumArrayLength; i++) {
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
if(e.isRequired()) {
// Required + nil => exception
buildString("throw new %s();", MessageTypeException.class.getName());
} else if(e.isOptional()) {
// Optional + nil => keep default value
} else { // Nullable
// Nullable + nil => set null
buildString("_$$_t.%s = null;", e.getName());
}
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
for(; i < entries.length; i++) {
buildString("if(length <= %d) { return _$$_t; }", i);
IFieldEntry e = entries[i];
if(!e.isAvailable()) {
continue;
}
buildString("obj = array[%d];", i);
buildString("if(obj.isNil()) {");
// this is Optional field becaue i >= minimumArrayLength
// Optional + nil => keep default value
buildString("} else {");
Class<?> type = e.getType();
if(type.isPrimitive()) {
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
} else {
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
}
buildString("}");
}
// latter entries are all Optional + nil => keep default value
buildString("return _$$_t;");
buildString("}");
return getBuiltString();
}
}

View File

@@ -0,0 +1,244 @@
//
// 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.javassist;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.Thread;
import org.msgpack.*;
import org.msgpack.template.*;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.ClassClassPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class BuildContextBase<T extends IFieldEntry> {
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
protected JavassistTemplateBuilder director;
protected String tmplName;
protected CtClass tmplCtClass;
protected abstract void setSuperClass() throws CannotCompileException, NotFoundException;
protected abstract void buildConstructor() throws CannotCompileException, NotFoundException;
protected void buildMethodInit() { }
protected abstract String buildPackMethodBody();
protected abstract String buildUnpackMethodBody();
protected abstract String buildConvertMethodBody();
protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException;
public BuildContextBase(JavassistTemplateBuilder director) {
this.director = director;
}
public abstract Template buildTemplate(Class<?> targetClass, T[] entries, Template[] templates);
protected Template build(final String className) {
try {
reset(className);
buildClass();
buildConstructor();
buildMethodInit();
buildPackMethod();
buildUnpackMethod();
buildConvertMethod();
return buildInstance(createClass());
} 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 reset(String className) {
tmplName = className + "_$$_Template" + director.nextSeqId();
tmplCtClass = director.makeCtClass(tmplName);
}
protected void buildClass() throws CannotCompileException, NotFoundException {
setSuperClass();
tmplCtClass.addInterface(director.getCtClass(Template.class.getName()));
}
protected void buildPackMethod() throws CannotCompileException, NotFoundException {
String mbody = buildPackMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = CtClass.voidType;
String mname = "pack";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(Packer.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(IOException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected void buildUnpackMethod() throws CannotCompileException, NotFoundException {
String mbody = buildUnpackMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = director.getCtClass(Object.class.getName());
String mname = "unpack";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(Unpacker.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(MessageTypeException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected void buildConvertMethod() throws CannotCompileException, NotFoundException {
String mbody = buildConvertMethodBody();
int mod = javassist.Modifier.PUBLIC;
CtClass returnType = director.getCtClass(Object.class.getName());
String mname = "convert";
CtClass[] paramTypes = new CtClass[] {
director.getCtClass(MessagePackObject.class.getName()),
director.getCtClass(Object.class.getName())
};
CtClass[] exceptTypes = new CtClass[] {
director.getCtClass(MessageTypeException.class.getName())
};
CtMethod newCtMethod = CtNewMethod.make(
mod, returnType, mname,
paramTypes, exceptTypes, mbody, tmplCtClass);
tmplCtClass.addMethod(newCtMethod);
}
protected Class<?> createClass() throws CannotCompileException {
return (Class<?>) tmplCtClass.toClass(null, null);
}
protected StringBuilder stringBuilder = null;
protected void resetStringBuilder() {
stringBuilder = new StringBuilder();
}
protected void buildString(String str) {
stringBuilder.append(str);
}
protected void buildString(String format, Object... args) {
stringBuilder.append(String.format(format, args));
}
protected String getBuiltString() {
if(stringBuilder == null) {
return null;
}
return stringBuilder.toString();
}
protected String primitivePackName(Class<?> type) {
if(type == boolean.class) {
return "packBoolean";
} else if(type == byte.class) {
return "packByte";
} else if(type == short.class) {
return "packShort";
} else if(type == int.class) {
return "packInt";
} else if(type == long.class) {
return "packLong";
} else if(type == float.class) {
return "packFloat";
} else if(type == double.class) {
return "packDouble";
}
return null;
}
protected String primitiveUnpackName(Class<?> type) {
if(type == boolean.class) {
return "unpackBoolean";
} else if(type == byte.class) {
return "unpackByte";
} else if(type == short.class) {
return "unpackShort";
} else if(type == int.class) {
return "unpackInt";
} else if(type == long.class) {
return "unpackLong";
} else if(type == float.class) {
return "unpackFloat";
} else if(type == double.class) {
return "unpackDouble";
}
return null;
}
protected String primitiveConvertName(Class<?> type) {
if(type == boolean.class) {
return "asBoolean";
} else if(type == byte.class) {
return "asByte";
} else if(type == short.class) {
return "asShort";
} else if(type == int.class) {
return "asInt";
} else if(type == long.class) {
return "asLong";
} else if(type == float.class) {
return "asFloat";
} else if(type == double.class) {
return "asDouble";
}
return null;
}
}

View File

@@ -0,0 +1,26 @@
//
// 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.javassist;
import org.msgpack.template.JavassistTemplateBuilder;
public interface BuildContextFactory {
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder);
}

View File

@@ -0,0 +1,52 @@
//
// 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.javassist;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.lang.Thread;
import org.msgpack.*;
import org.msgpack.template.*;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import javassist.ClassClassPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class JavassistTemplate extends AbstractTemplate {
public Class<?> targetClass;
public Template[] templates;
public JavassistTemplate(Class<?> targetClass, Template[] templates) {
this.targetClass = targetClass;
this.templates = templates;
}
}

View File

@@ -13,6 +13,10 @@ import org.junit.Test;
import junit.framework.TestCase;
public class TestArrays extends TestCase {
@MessagePackMessage
public static class PrimitiveTest {
public PrimitiveTest() { }

View File

@@ -0,0 +1,133 @@
package org.msgpack.template;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.msgpack.template.BeansFieldEntryReader;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.*;
/**
*
* @author takeshita
*
*/
public class BeansEntryReaderTest {
public static class VariableProps{
public int getCollect(){
return 0;
}
public void setCollect(int v){}
public int getOnlyGetter(){
return 0;
}
public void setOnlySetter(int v){}
public boolean isBoolean(){
return true;
}
public void setBoolean(boolean b){}
private int getPrivateBoth(){return 1;}
private void setPrivateBoth(int v){}
private int getPrivateGetter(){return 1;}
public void setPrivateGetter(int v){}
public int getPrivateSetter(){return 1;}
private void setPrivateSetter(int v){}
protected int getProtected(){return 1;}
protected void setProtected(int v){}
int getInternal(){return 1;}
void setInternal(int v){}
public int getWrongGetter(int v){return 1;}
public void setWrongGetter(int v){}
public void getWrongGetter2(){}
public void setWrongGetter2(int v){}
public int isWrongGetter3(){return 1;}
public void setWrongGetter3(int v){}
public int getWrongSetter(){return 1;}
public int setWrongSetter(int v){return 1;}
public int getWrongSetter2(){return 1;}
public void setWrongSetter2(){}
}
@Before
public void before(){
reader = new BeansFieldEntryReader();
try {
info = Introspector.getBeanInfo(VariableProps.class);
} catch (IntrospectionException e) {
e.printStackTrace();
Assert.fail();
}
}
BeansFieldEntryReader reader;
BeanInfo info;
@Test
public void testIgnorePropertyDesc(){
BeanDescriptor desc = info.getBeanDescriptor();
assertThat(reader.isIgnoreProp(getProp(info,"collect")),is(false));
assertThat(reader.isIgnoreProp(getProp(info,"boolean")),is(false));
assertThat(reader.isIgnoreProp(getProp(info,"onlyGetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"onlySetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"privateBoth")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"privateGetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"privateSetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"protected")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"internal")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter2")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter3")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter")),is(true));
assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter2")),is(true));
}
@Test
public void testReadEntries(){
IFieldEntry[] entries = reader.readFieldEntries(VariableProps.class, FieldOption.DEFAULT);
assertThat(entries.length, is(2));
}
public PropertyDescriptor getProp(BeanInfo info , String name){
PropertyDescriptor[] props = info.getPropertyDescriptors();
for(int i = 0;i < props.length;i++){
PropertyDescriptor d = props[i];
if(d.getDisplayName().equalsIgnoreCase(name)){
return d;
}
}
return null;
}
}

View File

@@ -0,0 +1,83 @@
package org.msgpack.template;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import org.hamcrest.BaseMatcher;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Description;
import org.junit.Assert;
/**
* This matcher compares all get***() methods(except getClass)
* @author takeshita
*
*/
public class BeansEquals extends BaseMatcher<Object>{
Object expected;
HashSet<String> ignoreNames = new HashSet<String>();
public BeansEquals(Object expected){
this.expected = expected;
}
public BeansEquals(Object expected,String[] ignoreNames){
this.expected = expected;
for(int i = 0;i < ignoreNames.length;i++){
this.ignoreNames.add(ignoreNames[i]);
}
}
static String errorMessage = "hoge";
@Override
public boolean matches(Object actual) {
if(expected == actual){
return true;
}
if(!actual.getClass().equals(expected.getClass())){
errorMessage = String.format("Expected class is %s but actual %s",
expected.getClass().getName(),
actual.getClass().getName());
return false;
}
for(Method m : expected.getClass().getMethods()){
String n = m.getName();
if(n.startsWith("get") &&
!n.equals("getClass") &&
!ignoreNames.contains(n)){
if(m.getParameterTypes().length == 0 &&
!m.getReturnType().equals(void.class)){
try {
Object exp = m.invoke(expected);
Object act = m.invoke(actual);
Assert.assertThat("@" + n,act, CoreMatchers.is(exp));
} catch (Exception e) {
throw new RuntimeException(String.format(
"Exception occured while comparing %s",n), e);
}
}
}
}
return true;
}
@Override
public void describeTo(Description desc) {
desc.appendText(errorMessage);
}
}

View File

@@ -24,7 +24,10 @@ import org.msgpack.Unpacker;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.MessagePackOrdinalEnum;
import org.msgpack.annotation.Optional;
import org.msgpack.template.builder.BuilderSelectorRegistry;
import org.msgpack.template.builder.TemplateBuilder;
import junit.framework.Assert;
import junit.framework.TestCase;
public class TestTemplateBuilderPackConvert extends TestCase {
@@ -714,7 +717,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
@Test
public void testFinalClass() throws Exception {
try {
TemplateBuilder.build(FinalModifierClass.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class);
Assert.assertNull(builder);// no available builder
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class);
assertTrue(true);
} catch (TemplateBuildException e) {
fail();
@@ -731,7 +736,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
@Test
public void testInterfaceType00() throws Exception {
try {
TemplateBuilder.build(SampleInterface.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
Assert.assertNull(builder);// no available builder
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
fail();
} catch (TemplateBuildException e) {
assertTrue(true);
@@ -742,7 +749,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
@Test
public void testInterfaceType01() throws Exception {
try {
TemplateBuilder.build(SampleInterface.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
Assert.assertNull(builder);// no available builder
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
fail();
} catch (TemplateBuildException e) {
assertTrue(true);

View File

@@ -24,7 +24,11 @@ import org.msgpack.Unpacker;
import org.msgpack.annotation.MessagePackMessage;
import org.msgpack.annotation.MessagePackOrdinalEnum;
import org.msgpack.annotation.Optional;
import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface;
import org.msgpack.template.builder.BuilderSelectorRegistry;
import org.msgpack.template.builder.TemplateBuilder;
import junit.framework.Assert;
import junit.framework.TestCase;
public class TestTemplateBuilderPackUnpack extends TestCase {
@@ -714,7 +718,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
@Test
public void testFinalClass() throws Exception {
try {
TemplateBuilder.build(FinalModifierClass.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class);
Assert.assertNull(builder);
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class);
assertTrue(true);
} catch (TemplateBuildException e) {
fail();
@@ -731,7 +737,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
@Test
public void testInterfaceType00() throws Exception {
try {
TemplateBuilder.build(SampleInterface.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
Assert.assertNull(builder);
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
fail();
} catch (TemplateBuildException e) {
assertTrue(true);
@@ -742,7 +750,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
@Test
public void testInterfaceType01() throws Exception {
try {
TemplateBuilder.build(SampleInterface.class);
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
Assert.assertNull(builder);
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
fail();
} catch (TemplateBuildException e) {
assertTrue(true);