mirror of
https://github.com/msgpack/msgpack-c
synced 2026-06-08 16:11:40 +00:00
Implement Scala MessagePack.
Change Java MessagePack to fit Scala's. Minor version up for Java's MessagePack.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#Mon Apr 19 22:18:48 JST 2010
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
#Sat Mar 26 02:44:20 JST 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
||||
@@ -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>
|
||||
|
||||
+17
-1
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.msgpack</groupId>
|
||||
<artifactId>msgpack</artifactId>
|
||||
<version>0.5.1-devel</version>
|
||||
<version>0.5.2-SNAPSHOT</version>
|
||||
<description>MessagePack for Java</description>
|
||||
|
||||
<name>MessagePack for Java</name>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ 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.FieldList;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
|
||||
public class MessagePack {
|
||||
public static byte[] pack(Object obj) {
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 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;
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 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.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.*;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
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 java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
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) ;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ 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.*;
|
||||
|
||||
@@ -34,11 +35,14 @@ import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.ClassClassPath;
|
||||
|
||||
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 +58,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,471 +105,40 @@ 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 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();
|
||||
}
|
||||
}
|
||||
|
||||
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 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++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||
@Override
|
||||
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||
// FIXME private / packagefields
|
||||
//for(FieldEntry e : entries) {
|
||||
// Field f = e.getField();
|
||||
@@ -556,7 +150,7 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
Template[] tmpls = new Template[entries.length];
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
tmpls[i] = null;
|
||||
} else {
|
||||
@@ -565,10 +159,21 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
BuildContext bc = new BuildContext(this);
|
||||
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);
|
||||
@@ -610,6 +215,6 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
|
||||
return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -22,17 +22,26 @@ import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
|
||||
public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
private static ReflectionTemplateBuilder instance;
|
||||
public class ReflectionTemplateBuilder extends CustomTemplateBuilder {
|
||||
/*private static ReflectionTemplateBuilder instance;
|
||||
public synchronized static ReflectionTemplateBuilder getInstance() {
|
||||
if(instance == null) {
|
||||
instance = new ReflectionTemplateBuilder();
|
||||
}
|
||||
return instance;
|
||||
}*/
|
||||
|
||||
IFieldEntryReader reader = new FieldEntryReader();
|
||||
|
||||
@Override
|
||||
public IFieldEntryReader getFieldEntryReader(){
|
||||
return reader;
|
||||
}
|
||||
|
||||
private ReflectionTemplateBuilder() {
|
||||
public ReflectionTemplateBuilder() {
|
||||
}
|
||||
|
||||
static abstract class ReflectionFieldEntry extends FieldEntry {
|
||||
@@ -373,9 +382,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -384,7 +394,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);
|
||||
@@ -411,159 +421,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];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,33 +26,55 @@ 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;
|
||||
import org.msgpack.Templates;
|
||||
|
||||
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) {
|
||||
@@ -102,7 +124,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);
|
||||
@@ -129,7 +151,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);
|
||||
@@ -150,7 +182,7 @@ public class TemplateRegistry {
|
||||
}
|
||||
|
||||
if(forceBuild) {
|
||||
tmpl = TemplateBuilder.build(target);
|
||||
tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target);
|
||||
register(target, tmpl);
|
||||
return tmpl;
|
||||
}
|
||||
@@ -198,8 +230,5 @@ public class TemplateRegistry {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
public static void setTemplateBuilder(TemplateBuilder builder) {
|
||||
TemplateBuilder.setInstance(builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
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);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 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.*;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.List;
|
||||
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 abstract Template buildTemplate(Type targetType);
|
||||
/*
|
||||
// Override this method
|
||||
public abstract Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries);
|
||||
|
||||
// Override this method
|
||||
public abstract Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries);
|
||||
|
||||
// Override this method
|
||||
public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim);
|
||||
|
||||
public abstract IFieldEntryReader getFieldEntryReader();
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist));
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) {
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption));
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass) {
|
||||
FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass);
|
||||
return buildTemplate(targetClass, implicitOption);
|
||||
}
|
||||
|
||||
public Template buildOrdinalEnumTemplate(Class<?> targetClass) {
|
||||
checkOrdinalEnumValidation(targetClass);
|
||||
Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants();
|
||||
return buildOrdinalEnumTemplate(targetClass, entries);
|
||||
}
|
||||
|
||||
public Template buildArrayTemplate(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 buildArrayTemplate(arrayType, baseType, baseClass, dim);
|
||||
}
|
||||
|
||||
private static Type getComponentType(Type arrayType) {
|
||||
if(arrayType instanceof GenericArrayType) {
|
||||
return ((GenericArrayType)arrayType).getGenericComponentType();
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
|
||||
private static TemplateBuilder selectDefaultTemplateBuilder() {
|
||||
try {
|
||||
// FIXME JavassistTemplateBuilder doesn't work on DalvikVM
|
||||
if(System.getProperty("java.vm.name").equals("Dalvik")) {
|
||||
return ReflectionTemplateBuilder.getInstance();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return JavassistTemplateBuilder.getInstance();
|
||||
}
|
||||
|
||||
public synchronized static void setInstance(TemplateBuilder builder) {
|
||||
instance = builder;
|
||||
}
|
||||
|
||||
public static Template build(Class<?> targetClass) {
|
||||
return instance.buildTemplate(targetClass);
|
||||
}
|
||||
|
||||
public static Template build(Class<?> targetClass, FieldOption implicitOption) {
|
||||
return instance.buildTemplate(targetClass, implicitOption);
|
||||
}
|
||||
|
||||
public static Template build(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
return instance.buildTemplate(targetClass, flist);
|
||||
}
|
||||
|
||||
public static Template buildOrdinalEnum(Class<?> targetClass) {
|
||||
return instance.buildOrdinalEnumTemplate(targetClass);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
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 static void checkOrdinalEnumValidation(Class<?> targetClass) {
|
||||
if(!targetClass.isEnum()) {
|
||||
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
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++) {
|
||||
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;
|
||||
}*/
|
||||
|
||||
/*static 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;
|
||||
}*/
|
||||
/*
|
||||
private static 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 readImplicitFieldOption(Class<?> targetClass) {
|
||||
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
|
||||
if(a == null) {
|
||||
return FieldOption.DEFAULT;
|
||||
}
|
||||
return a.value();
|
||||
}
|
||||
|
||||
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;
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import org.msgpack.template.JavassistTemplateBuilder;
|
||||
|
||||
public interface BuildContextFactory {
|
||||
|
||||
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,10 @@ import org.junit.Test;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestArrays extends TestCase {
|
||||
|
||||
|
||||
|
||||
|
||||
@MessagePackMessage
|
||||
public static class PrimitiveTest {
|
||||
public PrimitiveTest() { }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+2207
File diff suppressed because it is too large
Load Diff
+1417
File diff suppressed because it is too large
Load Diff
+1422
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# use glob syntax.
|
||||
syntax: glob
|
||||
*.ser
|
||||
*.class
|
||||
*~
|
||||
*.bak
|
||||
#*.off
|
||||
*.old
|
||||
|
||||
# eclipse conf file
|
||||
.settings
|
||||
.classpath
|
||||
.project
|
||||
.manager
|
||||
.scala_dependencies
|
||||
|
||||
# idea
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
# building
|
||||
target
|
||||
build
|
||||
null
|
||||
tmp*
|
||||
dist
|
||||
test-output
|
||||
build.log
|
||||
|
||||
# other scm
|
||||
.svn
|
||||
.CVS
|
||||
.hg*
|
||||
|
||||
# switch to regexp syntax.
|
||||
# syntax: regexp
|
||||
# ^\.pc/
|
||||
|
||||
#SHITTY output not in target directory
|
||||
build.log
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.msgpack</groupId>
|
||||
<artifactId>scala-msgpack</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>My wonderfull scala app</description>
|
||||
<inceptionYear>2010</inceptionYear>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>My License</name>
|
||||
<url>http://....</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.5</maven.compiler.source>
|
||||
<maven.compiler.target>1.5</maven.compiler.target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<scala.version>2.8.1</scala.version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>msgpack.org</id>
|
||||
<name>MessagePack Repository for Maven</name>
|
||||
<url>http://msgpack.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<!--
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>scala-tools.org</id>
|
||||
<name>Scala-Tools Maven2 Repository</name>
|
||||
<url>http://scala-tools.org/repo-releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>scala-tools.org</id>
|
||||
<name>Scala-Tools Maven2 Repository</name>
|
||||
<url>http://scala-tools.org/repo-releases</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
-->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.scala-lang</groupId>
|
||||
<artifactId>scala-library</artifactId>
|
||||
<version>${scala.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scala-tools.testing</groupId>
|
||||
<artifactId>specs_${scala.version}</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.msgpack</groupId>
|
||||
<artifactId>msgpack</artifactId>
|
||||
<version>0.5.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<uniqueVersion>false</uniqueVersion>
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/scala</sourceDirectory>
|
||||
<testSourceDirectory>src/test/scala</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.scala-tools</groupId>
|
||||
<artifactId>maven-scala-plugin</artifactId>
|
||||
<version>2.15.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<args>
|
||||
<arg>-make:transitive</arg>
|
||||
<arg>-dependencyfile</arg>
|
||||
<arg>${project.build.directory}/.scala_dependencies</arg>
|
||||
</args>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<useFile>false</useFile>
|
||||
<disableXmlReport>true</disableXmlReport>
|
||||
<!-- If you have classpath issue like NoDefClassError,... -->
|
||||
<!-- useManifestOnlyJar>false</useManifestOnlyJar -->
|
||||
<includes>
|
||||
<include>**/*Test.*</include>
|
||||
<include>**/*Suite.*</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<!-- ここはこのままでOK -->
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- ここでpackageのPhaseで実行されるように設定している-->
|
||||
<execution>
|
||||
<id>make-assembly</id> <!-- this is used for inheritance merges -->
|
||||
<phase>package</phase> <!-- append to the packaging phase. -->
|
||||
<goals>
|
||||
<goal>single</goal> <!-- goals == mojos -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.msgpack
|
||||
|
||||
/**
|
||||
* @author ${user.name}
|
||||
*/
|
||||
object App {
|
||||
|
||||
def foo(x : Array[String]) = x.foldLeft("")((a,b) => a + b)
|
||||
|
||||
def main(args : Array[String]) {
|
||||
println( "Hello World!" )
|
||||
println("concat arguments = " + foo(args))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
package org.msgpack
|
||||
|
||||
import _root_.javassist.{CtClass, CtNewConstructor}
|
||||
import annotation._
|
||||
import template._
|
||||
import java.lang.Class
|
||||
import collection.immutable.{ListMap, TreeMap}
|
||||
import java.lang.reflect.{Type, Modifier, Method, Field}
|
||||
import java.lang.annotation.{Annotation => JavaAnnotation}
|
||||
import javassist.{JavassistTemplate, BuildContextBase, BuildContext}
|
||||
import scala.collection.JavaConverters._
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/10
|
||||
* Time: 12:29
|
||||
*/
|
||||
|
||||
|
||||
class BuildContextForScala(builder : JavassistTemplateBuilder) extends BuildContextBase[IFieldEntry](builder){
|
||||
|
||||
var entries : Array[IFieldEntry] = null
|
||||
var origClass : Class[_] = null
|
||||
var origName : String = null
|
||||
var templates : Array[Template] = null
|
||||
var minimumArrayLength : Int = 0
|
||||
|
||||
def buildTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = {
|
||||
this.entries = entries;
|
||||
this.templates = templates;
|
||||
this.origClass = targetClass;
|
||||
this.origName = this.origClass.getName();
|
||||
build(this.origName);
|
||||
}
|
||||
|
||||
def setSuperClass() = {
|
||||
tmplCtClass.setSuperclass(director.getCtClass(classOf[JavassistTemplate].getName))
|
||||
}
|
||||
|
||||
def buildConstructor() = {
|
||||
val newCtCons = CtNewConstructor.make(
|
||||
Array[CtClass](
|
||||
director.getCtClass(classOf[Class[_]].getName),
|
||||
director.getCtClass(classOf[Template].getName + "[]")
|
||||
),
|
||||
new Array[CtClass](0),
|
||||
tmplCtClass
|
||||
)
|
||||
this.tmplCtClass.addConstructor(newCtCons)
|
||||
}
|
||||
def buildInstance(c : Class[_]) = {
|
||||
val cons = c.getConstructor(classOf[Class[_]], classOf[Array[Template]])
|
||||
val tmpl = cons.newInstance(origClass,templates)
|
||||
tmpl.asInstanceOf[Template]
|
||||
}
|
||||
override def buildMethodInit() = {
|
||||
this.minimumArrayLength = 0;
|
||||
var i : Int = 0
|
||||
for(e <- entries) {
|
||||
if(e.isRequired() || e.isNullable()) {
|
||||
this.minimumArrayLength = i+1;
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
lazy val newInstanceDeclaration : String = {
|
||||
|
||||
def defCon = "new " + origClass.getName + "();"
|
||||
try{
|
||||
val c = origClass.getClassLoader.loadClass(origClass.getName + "$")
|
||||
if(Modifier.isPublic(c.getModifiers)){
|
||||
val method = c.getMethod("apply")
|
||||
|
||||
if(Modifier.isPublic(method.getModifiers) &&
|
||||
origClass.isAssignableFrom(method.getReturnType)){
|
||||
val staticField = c.getDeclaredField("MODULE$")
|
||||
"%s.%s.apply();".format(c.getName,staticField.getName)
|
||||
}else{
|
||||
defCon
|
||||
}
|
||||
}else{
|
||||
defCon
|
||||
}
|
||||
}catch{
|
||||
case e : ClassNotFoundException => {
|
||||
defCon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected def buildPackMethodBody() : String = {
|
||||
resetStringBuilder();
|
||||
buildString("{");
|
||||
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
|
||||
buildString("$1.packArray(%d);", entries.length.asInstanceOf[AnyRef]);
|
||||
for(i <- 0 until entries.length) {
|
||||
val e = entries(i)
|
||||
|
||||
if(!e.isAvailable) {
|
||||
buildString("$1.packNil();");
|
||||
}else{
|
||||
val t = e.getType;
|
||||
if(t.isPrimitive()) {
|
||||
buildString("$1.%s(_$$_t.%s());", primitivePackName(t), e.getName());
|
||||
} else {
|
||||
buildString("if(_$$_t.%s() == null) {", e.getName());
|
||||
if(!e.isNullable() && !e.isOptional()) {
|
||||
buildString("throw new %s();", classOf[MessageTypeException].getName());
|
||||
} else {
|
||||
buildString("$1.packNil();");
|
||||
}
|
||||
buildString("} else {");
|
||||
buildString(" this.templates[%d].pack($1, _$$_t.%s());", i.asInstanceOf[AnyRef], e.getName());
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
|
||||
def buildUnpackMethodBody() : String = {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("int length = $1.unpackArray();");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]);
|
||||
buildString(" throw new %s();", classOf[MessageTypeException].getName());
|
||||
buildString("}");
|
||||
|
||||
for(i <- 0 until this.minimumArrayLength) {
|
||||
val e = entries(i);
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
}else{
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", classOf[MessageTypeException].getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s_$eq(null);", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
val t = e.getType();
|
||||
if(t.isPrimitive()) {
|
||||
buildString("_$$_t.%s_$eq( $1.%s() );", e.getName(), primitiveUnpackName(t));
|
||||
} else {
|
||||
buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s()));", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
|
||||
for(i <- this.minimumArrayLength until entries.length) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]);
|
||||
|
||||
val e = entries(i);
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
}else{
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
val t = e.getType();
|
||||
if(t.isPrimitive()) {
|
||||
buildString("_$$_t.%s_$eq( $1.%s());", e.getName(), primitiveUnpackName(t));
|
||||
} else {
|
||||
buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("for(int i=%d; i < length; i++) {", entries.length.asInstanceOf[AnyRef]);
|
||||
buildString(" $1.unpackObject();");
|
||||
buildString("}");
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected override def buildConvertMethodBody() : String = {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("%s[] array = $1.asArray();", classOf[MessagePackObject].getName());
|
||||
buildString("int length = array.length;");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]);
|
||||
buildString(" throw new %s();", classOf[MessageTypeException].getName());
|
||||
buildString("}");
|
||||
|
||||
buildString("%s obj;", classOf[MessagePackObject].getName());
|
||||
|
||||
for(i <- 0 until this.minimumArrayLength) {
|
||||
val e = entries(i);
|
||||
if(e.isAvailable()) {
|
||||
buildString("obj = array[%d];", i.asInstanceOf[AnyRef]);
|
||||
buildString("if(obj.isNil()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", classOf[MessageTypeException].getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s_$eq( null );", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
val t = e.getType();
|
||||
if(t.isPrimitive()) {
|
||||
buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t));
|
||||
} else {
|
||||
buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
|
||||
for(i <- this.minimumArrayLength until entries.length) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]);
|
||||
|
||||
val e = entries(i);
|
||||
if(e.isAvailable()) {
|
||||
|
||||
|
||||
buildString("obj = array[%d];", i.asInstanceOf[AnyRef]);
|
||||
buildString("if(obj.isNil()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
val t = e.getType();
|
||||
if(t.isPrimitive()) {
|
||||
buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t));
|
||||
} else {
|
||||
buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
}
|
||||
|
||||
class ScalaFieldEntryReader extends IFieldEntryReader{
|
||||
|
||||
type Property = (Method,Method,Field)
|
||||
type PropertySet = (String,Property)
|
||||
|
||||
def readImplicitFieldOption(targetClass: Class[_]) = {
|
||||
FieldOption.NULLABLE
|
||||
}
|
||||
|
||||
def convertFieldEntries(targetClass: Class[_], flist: FieldList) = {
|
||||
|
||||
val list : List[FieldList.Entry] = flist.getList.asScala.toList
|
||||
|
||||
list.map( s => {
|
||||
if(s.isAvailable){
|
||||
val getter = targetClass.getMethod(s.getName)
|
||||
if(getter.getReturnType.getName != "void"){
|
||||
val setter = targetClass.getMethod(s.getName + "_$eq",getter.getReturnType)
|
||||
if(setter.getReturnType.getName == "void"){
|
||||
val f = try{targetClass.getDeclaredField(s.getName)}
|
||||
catch{
|
||||
case e : NoSuchFieldException => null
|
||||
}
|
||||
val prop = (s.getName,(getter,setter,f))
|
||||
convertToScalaFieldEntry(prop)
|
||||
}else{
|
||||
new ScalaFieldEntry("")
|
||||
}
|
||||
}else new ScalaFieldEntry("")
|
||||
}else{
|
||||
new ScalaFieldEntry("")
|
||||
}
|
||||
}).toArray
|
||||
}
|
||||
|
||||
def readFieldEntries(targetClass: Class[_], implicitOption: FieldOption) = {
|
||||
val props = findPropertyMethods(targetClass) filter( !hasAnnotation(_,classOf[Ignore]))
|
||||
|
||||
val indexed = indexing(props)
|
||||
indexed.map(convertToScalaFieldEntry(_))
|
||||
}
|
||||
|
||||
|
||||
def setter_?(method : Method) : Boolean = {
|
||||
Modifier.isPublic(method.getModifiers) &&
|
||||
method.getReturnType.getName == "void" &&
|
||||
method.getName.endsWith("_$eq") &&
|
||||
method.getParameterTypes.length == 1
|
||||
}
|
||||
|
||||
def getter_?(method : Method) : Boolean = {
|
||||
Modifier.isPublic(method.getModifiers) &&
|
||||
method.getReturnType.getName != "void" &&
|
||||
method.getParameterTypes.length == 0
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
def findPropertyMethods(targetClass: Class[_]) : Map[String,Property] = {
|
||||
var getters : Map[String,Method] = ListMap.empty
|
||||
var setters : Map[String,Method] = ListMap.empty
|
||||
|
||||
def extractName( n : String) = {
|
||||
n.substring(0,n.length - 4)
|
||||
}
|
||||
|
||||
//Find getters and setters
|
||||
for( m <- targetClass.getMethods){
|
||||
if(setter_?(m)){
|
||||
setters +=(extractName(m.getName) -> m)
|
||||
}else if(getter_?(m)){
|
||||
getters +=(m.getName -> m)
|
||||
}
|
||||
}
|
||||
|
||||
var props : Map[String,Property] = ListMap.empty
|
||||
|
||||
def sameType_?( getter : Method,setter : Method) = {
|
||||
getter.getReturnType == setter.getParameterTypes()(0)
|
||||
}
|
||||
|
||||
for(g <- getters){
|
||||
setters.get(g._1).map( s => {
|
||||
if(sameType_?(g._2,s)){
|
||||
|
||||
val name = g._1
|
||||
val f = try{targetClass.getDeclaredField(name)}
|
||||
catch{
|
||||
case e : NoSuchFieldException => null
|
||||
}
|
||||
|
||||
//TODO add validation for field
|
||||
props +=( name -> (g._2,s,f))
|
||||
}
|
||||
})
|
||||
}
|
||||
props
|
||||
}
|
||||
|
||||
def indexing( props : Map[String , Property]) : Array[PropertySet] = {
|
||||
val indexed = new Array[PropertySet](props.size)
|
||||
|
||||
var notIndexed : List[PropertySet] = Nil
|
||||
|
||||
for(s <- props){
|
||||
val i = getAnnotation(s,classOf[Index])
|
||||
if(i == null){
|
||||
notIndexed = notIndexed :+ s
|
||||
}else{
|
||||
val index = i.value
|
||||
if(indexed(index) != null){
|
||||
throw new TemplateBuildException("duplicated index: "+index);
|
||||
}else{
|
||||
try{
|
||||
indexed(index) = s
|
||||
}catch{
|
||||
case e : Exception => {
|
||||
throw new TemplateBuildException("invalid index: %s index must be 0 <= x < %s".format(index,indexed.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i <- 0 until indexed.length ){
|
||||
if(indexed(i) == null){
|
||||
indexed(i) = notIndexed.head
|
||||
notIndexed = notIndexed.drop(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
indexed
|
||||
}
|
||||
|
||||
def convertToScalaFieldEntry( propInfo : PropertySet) = {
|
||||
val entry = new ScalaFieldEntry(propInfo._1)
|
||||
entry.option = readFieldOption(propInfo,FieldOption.NULLABLE)
|
||||
entry.normalType = readValueType(propInfo)
|
||||
entry.genericType = readGenericType(propInfo)
|
||||
|
||||
entry
|
||||
}
|
||||
|
||||
|
||||
def hasAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : Boolean = {
|
||||
val getter = prop._2._1
|
||||
val setter = prop._2._2
|
||||
val field = prop._2._3
|
||||
getter.getAnnotation(classOfAnno) != null ||
|
||||
setter.getAnnotation(classOfAnno) != null ||
|
||||
{if(field != null) field.getAnnotation(classOfAnno) != null
|
||||
else false}
|
||||
}
|
||||
def getAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : T = {
|
||||
val getter = prop._2._1
|
||||
val setter = prop._2._2
|
||||
val field = prop._2._3
|
||||
|
||||
|
||||
|
||||
val a = getter.getAnnotation(classOfAnno)
|
||||
if(a != null){
|
||||
a
|
||||
}else{
|
||||
val b = setter.getAnnotation(classOfAnno)
|
||||
if(b != null){
|
||||
b
|
||||
}else if(field != null){
|
||||
field.getAnnotation(classOfAnno)
|
||||
}else{
|
||||
null.asInstanceOf[T]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def readFieldOption(prop : PropertySet , implicitOption : FieldOption) = {
|
||||
if(hasAnnotation(prop,classOf[Required])){
|
||||
FieldOption.REQUIRED
|
||||
} else if(hasAnnotation(prop,classOf[Optional])){
|
||||
FieldOption.OPTIONAL
|
||||
} else if(hasAnnotation(prop,classOf[Nullable])){
|
||||
if(readValueType(prop).isPrimitive){
|
||||
FieldOption.REQUIRED
|
||||
}else{
|
||||
FieldOption.NULLABLE
|
||||
}
|
||||
} else{
|
||||
if(implicitOption == FieldOption.NULLABLE){
|
||||
if(readValueType(prop).isPrimitive){
|
||||
FieldOption.REQUIRED
|
||||
}else{
|
||||
FieldOption.NULLABLE
|
||||
}
|
||||
}else{
|
||||
implicitOption
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def readValueType(prop : PropertySet) = {
|
||||
prop._2._1.getReturnType
|
||||
}
|
||||
def readGenericType(prop : PropertySet) = {
|
||||
prop._2._1.getGenericReturnType
|
||||
}
|
||||
}
|
||||
|
||||
class ScalaFieldEntry(name : String) extends IFieldEntry{
|
||||
|
||||
def getName() = name
|
||||
|
||||
def isNullable() = {getOption == FieldOption.NULLABLE}
|
||||
|
||||
def isOptional = {getOption == FieldOption.OPTIONAL}
|
||||
|
||||
def isRequired = {getOption == FieldOption.REQUIRED}
|
||||
|
||||
def isAvailable = {getOption != FieldOption.IGNORE}
|
||||
|
||||
var option : FieldOption = null
|
||||
|
||||
var genericType : Type = null
|
||||
|
||||
def getJavaTypeName = {
|
||||
if(getType.isArray){
|
||||
//TODO implement here
|
||||
getType.getName()
|
||||
}else{
|
||||
getType.getName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var normalType : Class[_] = null
|
||||
|
||||
def getOption() = option
|
||||
def getType() = normalType
|
||||
def getGenericType() = genericType
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.msgpack
|
||||
|
||||
import template._
|
||||
import builder.{MessagePackMessageBuilderSelector, BuilderSelectorRegistry}
|
||||
import template.javassist.BuildContextFactory
|
||||
import collection.mutable.{MutableList, LinkedList}
|
||||
import collection.mutable.{Map => MMap,HashMap => MHashMap}
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/10
|
||||
* Time: 1:34
|
||||
*/
|
||||
|
||||
object ScalaMessagePack {
|
||||
|
||||
{
|
||||
// for scala object
|
||||
BuilderSelectorRegistry.getInstance.insertBefore(
|
||||
MessagePackMessageBuilderSelector.NAME,
|
||||
new ScalaTemplateBuilderSelector)
|
||||
|
||||
// register scala's list classes
|
||||
TemplateRegistry.register(classOf[List[_]],new ImmutableListTemplate(AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[List[_]],new GenericTemplate1(classOf[ImmutableListTemplate]))
|
||||
TemplateRegistry.register(classOf[Seq[_]],new ImmutableListTemplate(AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[Seq[_]],new GenericTemplate1(classOf[ImmutableListTemplate]))
|
||||
TemplateRegistry.register(classOf[LinkedList[_]],new LinkedListTemplate(AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[LinkedList[_]],new GenericTemplate1(classOf[LinkedListTemplate]))
|
||||
TemplateRegistry.register(classOf[MutableList[_]],new MutableListCTemplate(AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[MutableList[_]],new GenericTemplate1(classOf[MutableListCTemplate]))
|
||||
|
||||
// register scala's map classes
|
||||
TemplateRegistry.register(classOf[Map[_,_]],new ImmutableMapTemplate(
|
||||
AnyTemplate.getInstance,AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[Map[_,_]],new GenericTemplate2(
|
||||
classOf[ImmutableMapTemplate]))
|
||||
TemplateRegistry.register(classOf[MMap[_,_]],new MutableHashMapTemplate(
|
||||
AnyTemplate.getInstance,AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[MMap[_,_]],new GenericTemplate2(
|
||||
classOf[MutableHashMapTemplate]))
|
||||
TemplateRegistry.register(classOf[MHashMap[_,_]],new MutableHashMapTemplate(
|
||||
AnyTemplate.getInstance,AnyTemplate.getInstance))
|
||||
TemplateRegistry.registerGeneric(classOf[MHashMap[_,_]],new GenericTemplate2(
|
||||
classOf[MutableHashMapTemplate]))
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* dammy method for initialize
|
||||
*/
|
||||
def init() = {}
|
||||
|
||||
|
||||
def pack( obj : Any) = {
|
||||
MessagePack.pack(obj.asInstanceOf[AnyRef])
|
||||
}
|
||||
|
||||
def unpack[T]( buffer : Array[Byte])(implicit manifest : ClassManifest[T]) : T = {
|
||||
MessagePack.unpack[T]( buffer, manifest.erasure.asInstanceOf[Class[T]])
|
||||
}
|
||||
|
||||
def unpackD(buffer : Array[Byte]) = {
|
||||
MessagePack.unpack(buffer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.msgpack;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/10
|
||||
* Time: 1:52
|
||||
*/
|
||||
|
||||
class ScalaTemplateBuilder {
|
||||
|
||||
|
||||
def pack(v : Int) = {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.msgpack
|
||||
|
||||
import annotation.MessagePackMessage
|
||||
import template.builder.BuilderSelector
|
||||
import java.lang.reflect.Type
|
||||
import template.javassist.BuildContextFactory
|
||||
import template.JavassistTemplateBuilder
|
||||
import java.lang.annotation.{Annotation => JAnnotation}
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/14
|
||||
* Time: 17:59
|
||||
*/
|
||||
|
||||
class ScalaTemplateBuilderSelector extends BuilderSelector
|
||||
{
|
||||
val b = new JavassistTemplateBuilder()
|
||||
|
||||
{
|
||||
b.setFieldEntryReader(new ScalaFieldEntryReader)
|
||||
b.setBuildContextFactory(new BuildContextFactory{
|
||||
def createBuildContext(builder: JavassistTemplateBuilder) = {
|
||||
new BuildContextForScala(builder)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def getName = "ScalaMessagePackMessageTemplateBuilderSelector";
|
||||
|
||||
def getTemplateBuilder(targetType: Type) = {
|
||||
b
|
||||
}
|
||||
|
||||
def matchType(targetType: Type) = {
|
||||
val c : Class[_] = targetType.asInstanceOf[Class[Object]]
|
||||
isAnnotated(c, classOf[MessagePackMessage]) &&
|
||||
classOf[ScalaObject].isAssignableFrom(c)//c.isAssignableFrom(classOf[ScalaObject])
|
||||
|
||||
}
|
||||
|
||||
private def isAnnotated(targetType : Class[_], annotation : Class[_ <: JAnnotation]) = {
|
||||
targetType.getAnnotation(annotation) != null
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.msgpack.template
|
||||
|
||||
import org.msgpack._
|
||||
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 2:25
|
||||
*/
|
||||
|
||||
class ImmutableListTemplate(elementTemplate : Template) extends Template{
|
||||
def unpack(pac: Unpacker, to: AnyRef) = {
|
||||
|
||||
val length = pac.unpackArray();
|
||||
val array : Array[Object] = new Array(length)
|
||||
|
||||
for(i <- 0 until length){
|
||||
array(i) = elementTemplate.unpack(pac,null)
|
||||
}
|
||||
|
||||
array.toList
|
||||
|
||||
}
|
||||
|
||||
def pack(pk: Packer, target: AnyRef) = {
|
||||
|
||||
val list = try{target.asInstanceOf[List[_]]}
|
||||
catch{
|
||||
case e : ClassCastException => {
|
||||
throw new MessageTypeException("target is not List type: " + target.getClass());
|
||||
}
|
||||
case e : NullPointerException => {
|
||||
throw new MessageTypeException(new NullPointerException("target is null."));
|
||||
}
|
||||
}
|
||||
|
||||
pk.packArray(list.size)
|
||||
for( e <- list){
|
||||
elementTemplate.pack(pk,e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def convert(from: MessagePackObject, to: AnyRef) = {
|
||||
from.asArray.map(elementTemplate.convert(_,null)).toList
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.msgpack.template
|
||||
|
||||
import org.msgpack._
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 11:11
|
||||
*/
|
||||
|
||||
class ImmutableMapTemplate(keyTemplate : Template , valueTemplate : Template) extends Template {
|
||||
|
||||
def unpack(pac: Unpacker, to: AnyRef) = {
|
||||
|
||||
val length = pac.unpackMap()
|
||||
val array : Array[(Object,Object)] = new Array(length)
|
||||
|
||||
for(i <- 0 until length){
|
||||
array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null))
|
||||
}
|
||||
|
||||
array.toMap
|
||||
|
||||
}
|
||||
|
||||
def pack(pk: Packer, target: AnyRef) = {
|
||||
|
||||
val map = try{target.asInstanceOf[Map[_,_]]}
|
||||
catch{
|
||||
case e : ClassCastException => {
|
||||
throw new MessageTypeException("target is not List type: " + target.getClass());
|
||||
}
|
||||
case e : NullPointerException => {
|
||||
throw new MessageTypeException(new NullPointerException("target is null."));
|
||||
}
|
||||
}
|
||||
pk.packMap(map.size)
|
||||
for( e <- map){
|
||||
keyTemplate.pack(pk,e._1)
|
||||
valueTemplate.pack(pk,e._2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def convert(from: MessagePackObject, to: AnyRef) = {
|
||||
from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toMap
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.msgpack.template
|
||||
|
||||
import org.msgpack.{MessagePackObject, Packer, Unpacker, Template}
|
||||
import collection.mutable.{MutableList, LinearSeq, LinkedList}
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 2:37
|
||||
*/
|
||||
|
||||
abstract class MutableListTemplate[T <: LinearSeq[_]](elementTemplate : Template) extends Template{
|
||||
def unpack(pac: Unpacker, to: AnyRef) = {
|
||||
|
||||
val length = pac.unpackArray();
|
||||
|
||||
var list : LinearSeq[_] = if(to == null){
|
||||
toList(new Array[Object](0))
|
||||
}else{
|
||||
to.asInstanceOf[T]
|
||||
}
|
||||
for(i <- 0 until length){
|
||||
list = list :+ elementTemplate.unpack(pac,null)
|
||||
}
|
||||
|
||||
list
|
||||
|
||||
}
|
||||
def toList(array : Array[Object]) : T
|
||||
|
||||
def pack(pk: Packer, target: AnyRef) = {
|
||||
|
||||
val list = target.asInstanceOf[LinearSeq[_]]
|
||||
pk.packArray(list.size)
|
||||
for( e <- list){
|
||||
elementTemplate.pack(pk,e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def convert(from: MessagePackObject, to: AnyRef) = {
|
||||
toList(from.asArray.map(elementTemplate.convert(_,null)))
|
||||
}
|
||||
}
|
||||
|
||||
class LinkedListTemplate(elementTemplate : Template) extends MutableListTemplate[LinkedList[_]](elementTemplate){
|
||||
def toList(array : Array[Object]) = LinkedList(array :_*)
|
||||
}
|
||||
class MutableListCTemplate(elementTemplate : Template) extends MutableListTemplate[MutableList[_]](elementTemplate){
|
||||
def toList(array : Array[Object]) = {
|
||||
val list : MutableList[Object] = new MutableList
|
||||
list ++= array
|
||||
list
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.msgpack.template;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 12:06
|
||||
*/
|
||||
|
||||
import org.msgpack._
|
||||
import collection.mutable.{HashMap,Map => MMap}
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
abstract class MutableMapTemplate[T <: MMap[_,_]](keyTemplate : Template , valueTemplate : Template) extends Template {
|
||||
|
||||
def unpack(pac: Unpacker, to: AnyRef) = {
|
||||
|
||||
val length = pac.unpackMap()
|
||||
val array : Array[(Object,Object)] = new Array(length)
|
||||
|
||||
for(i <- 0 until length){
|
||||
array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null))
|
||||
}
|
||||
|
||||
toMap(array)
|
||||
|
||||
}
|
||||
|
||||
def toMap(array : Array[(Object,Object)]) : T
|
||||
|
||||
|
||||
def pack(pk: Packer, target: AnyRef) = {
|
||||
|
||||
val map = try{target.asInstanceOf[MMap[_,_]]}
|
||||
catch{
|
||||
case e : ClassCastException => {
|
||||
throw new MessageTypeException("target is not List type: " + target.getClass());
|
||||
}
|
||||
case e : NullPointerException => {
|
||||
throw new MessageTypeException(new NullPointerException("target is null."));
|
||||
}
|
||||
}
|
||||
pk.packMap(map.size)
|
||||
for( e <- map){
|
||||
keyTemplate.pack(pk,e._1)
|
||||
valueTemplate.pack(pk,e._2)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
def convert(from: MessagePackObject, to: AnyRef) = {
|
||||
toMap(from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toArray)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MutableHashMapTemplate(keyTemplate : Template , valueTemplate : Template)
|
||||
extends MutableMapTemplate[HashMap[_,_]](keyTemplate,valueTemplate ) {
|
||||
|
||||
def toMap(array : Array[(Object,Object)]) = {
|
||||
HashMap(array :_*)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.msgpack;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 2:13
|
||||
*/
|
||||
|
||||
import annotation.MessagePackMessage
|
||||
import collection.mutable.{MutableList, LinkedList}
|
||||
|
||||
@MessagePackMessage
|
||||
class ClassWithList {
|
||||
var immutable : List[String] = Nil
|
||||
|
||||
var mutable : LinkedList[String] = LinkedList.empty
|
||||
|
||||
var mutable2 : MutableList[String] = new MutableList
|
||||
|
||||
//var tuple2 : (String,String) = (null,null)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.msgpack;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/11
|
||||
* Time: 2:22
|
||||
*/
|
||||
|
||||
import annotation.MessagePackMessage
|
||||
import scala.collection.mutable.{Map => MMap}
|
||||
|
||||
@MessagePackMessage
|
||||
class ClassWithMap {
|
||||
|
||||
var immutable : Map[String,String] = Map.empty
|
||||
|
||||
var mutable : MMap[String,String] = MMap.empty
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.msgpack
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
import org.specs._
|
||||
import org.specs.matcher._
|
||||
import org.specs.runner.{ JUnitSuiteRunner, JUnit }
|
||||
import scala.collection.mutable.LinkedList
|
||||
|
||||
//import org.scalacheck.Gen
|
||||
|
||||
/**
|
||||
* Sample specification.
|
||||
*
|
||||
* This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest
|
||||
* Or using maven: mvn test
|
||||
*
|
||||
* For more information on how to write or run specifications, please visit: http://code.google.com/p/specs.
|
||||
*
|
||||
*/
|
||||
@RunWith(classOf[JUnitSuiteRunner])
|
||||
class CollectionPackSpec extends Specification with JUnit {
|
||||
|
||||
"ScalaMessagePack" should {
|
||||
"pack scala-list" in {
|
||||
val c = new ClassWithList
|
||||
|
||||
c.immutable = List("a","b","c")
|
||||
c.mutable = LinkedList("a","b","d")
|
||||
c.mutable2 ++= List("gh","fjei")
|
||||
//c.tuple2 = ("hoge","wahoo")
|
||||
|
||||
val b = ScalaMessagePack.pack(c)
|
||||
val des = ScalaMessagePack.unpack[ClassWithList](b)
|
||||
|
||||
des.immutable must be_==(c.immutable)
|
||||
des.mutable must be_==(c.mutable)
|
||||
//des.tuple2 must be_==(c.tuple2)
|
||||
|
||||
val mpo = ScalaMessagePack.unpackD(b)
|
||||
val des2 = mpo.convert(classOf[ClassWithList])
|
||||
|
||||
des2.immutable must be_==(c.immutable)
|
||||
des2.mutable must be_==(c.mutable)
|
||||
|
||||
}
|
||||
"pack scala-map" in {
|
||||
val c = new ClassWithMap
|
||||
c.immutable = Map("a" -> "hoge","b" -> "fuga","c" -> "hehe")
|
||||
c.mutable = scala.collection.mutable.Map("d" -> "oo" , "e" -> "aa")
|
||||
|
||||
val b = ScalaMessagePack.pack(c)
|
||||
val des = ScalaMessagePack.unpack[ClassWithMap](b)
|
||||
|
||||
des.immutable must be_==(c.immutable)
|
||||
des.mutable must be_==(c.mutable)
|
||||
|
||||
val mpo = ScalaMessagePack.unpackD(b)
|
||||
val des2 = mpo.convert(classOf[ClassWithMap])
|
||||
|
||||
des2.immutable must be_==(c.immutable)
|
||||
des2.mutable must be_==(c.mutable)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.msgpack
|
||||
|
||||
import annotation.MessagePackMessage
|
||||
import annotation.{Optional, Index}
|
||||
import java.util.Date
|
||||
;
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: takeshita
|
||||
* Date: 11/03/10
|
||||
* Time: 1:35
|
||||
*/
|
||||
|
||||
@MessagePackMessage
|
||||
class SampleClass {
|
||||
var name : String = "hoge"
|
||||
var number : Int = 2
|
||||
|
||||
}
|
||||
|
||||
trait SampleTrait {
|
||||
|
||||
var traitName : String = ""
|
||||
|
||||
var traitNum : Int = 12
|
||||
|
||||
}
|
||||
|
||||
class SampleClass2 extends SampleClass with SampleTrait {
|
||||
|
||||
|
||||
@Index(3)
|
||||
var sampleClass2Name : String = "sampleclass2"
|
||||
|
||||
@Index(0)
|
||||
def sampleClass2Num : Int = 22
|
||||
def sampleClass2Num_=(v : Int) = {}
|
||||
|
||||
val notProperty : String ="This is not prop.Only getter"
|
||||
|
||||
// wrong property
|
||||
def wrongValue : Int = 53
|
||||
def wrongValue_=(v : String) = {}
|
||||
|
||||
}
|
||||
|
||||
object NotDefaultCons{
|
||||
|
||||
def apply() : NotDefaultCons2 = {
|
||||
new NotDefaultCons2()
|
||||
}
|
||||
}
|
||||
@MessagePackMessage
|
||||
class NotDefaultCons(var name : String){
|
||||
}
|
||||
|
||||
class NotDefaultCons2 extends NotDefaultCons("hoge")
|
||||
|
||||
@MessagePackMessage
|
||||
class BasicalTypes{
|
||||
|
||||
var intVar : Int = 0
|
||||
var longVar : Long = 0
|
||||
var shortVar : Short = 0
|
||||
var byteVar : Byte = 0
|
||||
var boolVar : Boolean = false
|
||||
|
||||
var floatVar : Float = 0
|
||||
var doubleVar : Double = 0
|
||||
|
||||
var strVar : String = ""
|
||||
|
||||
var dateVar : Date = null
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package org.msgpack
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
import org.specs._
|
||||
import org.specs.matcher._
|
||||
import org.specs.runner.{ JUnitSuiteRunner, JUnit }
|
||||
//import org.scalacheck.Gen
|
||||
|
||||
/**
|
||||
* Sample specification.
|
||||
*
|
||||
* This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest
|
||||
* Or using maven: mvn test
|
||||
*
|
||||
* For more information on how to write or run specifications, please visit: http://code.google.com/p/specs.
|
||||
*
|
||||
*/
|
||||
@RunWith(classOf[JUnitSuiteRunner])
|
||||
class ScalaFieldEntryReaderSpec extends Specification with JUnit {
|
||||
|
||||
"ScalaFieldEntryReader" should {
|
||||
"check setter " in {
|
||||
val reader = new ScalaFieldEntryReader()
|
||||
|
||||
val c = classOf[SampleClass]
|
||||
|
||||
reader.setter_?(c.getMethod("name")) must be_==(false)
|
||||
reader.setter_?(c.getMethod("name_$eq",classOf[String])) must be_==(true)
|
||||
}
|
||||
"check getter " in {
|
||||
val reader = new ScalaFieldEntryReader()
|
||||
|
||||
val c = classOf[SampleClass]
|
||||
|
||||
reader.getter_?(c.getMethod("name")) must be_==(true)
|
||||
reader.getter_?(c.getMethod("name_$eq",classOf[String])) must be_==(false)
|
||||
}
|
||||
|
||||
"find props " in {
|
||||
val reader = new ScalaFieldEntryReader()
|
||||
|
||||
{
|
||||
val c = classOf[SampleClass]
|
||||
|
||||
val props = reader.findPropertyMethods(c)
|
||||
|
||||
props.size must be_==(2)
|
||||
props must haveKey("name")
|
||||
props must haveKey("number")
|
||||
}
|
||||
|
||||
{
|
||||
val c = classOf[SampleClass2]
|
||||
|
||||
val props = reader.findPropertyMethods(c)
|
||||
|
||||
println(props.keys)
|
||||
|
||||
props.size must be_==(6)
|
||||
props must haveKey("name")
|
||||
props must haveKey("number")
|
||||
props must haveKey("traitName")
|
||||
props must haveKey("traitNum")
|
||||
props must haveKey("sampleClass2Name")
|
||||
props must haveKey("sampleClass2Num")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"indexing " in {
|
||||
val reader = new ScalaFieldEntryReader()
|
||||
|
||||
val c = classOf[SampleClass2]
|
||||
|
||||
def printDecs(c : Class[_]) : Unit = {
|
||||
println(c.getName + "---")
|
||||
val ds = c.getDeclaredMethods
|
||||
ds.foreach(m => {println(m)
|
||||
println(m.getAnnotations.toList)
|
||||
})
|
||||
if(c.getSuperclass != classOf[Object]){
|
||||
printDecs(c.getSuperclass)
|
||||
}
|
||||
}
|
||||
printDecs(c)
|
||||
|
||||
|
||||
|
||||
val props = reader.findPropertyMethods(c)
|
||||
|
||||
val indexed = reader.indexing(props)
|
||||
|
||||
println(indexed.map(_._1).toList)
|
||||
|
||||
indexed.size must be_==(6)
|
||||
indexed(0)._1 must be_==("sampleClass2Num")
|
||||
indexed(3)._1 must be_==("sampleClass2Name")
|
||||
indexed must notContain(null)
|
||||
|
||||
}
|
||||
|
||||
"read entries" in {
|
||||
val reader = new ScalaFieldEntryReader()
|
||||
|
||||
val c = classOf[SampleClass2]
|
||||
import org.msgpack.template.FieldOption
|
||||
|
||||
val e = reader.readFieldEntries(c, FieldOption.NULLABLE)
|
||||
|
||||
e.size must be_==(6)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.msgpack
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
import org.specs._
|
||||
import org.specs.matcher._
|
||||
import org.specs.runner.{ JUnitSuiteRunner, JUnit }
|
||||
import java.util.Date
|
||||
|
||||
//import org.scalacheck.Gen
|
||||
|
||||
/**
|
||||
* Sample specification.
|
||||
*
|
||||
* This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest
|
||||
* Or using maven: mvn test
|
||||
*
|
||||
* For more information on how to write or run specifications, please visit: http://code.google.com/p/specs.
|
||||
*
|
||||
*/
|
||||
@RunWith(classOf[JUnitSuiteRunner])
|
||||
class ScalaMessagePackTest extends Specification with JUnit /*with ScalaCheck*/ {
|
||||
|
||||
"ScalaMessagePackTest" should {
|
||||
"pack and unpack" in {
|
||||
|
||||
val sc = new SampleClass()
|
||||
sc.name = "Test object"
|
||||
sc.number = 123456
|
||||
|
||||
println("Sampleclass is inherit ScalaObject " + classOf[ScalaObject].isAssignableFrom(classOf[SampleClass]))
|
||||
new ScalaTemplateBuilderSelector().matchType(classOf[SampleClass]) must be_==(true)
|
||||
val b = ScalaMessagePack.pack(sc)
|
||||
|
||||
val deser = ScalaMessagePack.unpack[SampleClass](b)
|
||||
|
||||
deser.name must be_==(sc.name)
|
||||
deser.number must be_==(sc.number)
|
||||
|
||||
val mso = ScalaMessagePack.unpackD(b)
|
||||
val conv = mso.convert(classOf[SampleClass])
|
||||
conv.name must be_==(sc.name)
|
||||
conv.number must be_==(sc.number)
|
||||
}
|
||||
"check basical types" in {
|
||||
val v = new BasicalTypes
|
||||
v.intVar = 20
|
||||
v.longVar = 11
|
||||
v.shortVar = 7
|
||||
v.byteVar = 1
|
||||
v.floatVar = 1.5f
|
||||
v.doubleVar = 2.5
|
||||
v.strVar = "fugafuga"
|
||||
v.dateVar = new Date(1233333)
|
||||
|
||||
val b = ScalaMessagePack.pack(v)
|
||||
val des : BasicalTypes = ScalaMessagePack.unpack[BasicalTypes](b)
|
||||
|
||||
des.intVar must be_==(v.intVar)
|
||||
des.longVar must be_==(v.longVar)
|
||||
des.shortVar must be_==(v.shortVar)
|
||||
des.byteVar must be_==(v.byteVar)
|
||||
des.floatVar must be_==(v.floatVar)
|
||||
des.doubleVar must be_==(v.doubleVar)
|
||||
des.strVar must be_==(v.strVar)
|
||||
des.dateVar must be_==(v.dateVar)
|
||||
|
||||
|
||||
}
|
||||
|
||||
"pack and unpack none-default constructor class" in {
|
||||
|
||||
val sc = new NotDefaultCons("hehehehe")
|
||||
|
||||
val b = ScalaMessagePack.pack(sc)
|
||||
|
||||
val deser = ScalaMessagePack.unpack[NotDefaultCons](b)
|
||||
|
||||
deser.name must be_==(sc.name)
|
||||
|
||||
val mso = ScalaMessagePack.unpackD(b)
|
||||
val conv = mso.convert(classOf[NotDefaultCons])
|
||||
conv.name must be_==(sc.name)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user