mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 21:18:23 +01:00
java: Merged takezoux2's branch for 'MessagePack for Scala'
This commit is contained in:
commit
ecbb8f8711
17
java/msgpack.iml
Normal file
17
java/msgpack.iml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
16
java/pom.xml
16
java/pom.xml
@ -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,7 +22,6 @@ import java.io.InputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
import org.msgpack.template.TemplateBuilder;
|
||||
import org.msgpack.template.TemplateClassWriter;
|
||||
import org.msgpack.template.FieldList;
|
||||
|
||||
|
@ -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-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.msgpack.template.FieldOption;
|
||||
|
||||
/**
|
||||
* Annotation for java beans class
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MessagePackBeans {
|
||||
FieldOption value() default FieldOption.DEFAULT;
|
||||
}
|
@ -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 {
|
||||
}
|
||||
|
143
java/src/main/java/org/msgpack/template/BeansFieldEntry.java
Normal file
143
java/src/main/java/org/msgpack/template/BeansFieldEntry.java
Normal file
@ -0,0 +1,143 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.*;
|
||||
import org.msgpack.*;
|
||||
|
||||
/**
|
||||
* Field entry for Java beans property.
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public class BeansFieldEntry implements IFieldEntry {
|
||||
|
||||
PropertyDescriptor desc;
|
||||
FieldOption option = FieldOption.DEFAULT;
|
||||
|
||||
public BeansFieldEntry(PropertyDescriptor desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return desc.getDisplayName();
|
||||
}
|
||||
public String getGetterName(){
|
||||
return desc.getReadMethod().getName();
|
||||
}
|
||||
public String getSetterName(){
|
||||
return desc.getWriteMethod().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
return desc.getPropertyType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJavaTypeName() {
|
||||
Class<?> type = getType();
|
||||
if(type.isArray()) {
|
||||
return arrayTypeToString(type);
|
||||
} else {
|
||||
return type.getName();
|
||||
}
|
||||
}
|
||||
static String arrayTypeToString(Class<?> type) {
|
||||
int dim = 1;
|
||||
Class<?> baseType = type.getComponentType();
|
||||
while(baseType.isArray()) {
|
||||
baseType = baseType.getComponentType();
|
||||
dim += 1;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseType.getName());
|
||||
for (int i = 0; i < dim; ++i) {
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getGenericType() {
|
||||
return desc.getReadMethod().getGenericReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldOption getOption() {
|
||||
return option;
|
||||
}
|
||||
public void setOption(FieldOption option){
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return option != FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isRequired()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return option == FieldOption.REQUIRED;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isOptional()
|
||||
*/
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return option == FieldOption.OPTIONAL;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isNullable()
|
||||
*/
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return option == FieldOption.NULLABLE;
|
||||
}
|
||||
|
||||
public Object get(Object target){
|
||||
try {
|
||||
return desc.getReadMethod().invoke(target);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessageTypeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MessageTypeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MessageTypeException(e);
|
||||
}
|
||||
}
|
||||
public void set(Object target , Object value){
|
||||
try {
|
||||
desc.getWriteMethod().invoke(target, value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new MessageTypeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MessageTypeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MessageTypeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.msgpack.annotation.Ignore;
|
||||
import org.msgpack.annotation.Index;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.Nullable;
|
||||
import org.msgpack.annotation.Optional;
|
||||
import org.msgpack.annotation.Required;
|
||||
|
||||
/**
|
||||
* List up Java beans property methods.
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public class BeansFieldEntryReader implements IFieldEntryReader{
|
||||
|
||||
|
||||
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
List<FieldList.Entry> src = flist.getList();
|
||||
FieldEntry[] result = new FieldEntry[src.size()];
|
||||
for(int i=0; i < src.size(); i++) {
|
||||
FieldList.Entry s = src.get(i);
|
||||
if(s.isAvailable()) {
|
||||
result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
|
||||
} else {
|
||||
result[i] = new FieldEntry();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFieldEntry[] readFieldEntries(Class<?> targetClass,
|
||||
FieldOption implicitOption) {
|
||||
BeanInfo desc;
|
||||
try {
|
||||
desc = Introspector.getBeanInfo(targetClass);
|
||||
} catch (IntrospectionException e1) {
|
||||
throw new TemplateBuildException("Class must be java beans class:" + targetClass.getName());
|
||||
}
|
||||
|
||||
PropertyDescriptor[] props = desc.getPropertyDescriptors();
|
||||
ArrayList<PropertyDescriptor> list = new ArrayList<PropertyDescriptor>();
|
||||
for(int i = 0;i < props.length;i++){
|
||||
PropertyDescriptor pd = props[i];
|
||||
if(!isIgnoreProp(pd)){
|
||||
list.add(pd);
|
||||
}
|
||||
}
|
||||
props = new PropertyDescriptor[list.size()];
|
||||
list.toArray(props);
|
||||
|
||||
BeansFieldEntry[] entries = new BeansFieldEntry[props.length];
|
||||
for(int i = 0;i < props.length;i++){
|
||||
PropertyDescriptor p = props[i];
|
||||
int index = readPropIndex(p);
|
||||
if(index >= 0){
|
||||
if(entries[index] != null){
|
||||
throw new TemplateBuildException("duplicated index: "+index);
|
||||
}
|
||||
if(index >= entries.length){
|
||||
throw new TemplateBuildException("invalid index: "+index);
|
||||
}
|
||||
entries[index] = new BeansFieldEntry(p);
|
||||
props[index] = null;
|
||||
}
|
||||
}
|
||||
int insertIndex = 0;
|
||||
for(int i = 0;i < props.length;i++){
|
||||
PropertyDescriptor p = props[i];
|
||||
if(p != null){
|
||||
while(entries[insertIndex] != null){
|
||||
insertIndex++;
|
||||
}
|
||||
entries[insertIndex] = new BeansFieldEntry(p);
|
||||
}
|
||||
|
||||
}
|
||||
for(int i = 0;i < entries.length;i++){
|
||||
BeansFieldEntry e = entries[i];
|
||||
FieldOption op = readPropOption(e.desc, implicitOption);
|
||||
e.setOption(op);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
public FieldOption readImplicitFieldOption(Class<?> targetClass) {
|
||||
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
|
||||
if(a == null) {
|
||||
return FieldOption.DEFAULT;
|
||||
}
|
||||
return a.value();
|
||||
}
|
||||
|
||||
|
||||
private FieldOption readPropOption(PropertyDescriptor desc, FieldOption implicitOption) {
|
||||
|
||||
FieldOption forGetter = readMethodOption(desc.getReadMethod());
|
||||
if(forGetter != FieldOption.DEFAULT){
|
||||
return forGetter;
|
||||
}
|
||||
FieldOption forSetter = readMethodOption(desc.getWriteMethod());
|
||||
if(forSetter != FieldOption.DEFAULT){
|
||||
return forSetter;
|
||||
}else{
|
||||
return implicitOption;
|
||||
}
|
||||
|
||||
}
|
||||
private FieldOption readMethodOption(Method method){
|
||||
|
||||
if(isAnnotated(method, Ignore.class)) {
|
||||
return FieldOption.IGNORE;
|
||||
} else if(isAnnotated(method, Required.class)) {
|
||||
return FieldOption.REQUIRED;
|
||||
} else if(isAnnotated(method, Optional.class)) {
|
||||
return FieldOption.OPTIONAL;
|
||||
} else if(isAnnotated(method, Nullable.class)) {
|
||||
if(method.getDeclaringClass().isPrimitive()) {
|
||||
return FieldOption.REQUIRED;
|
||||
} else {
|
||||
return FieldOption.NULLABLE;
|
||||
}
|
||||
}
|
||||
return FieldOption.DEFAULT;
|
||||
}
|
||||
|
||||
private int readPropIndex(PropertyDescriptor desc) {
|
||||
|
||||
int forGetter = readMethodIndex(desc.getReadMethod());
|
||||
if(forGetter >= 0){
|
||||
return forGetter;
|
||||
}
|
||||
int forSetter = readMethodIndex(desc.getWriteMethod());
|
||||
return forSetter;
|
||||
}
|
||||
private int readMethodIndex(Method method){
|
||||
Index a = method.getAnnotation(Index.class);
|
||||
if(a == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return a.value();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
boolean isIgnoreProp(PropertyDescriptor desc){
|
||||
if(desc == null)return true;
|
||||
Method getter = desc.getReadMethod();
|
||||
Method setter = desc.getWriteMethod();
|
||||
return getter == null ||
|
||||
setter == null ||
|
||||
!Modifier.isPublic(getter.getModifiers()) ||
|
||||
!Modifier.isPublic(setter.getModifiers()) ||
|
||||
isAnnotated(getter,Ignore.class) ||
|
||||
isAnnotated(setter, Ignore.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.msgpack.AbstractTemplate;
|
||||
import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.BooleanFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.ByteFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.DoubleFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.FloatFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.IntFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.LongFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.NullFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.ObjectFieldEntry;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder.ShortFieldEntry;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
|
||||
/**
|
||||
* Class for building java reflection template builder for java beans class.
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public class BeansReflectionTemplateBuilder extends CustomTemplateBuilder{
|
||||
|
||||
IFieldEntryReader reader = new BeansFieldEntryReader();
|
||||
|
||||
public BeansReflectionTemplateBuilder(){}
|
||||
|
||||
@Override
|
||||
public IFieldEntryReader getFieldEntryReader(){
|
||||
return reader;
|
||||
}
|
||||
|
||||
static class ReflectionEntry{
|
||||
BeansFieldEntry entry;
|
||||
public ReflectionEntry(BeansFieldEntry entry){
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
public void pack(Object value , Packer packer) throws IOException{
|
||||
packer.pack(value);
|
||||
}
|
||||
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||
entry.set(target, obj.convert(entry.getType()));
|
||||
}
|
||||
|
||||
public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException {
|
||||
entry.set(target, unpacker.unpack(entry.getType()));
|
||||
}
|
||||
|
||||
public void setNull(Object target){
|
||||
entry.set(target, null);
|
||||
}
|
||||
|
||||
public boolean isRequired(){
|
||||
return entry.isRequired();
|
||||
}
|
||||
public boolean isNullable(){
|
||||
return entry.isNullable();
|
||||
}
|
||||
public boolean isAvailable(){
|
||||
return entry.isAvailable();
|
||||
}
|
||||
public boolean isOptional(){
|
||||
return entry.isOptional();
|
||||
}
|
||||
public Object get(Object target){
|
||||
return entry.get(target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ObjectFieldEntry extends ReflectionEntry{
|
||||
Template template;
|
||||
public ObjectFieldEntry(BeansFieldEntry entry,Template template){
|
||||
super(entry);
|
||||
this.template = template;
|
||||
}
|
||||
public void pack(Object value , Packer packer) throws IOException{
|
||||
template.pack(packer,value);
|
||||
}
|
||||
public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException {
|
||||
Class<Object> type = (Class<Object>)entry.getType();
|
||||
Object fieldReference = entry.get(target);
|
||||
Object valueReference = template.convert(obj, fieldReference);
|
||||
if(valueReference != fieldReference) {
|
||||
entry.set(target, valueReference);
|
||||
}
|
||||
}
|
||||
|
||||
public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException {
|
||||
|
||||
Class<Object> type = (Class<Object>)entry.getType();
|
||||
Object fieldReference = entry.get(target);
|
||||
Object valueReference = template.unpack(unpacker, fieldReference);
|
||||
if(valueReference != fieldReference) {
|
||||
entry.set(target, valueReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class BeansReflectionTemplate extends AbstractTemplate{
|
||||
|
||||
Class<?> targetClass;
|
||||
ReflectionEntry[] entries = null;
|
||||
protected int minimumArrayLength;
|
||||
|
||||
public BeansReflectionTemplate(
|
||||
Class<?> targetClass,
|
||||
ReflectionEntry[] entries){
|
||||
this.targetClass = targetClass;
|
||||
this.entries = entries;
|
||||
this.minimumArrayLength = 0;
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
ReflectionEntry e = entries[i];
|
||||
if(e.isRequired() || e.isNullable()) {
|
||||
this.minimumArrayLength = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
|
||||
pk.packArray(entries.length);
|
||||
for(ReflectionEntry e : entries){
|
||||
if(!e.isAvailable()){
|
||||
pk.packNil();
|
||||
continue;
|
||||
}
|
||||
Object obj = e.get(target);
|
||||
if(obj == null) {
|
||||
if(!e.isNullable() && !e.isOptional()) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
pk.packNil();
|
||||
} else {
|
||||
pk.pack(obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
try {
|
||||
if(to == null) {
|
||||
to = targetClass.newInstance();
|
||||
}
|
||||
|
||||
int length = pac.unpackArray();
|
||||
if(length < minimumArrayLength) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i=0; i < minimumArrayLength; i++) {
|
||||
ReflectionEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
pac.unpackObject();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(pac.tryUnpackNull()) {
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
throw new MessageTypeException();
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
e.setNull(to);
|
||||
}
|
||||
} else {
|
||||
e.unpack(to,pac);
|
||||
//e.set(to, pac.unpack(e.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
int max = length < entries.length ? length : entries.length;
|
||||
for(; i < max; i++) {
|
||||
ReflectionEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
pac.unpackObject();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(pac.tryUnpackNull()) {
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
} else {
|
||||
e.unpack(to, pac);
|
||||
//e.set(to, pac.unpack(e.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
for(; i < length; i++) {
|
||||
pac.unpackObject();
|
||||
}
|
||||
|
||||
return to;
|
||||
|
||||
} catch (MessageTypeException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new MessageTypeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(MessagePackObject from, Object to)
|
||||
throws MessageTypeException {
|
||||
try {
|
||||
if(to == null) {
|
||||
to = targetClass.newInstance();
|
||||
}
|
||||
|
||||
MessagePackObject[] array = from.asArray();
|
||||
int length = array.length;
|
||||
if(length < minimumArrayLength) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i=0; i < minimumArrayLength; i++) {
|
||||
ReflectionEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MessagePackObject obj = array[i];
|
||||
if(obj.isNil()) {
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
throw new MessageTypeException();
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
e.setNull(to);
|
||||
//e.set(to,null);
|
||||
}
|
||||
} else {
|
||||
e.convert(to, obj);
|
||||
//e.set(to, from.convert(e.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
int max = length < entries.length ? length : entries.length;
|
||||
for(; i < max; i++) {
|
||||
ReflectionEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MessagePackObject obj = array[i];
|
||||
if(obj.isNil()) {
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
} else {
|
||||
e.convert(to, obj);
|
||||
//e.set(to, obj.convert(e.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
return to;
|
||||
|
||||
} catch (MessageTypeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new MessageTypeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||
|
||||
ReflectionEntry[] refEntries = new ReflectionEntry[entries.length];
|
||||
for(int i = 0;i < entries.length;i++){
|
||||
BeansFieldEntry e = (BeansFieldEntry)entries[i];
|
||||
Class<?> type = e.getType();
|
||||
if(type.equals(boolean.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(byte.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(short.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(int.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(long.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(float.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else if(type.equals(double.class)) {
|
||||
refEntries[i] = new ReflectionEntry(e);
|
||||
} else {
|
||||
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
|
||||
refEntries[i] = new ObjectFieldEntry(e, tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new BeansReflectionTemplate(targetClass,refEntries);
|
||||
}
|
||||
|
||||
|
||||
}
|
143
java/src/main/java/org/msgpack/template/FieldEntry.java
Normal file
143
java/src/main/java/org/msgpack/template/FieldEntry.java
Normal file
@ -0,0 +1,143 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.annotation.*;
|
||||
|
||||
public class FieldEntry implements IFieldEntry {
|
||||
private Field field;
|
||||
private FieldOption option;
|
||||
|
||||
public FieldEntry() {
|
||||
this.field = null;
|
||||
this.option = FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
public FieldEntry(FieldEntry e) {
|
||||
this.field = e.field;
|
||||
this.option = e.option;
|
||||
}
|
||||
|
||||
public FieldEntry(Field field, FieldOption option) {
|
||||
this.field = field;
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#getType()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#getJavaTypeName()
|
||||
*/
|
||||
@Override
|
||||
public String getJavaTypeName() {
|
||||
Class<?> type = field.getType();
|
||||
if(type.isArray()) {
|
||||
return arrayTypeToString(type);
|
||||
} else {
|
||||
return type.getName();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#getGenericType()
|
||||
*/
|
||||
@Override
|
||||
public Type getGenericType() {
|
||||
return field.getGenericType();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#getOption()
|
||||
*/
|
||||
@Override
|
||||
public FieldOption getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isAvailable()
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return option != FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isRequired()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return option == FieldOption.REQUIRED;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isOptional()
|
||||
*/
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return option == FieldOption.OPTIONAL;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.msgpack.template.IFieldEntry#isNullable()
|
||||
*/
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return option == FieldOption.NULLABLE;
|
||||
}
|
||||
|
||||
static String arrayTypeToString(Class<?> type) {
|
||||
int dim = 1;
|
||||
Class<?> baseType = type.getComponentType();
|
||||
while(baseType.isArray()) {
|
||||
baseType = baseType.getComponentType();
|
||||
dim += 1;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseType.getName());
|
||||
for (int i = 0; i < dim; ++i) {
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
182
java/src/main/java/org/msgpack/template/FieldEntryReader.java
Normal file
182
java/src/main/java/org/msgpack/template/FieldEntryReader.java
Normal file
@ -0,0 +1,182 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.msgpack.annotation.Ignore;
|
||||
import org.msgpack.annotation.Index;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.Nullable;
|
||||
import org.msgpack.annotation.Optional;
|
||||
import org.msgpack.annotation.Required;
|
||||
|
||||
public class FieldEntryReader implements IFieldEntryReader{
|
||||
|
||||
|
||||
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
List<FieldList.Entry> src = flist.getList();
|
||||
FieldEntry[] result = new FieldEntry[src.size()];
|
||||
for(int i=0; i < src.size(); i++) {
|
||||
FieldList.Entry s = src.get(i);
|
||||
if(s.isAvailable()) {
|
||||
result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption());
|
||||
} else {
|
||||
result[i] = new FieldEntry();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFieldEntry[] readFieldEntries(Class<?> targetClass,
|
||||
FieldOption implicitOption) {
|
||||
Field[] allFields = readAllFields(targetClass);
|
||||
|
||||
/* index:
|
||||
* @Index(0) int field_a; // 0
|
||||
* int field_b; // 1
|
||||
* @Index(3) int field_c; // 3
|
||||
* int field_d; // 4
|
||||
* @Index(2) int field_e; // 2
|
||||
* int field_f; // 5
|
||||
*/
|
||||
List<FieldEntry> indexed = new ArrayList<FieldEntry>();
|
||||
int maxIndex = -1;
|
||||
for(Field f : allFields) {
|
||||
FieldOption opt = readFieldOption(f, implicitOption);
|
||||
if(opt == FieldOption.IGNORE) {
|
||||
// skip
|
||||
continue;
|
||||
}
|
||||
|
||||
int index = readFieldIndex(f, maxIndex);
|
||||
|
||||
if(indexed.size() > index && indexed.get(index) != null) {
|
||||
throw new TemplateBuildException("duplicated index: "+index);
|
||||
}
|
||||
if(index < 0) {
|
||||
throw new TemplateBuildException("invalid index: "+index);
|
||||
}
|
||||
|
||||
while(indexed.size() <= index) {
|
||||
indexed.add(null);
|
||||
}
|
||||
indexed.set(index, new FieldEntry(f, opt));
|
||||
|
||||
if(maxIndex < index) {
|
||||
maxIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
FieldEntry[] result = new FieldEntry[maxIndex+1];
|
||||
for(int i=0; i < indexed.size(); i++) {
|
||||
FieldEntry e = indexed.get(i);
|
||||
if(e == null) {
|
||||
result[i] = new FieldEntry();
|
||||
} else {
|
||||
result[i] = e;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public FieldOption readImplicitFieldOption(Class<?> targetClass) {
|
||||
MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class);
|
||||
if(a == null) {
|
||||
return FieldOption.DEFAULT;
|
||||
}
|
||||
return a.value();
|
||||
}
|
||||
|
||||
private Field[] readAllFields(Class<?> targetClass) {
|
||||
// order: [fields of super class, ..., fields of this class]
|
||||
List<Field[]> succ = new ArrayList<Field[]>();
|
||||
int total = 0;
|
||||
for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) {
|
||||
Field[] fields = c.getDeclaredFields();
|
||||
total += fields.length;
|
||||
succ.add(fields);
|
||||
}
|
||||
Field[] result = new Field[total];
|
||||
int off = 0;
|
||||
for(int i=succ.size()-1; i >= 0; i--) {
|
||||
Field[] fields = succ.get(i);
|
||||
System.arraycopy(fields, 0, result, off, fields.length);
|
||||
off += fields.length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static FieldOption readFieldOption(Field field, FieldOption implicitOption) {
|
||||
int mod = field.getModifiers();
|
||||
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
|
||||
return FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
if(isAnnotated(field, Ignore.class)) {
|
||||
return FieldOption.IGNORE;
|
||||
} else if(isAnnotated(field, Required.class)) {
|
||||
return FieldOption.REQUIRED;
|
||||
} else if(isAnnotated(field, Optional.class)) {
|
||||
return FieldOption.OPTIONAL;
|
||||
} else if(isAnnotated(field, Nullable.class)) {
|
||||
if(field.getDeclaringClass().isPrimitive()) {
|
||||
return FieldOption.REQUIRED;
|
||||
} else {
|
||||
return FieldOption.NULLABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if(implicitOption != FieldOption.DEFAULT) {
|
||||
return implicitOption;
|
||||
}
|
||||
|
||||
// default mode:
|
||||
// transient : Ignore
|
||||
// public : Required
|
||||
// others : Ignore
|
||||
if(Modifier.isTransient(mod)) {
|
||||
return FieldOption.IGNORE;
|
||||
} else if(Modifier.isPublic(mod)) {
|
||||
return FieldOption.REQUIRED;
|
||||
} else {
|
||||
return FieldOption.IGNORE;
|
||||
}
|
||||
}
|
||||
|
||||
private static int readFieldIndex(Field field, int maxIndex) {
|
||||
Index a = field.getAnnotation(Index.class);
|
||||
if(a == null) {
|
||||
return maxIndex + 1;
|
||||
} else {
|
||||
return a.value();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
42
java/src/main/java/org/msgpack/template/IFieldEntry.java
Normal file
42
java/src/main/java/org/msgpack/template/IFieldEntry.java
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public interface IFieldEntry {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract Class<?> getType();
|
||||
|
||||
public abstract String getJavaTypeName();
|
||||
|
||||
public abstract Type getGenericType();
|
||||
|
||||
public abstract FieldOption getOption();
|
||||
|
||||
public abstract boolean isAvailable();
|
||||
|
||||
public abstract boolean isRequired();
|
||||
|
||||
public abstract boolean isOptional();
|
||||
|
||||
public abstract boolean isNullable();
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
public interface IFieldEntryReader {
|
||||
|
||||
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException;
|
||||
public IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption);
|
||||
public FieldOption readImplicitFieldOption(Class<?> targetClass) ;
|
||||
}
|
@ -17,28 +17,21 @@
|
||||
//
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.Thread;
|
||||
|
||||
import org.msgpack.*;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
import org.msgpack.template.javassist.*;
|
||||
|
||||
public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
public class JavassistTemplateBuilder extends CustomTemplateBuilder {
|
||||
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
|
||||
|
||||
private static JavassistTemplateBuilder instance;
|
||||
@ -54,12 +47,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
getInstance().pool.appendClassPath(new LoaderClassPath(cl));
|
||||
}
|
||||
|
||||
private JavassistTemplateBuilder() {
|
||||
|
||||
IFieldEntryReader reader = new FieldEntryReader();
|
||||
|
||||
public void setFieldEntryReader(IFieldEntryReader reader){
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
BuildContextFactory buildContextFactory = new BuildContextFactory() {
|
||||
|
||||
@Override
|
||||
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) {
|
||||
|
||||
return new BuildContext(builder);
|
||||
}
|
||||
};
|
||||
public void setBuildContextFactory(BuildContextFactory factory){
|
||||
this.buildContextFactory = factory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public JavassistTemplateBuilder() {
|
||||
pool = new ClassPool();
|
||||
boolean appended = false;
|
||||
ClassLoader cl = null;
|
||||
try {
|
||||
Thread.currentThread().getContextClassLoader();
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
if (cl != null) {
|
||||
pool.appendClassPath(new LoaderClassPath(cl));
|
||||
appended = true;
|
||||
@ -80,556 +94,38 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
pool.appendSystemPath();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Replace FieldEntryReader and BuilderContextFactory.
|
||||
* you can replace field entry rules and generated codes easily.
|
||||
* @param reader
|
||||
* @param buildContextFactory
|
||||
*/
|
||||
public JavassistTemplateBuilder(IFieldEntryReader reader,BuildContextFactory buildContextFactory ){
|
||||
this();
|
||||
this.reader = reader;
|
||||
this.buildContextFactory = buildContextFactory;
|
||||
}
|
||||
|
||||
|
||||
protected ClassPool pool;
|
||||
|
||||
private int seqId = 0;
|
||||
|
||||
CtClass makeCtClass(String className) {
|
||||
public CtClass makeCtClass(String className) {
|
||||
return pool.makeClass(className);
|
||||
}
|
||||
|
||||
CtClass getCtClass(String className) throws NotFoundException {
|
||||
public CtClass getCtClass(String className) throws NotFoundException {
|
||||
return pool.get(className);
|
||||
}
|
||||
|
||||
int nextSeqId() {
|
||||
public int nextSeqId() {
|
||||
return seqId++;
|
||||
}
|
||||
|
||||
private static abstract class BuildContextBase {
|
||||
protected JavassistTemplateBuilder director;
|
||||
|
||||
protected String tmplName;
|
||||
|
||||
protected CtClass tmplCtClass;
|
||||
|
||||
protected abstract void setSuperClass() throws CannotCompileException, NotFoundException;
|
||||
|
||||
protected abstract void buildConstructor() throws CannotCompileException, NotFoundException;
|
||||
|
||||
protected void buildMethodInit() { }
|
||||
|
||||
protected abstract String buildPackMethodBody();
|
||||
|
||||
protected abstract String buildUnpackMethodBody();
|
||||
|
||||
protected abstract String buildConvertMethodBody();
|
||||
|
||||
protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException;
|
||||
|
||||
public BuildContextBase(JavassistTemplateBuilder director) {
|
||||
this.director = director;
|
||||
}
|
||||
|
||||
protected void write(final String className, final String directoryName) {
|
||||
try {
|
||||
reset(className, false);
|
||||
buildClass();
|
||||
buildConstructor();
|
||||
buildMethodInit();
|
||||
buildPackMethod();
|
||||
buildUnpackMethod();
|
||||
buildConvertMethod();
|
||||
writeClassFile(directoryName);
|
||||
} catch (Exception e) {
|
||||
String code = getBuiltString();
|
||||
if(code != null) {
|
||||
LOG.error("builder: " + code, e);
|
||||
throw new TemplateBuildException("cannot compile: " + code, e);
|
||||
} else {
|
||||
throw new TemplateBuildException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void writeClassFile(final String directoryName) throws CannotCompileException, IOException {
|
||||
tmplCtClass.writeFile(directoryName);
|
||||
}
|
||||
|
||||
protected Template build(final String className) {
|
||||
try {
|
||||
reset(className, true);
|
||||
buildClass();
|
||||
buildConstructor();
|
||||
buildMethodInit();
|
||||
buildPackMethod();
|
||||
buildUnpackMethod();
|
||||
buildConvertMethod();
|
||||
return buildInstance(createClass());
|
||||
} catch (Exception e) {
|
||||
String code = getBuiltString();
|
||||
if(code != null) {
|
||||
LOG.error("builder: " + code, e);
|
||||
throw new TemplateBuildException("cannot compile: " + code, e);
|
||||
} else {
|
||||
throw new TemplateBuildException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void reset(String className, boolean isBuilt) {
|
||||
if (isBuilt) {
|
||||
tmplName = className + "_$$_Template" + director.nextSeqId();
|
||||
} else {
|
||||
tmplName = className + "_$$_Template";
|
||||
}
|
||||
tmplCtClass = director.makeCtClass(tmplName);
|
||||
}
|
||||
|
||||
protected void buildClass() throws CannotCompileException, NotFoundException {
|
||||
setSuperClass();
|
||||
tmplCtClass.addInterface(director.getCtClass(Template.class.getName()));
|
||||
}
|
||||
|
||||
protected void buildPackMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildPackMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = CtClass.voidType;
|
||||
String mname = "pack";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(Packer.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(IOException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected void buildUnpackMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildUnpackMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||
String mname = "unpack";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(Unpacker.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(MessageTypeException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected void buildConvertMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildConvertMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||
String mname = "convert";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(MessagePackObject.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(MessageTypeException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected Class<?> createClass() throws CannotCompileException {
|
||||
return (Class<?>) tmplCtClass.toClass(null, null);
|
||||
}
|
||||
|
||||
protected StringBuilder stringBuilder = null;
|
||||
|
||||
protected void resetStringBuilder() {
|
||||
stringBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
protected void buildString(String str) {
|
||||
stringBuilder.append(str);
|
||||
}
|
||||
|
||||
protected void buildString(String format, Object... args) {
|
||||
stringBuilder.append(String.format(format, args));
|
||||
}
|
||||
|
||||
protected String getBuiltString() {
|
||||
if(stringBuilder == null) {
|
||||
return null;
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class JavassistTemplate extends AbstractTemplate {
|
||||
public Class<?> targetClass;
|
||||
public Template[] templates;
|
||||
|
||||
public JavassistTemplate(Class<?> targetClass, Template[] templates) {
|
||||
this.targetClass = targetClass;
|
||||
this.templates = templates;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BuildContext extends BuildContextBase {
|
||||
protected FieldEntry[] entries;
|
||||
protected Class<?> origClass;
|
||||
protected String origName;
|
||||
protected Template[] templates;
|
||||
protected int minimumArrayLength;
|
||||
|
||||
public BuildContext(JavassistTemplateBuilder director) {
|
||||
super(director);
|
||||
}
|
||||
|
||||
public void writeTemplateClass(Class<?> targetClass, FieldEntry[] entries,
|
||||
Template[] templates, final String directoryName) {
|
||||
this.entries = entries;
|
||||
this.templates = templates;
|
||||
this.origClass = targetClass;
|
||||
this.origName = this.origClass.getName();
|
||||
write(this.origName, directoryName);
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) {
|
||||
this.entries = entries;
|
||||
this.templates = templates;
|
||||
this.origClass = targetClass;
|
||||
this.origName = this.origClass.getName();
|
||||
return build(this.origName);
|
||||
}
|
||||
|
||||
protected void setSuperClass() throws CannotCompileException, NotFoundException {
|
||||
this.tmplCtClass.setSuperclass(
|
||||
director.getCtClass(JavassistTemplate.class.getName()));
|
||||
}
|
||||
|
||||
protected void buildConstructor() throws CannotCompileException, NotFoundException {
|
||||
// Constructor(Class targetClass, Template[] templates)
|
||||
CtConstructor newCtCons = CtNewConstructor.make(
|
||||
new CtClass[] {
|
||||
director.getCtClass(Class.class.getName()),
|
||||
director.getCtClass(Template.class.getName()+"[]")
|
||||
},
|
||||
new CtClass[0],
|
||||
this.tmplCtClass);
|
||||
this.tmplCtClass.addConstructor(newCtCons);
|
||||
}
|
||||
|
||||
protected Template buildInstance(Class<?> targetClass, Class<?> tmplClass, Template[] tmpls) {
|
||||
try {
|
||||
Constructor<?> cons = tmplClass.getConstructor(new Class[] {
|
||||
Class.class,
|
||||
Template[].class
|
||||
});
|
||||
Object tmpl = cons.newInstance(new Object[] {
|
||||
targetClass,
|
||||
tmpls
|
||||
});
|
||||
return (Template)tmpl;
|
||||
} catch (Exception e) {
|
||||
throw new TemplateBuildException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
Constructor<?> cons = c.getConstructor(new Class[] {
|
||||
Class.class,
|
||||
Template[].class
|
||||
});
|
||||
Object tmpl = cons.newInstance(new Object[] {
|
||||
this.origClass,
|
||||
this.templates
|
||||
});
|
||||
return (Template)tmpl;
|
||||
}
|
||||
|
||||
protected void buildMethodInit() {
|
||||
this.minimumArrayLength = 0;
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
if(e.isRequired() || e.isNullable()) {
|
||||
this.minimumArrayLength = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String buildPackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{");
|
||||
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
|
||||
buildString("$1.packArray(%d);", entries.length);
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.packNil();");
|
||||
continue;
|
||||
}
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName());
|
||||
} else {
|
||||
buildString("if(_$$_t.%s == null) {", e.getName());
|
||||
if(!e.isNullable() && !e.isOptional()) {
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else {
|
||||
buildString("$1.packNil();");
|
||||
}
|
||||
buildString("} else {");
|
||||
buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName());
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildUnpackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("int length = $1.unpackArray();");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s = null;", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
FieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("for(int i=%d; i < length; i++) {", i);
|
||||
buildString(" $1.unpackObject();");
|
||||
buildString("}");
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildConvertMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
|
||||
buildString("int length = array.length;");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
buildString("%s obj;", MessagePackObject.class.getName());
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s = null;", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
FieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String primitivePackName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "packBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "packByte";
|
||||
} else if(type == short.class) {
|
||||
return "packShort";
|
||||
} else if(type == int.class) {
|
||||
return "packInt";
|
||||
} else if(type == long.class) {
|
||||
return "packLong";
|
||||
} else if(type == float.class) {
|
||||
return "packFloat";
|
||||
} else if(type == double.class) {
|
||||
return "packDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String primitiveUnpackName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "unpackBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "unpackByte";
|
||||
} else if(type == short.class) {
|
||||
return "unpackShort";
|
||||
} else if(type == int.class) {
|
||||
return "unpackInt";
|
||||
} else if(type == long.class) {
|
||||
return "unpackLong";
|
||||
} else if(type == float.class) {
|
||||
return "unpackFloat";
|
||||
} else if(type == double.class) {
|
||||
return "unpackDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String primitiveConvertName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "asBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "asByte";
|
||||
} else if(type == short.class) {
|
||||
return "asShort";
|
||||
} else if(type == int.class) {
|
||||
return "asInt";
|
||||
} else if(type == long.class) {
|
||||
return "asLong";
|
||||
} else if(type == float.class) {
|
||||
return "asFloat";
|
||||
} else if(type == double.class) {
|
||||
return "asDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadTemplateClass(Class<?> targetClass) {
|
||||
String tmplClassName = targetClass.getName() + "_$$_Template";
|
||||
ClassLoader cl = this.getClass().getClassLoader();// TODO
|
||||
try {
|
||||
return cl.loadClass(tmplClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.debug("Tmplate class not found: " + tmplClassName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Template initializeTemplate(Class<?> targetClass, Class<?> tmplClass, FieldEntry[] entries) {
|
||||
Template[] tmpls = toTemplates(entries);
|
||||
BuildContext bc = new BuildContext(this);
|
||||
return bc.buildInstance(targetClass, tmplClass, tmpls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTemplateClass(Class<?> targetClass, FieldEntry[] entries, String directoryName) {
|
||||
Template[] tmpls = toTemplates(entries);
|
||||
BuildContext bc = new BuildContext(this);
|
||||
bc.writeTemplateClass(targetClass, entries, tmpls, directoryName);
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||
Template[] tmpls = toTemplates(entries);
|
||||
BuildContext bc = new BuildContext(this);
|
||||
return bc.buildTemplate(targetClass, entries, tmpls);
|
||||
}
|
||||
|
||||
private static Template[] toTemplates(FieldEntry[] from) {
|
||||
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||
// FIXME private / packagefields
|
||||
//for(FieldEntry e : entries) {
|
||||
// Field f = e.getField();
|
||||
@ -639,9 +135,9 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
// }
|
||||
//}
|
||||
|
||||
Template[] tmpls = new Template[from.length];
|
||||
for(int i=0; i < from.length; i++) {
|
||||
FieldEntry e = from[i];
|
||||
Template[] tmpls = new Template[entries.length];
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
tmpls[i] = null;
|
||||
} else {
|
||||
@ -649,9 +145,22 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
tmpls[i] = tmpl;
|
||||
}
|
||||
}
|
||||
return tmpls;
|
||||
|
||||
BuildContextBase bc = getBuildContextFacotry().createBuildContext(this);
|
||||
return bc.buildTemplate(targetClass, entries, tmpls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFieldEntryReader getFieldEntryReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
public BuildContextFactory getBuildContextFacotry() {
|
||||
return buildContextFactory;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate {
|
||||
JavassistOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||
super(entries);
|
||||
@ -704,6 +213,6 @@ public class JavassistTemplateBuilder extends TemplateBuilder {
|
||||
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
|
||||
return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
@ -18,21 +18,21 @@
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
|
||||
public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
private static ReflectionTemplateBuilder instance;
|
||||
public synchronized static ReflectionTemplateBuilder getInstance() {
|
||||
if(instance == null) {
|
||||
instance = new ReflectionTemplateBuilder();
|
||||
}
|
||||
return instance;
|
||||
public class ReflectionTemplateBuilder extends CustomTemplateBuilder {
|
||||
IFieldEntryReader reader = new FieldEntryReader();
|
||||
|
||||
@Override
|
||||
public IFieldEntryReader getFieldEntryReader(){
|
||||
return reader;
|
||||
}
|
||||
|
||||
private ReflectionTemplateBuilder() {
|
||||
public ReflectionTemplateBuilder() {
|
||||
}
|
||||
|
||||
static abstract class ReflectionFieldEntry extends FieldEntry {
|
||||
@ -373,25 +373,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadTemplateClass(Class<?> targetClass) {
|
||||
throw new UnsupportedOperationException("Not supported by reflection-based template builder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Template initializeTemplate(Class<?> targetClass, Class<?> tmplClass, FieldEntry[] entries) {
|
||||
throw new UnsupportedOperationException("Not supported by reflection-based template builder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTemplateClass(Class<?> targetClass, FieldEntry[] entries,
|
||||
String directoryName) {
|
||||
throw new UnsupportedOperationException("Not supported by reflection-based template builder");
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||
for(FieldEntry e : entries) {
|
||||
Field f = e.getField();
|
||||
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||
// TODO Now it is simply cast.
|
||||
for(IFieldEntry e : entries) {
|
||||
Field f = ((FieldEntry)e).getField();
|
||||
int mod = f.getModifiers();
|
||||
if(!Modifier.isPublic(mod)) {
|
||||
f.setAccessible(true);
|
||||
@ -400,7 +385,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
FieldEntry e = (FieldEntry)entries[i];
|
||||
Class<?> type = e.getType();
|
||||
if(!e.isAvailable()) {
|
||||
res[i] = new NullFieldEntry(e);
|
||||
@ -426,171 +411,5 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
return new ReflectionTemplate(targetClass, res);
|
||||
}
|
||||
|
||||
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
|
||||
protected Enum<?>[] entries;
|
||||
protected Map<Enum<?>, Integer> reverse;
|
||||
|
||||
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||
this.entries = entries;
|
||||
this.reverse = new HashMap<Enum<?>, Integer>();
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
this.reverse.put(entries[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
Integer ord = reverse.get(target);
|
||||
if(ord == null) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
pk.pack((int)ord);
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
int ord = pac.unpackInt();
|
||||
if(entries.length <= ord) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return entries[ord];
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
int ord = from.asInt();
|
||||
if(entries.length <= ord) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return entries[ord];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOrdinalEnumTemplateClass(Class<?> targetClass,
|
||||
Enum<?>[] entires, String directoryName) {
|
||||
throw new UnsupportedOperationException("Not supported by reflection-based template builder");
|
||||
}
|
||||
|
||||
public Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries) {
|
||||
return new ReflectionOrdinalEnumTemplate(entries);
|
||||
}
|
||||
|
||||
static class ReflectionObjectArrayTemplate extends AbstractTemplate {
|
||||
private Class<?> componentClass;
|
||||
private Template elementTemplate;
|
||||
|
||||
public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) {
|
||||
this.componentClass = componentClass;
|
||||
this.elementTemplate = elementTemplate;
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
Object[] array = (Object[])target;
|
||||
int length = array.length;
|
||||
pk.packArray(length);
|
||||
for(int i=0; i < length; i++) {
|
||||
elementTemplate.pack(pk, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException {
|
||||
int length = pac.unpackArray();
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = elementTemplate.unpack(pac, null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
MessagePackObject[] src = from.asArray();
|
||||
int length = src.length;
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = elementTemplate.convert(src[i], null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate {
|
||||
private Class<?> componentClass;
|
||||
private Template componentTemplate;
|
||||
|
||||
public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) {
|
||||
this.componentClass = componentClass;
|
||||
this.componentTemplate = componentTemplate;
|
||||
}
|
||||
|
||||
Class<?> getComponentClass() {
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
Object[] array = (Object[])target;
|
||||
int length = array.length;
|
||||
pk.packArray(length);
|
||||
for(int i=0; i < length; i++) {
|
||||
componentTemplate.pack(pk, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
int length = pac.unpackArray();
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = componentTemplate.unpack(pac, null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
MessagePackObject[] src = from.asArray();
|
||||
int length = src.length;
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = componentTemplate.convert(src[i], null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeArrayTemplateClass(Type arrayType, Type genericBaseType,
|
||||
Class<?> baseClass, int dim, String directoryName) {
|
||||
throw new UnsupportedOperationException("Not supported by reflection-based template builder");
|
||||
}
|
||||
|
||||
public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) {
|
||||
if(dim == 1) {
|
||||
if(baseClass == boolean.class) {
|
||||
return BooleanArrayTemplate.getInstance();
|
||||
} else if(baseClass == short.class) {
|
||||
return ShortArrayTemplate.getInstance();
|
||||
} else if(baseClass == int.class) {
|
||||
return IntArrayTemplate.getInstance();
|
||||
} else if(baseClass == long.class) {
|
||||
return LongArrayTemplate.getInstance();
|
||||
} else if(baseClass == float.class) {
|
||||
return FloatArrayTemplate.getInstance();
|
||||
} else if(baseClass == double.class) {
|
||||
return DoubleArrayTemplate.getInstance();
|
||||
} else {
|
||||
Template baseTemplate = TemplateRegistry.lookup(genericBaseType);
|
||||
return new ReflectionObjectArrayTemplate(baseClass, baseTemplate);
|
||||
}
|
||||
} else if(dim == 2) {
|
||||
Class<?> componentClass = Array.newInstance(baseClass, 0).getClass();
|
||||
Template componentTemplate = buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1);
|
||||
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
} else {
|
||||
ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate)
|
||||
buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1);
|
||||
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
|
||||
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,32 +26,54 @@ import java.lang.annotation.Annotation;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.MessagePackDelegate;
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
import org.msgpack.Template;
|
||||
|
||||
public class TemplateRegistry {
|
||||
private static Map<Type, Template> map;
|
||||
private static Map<Type, GenericTemplate> genericMap;
|
||||
|
||||
private static BuilderSelectorRegistry builderSelectorRegistry;
|
||||
|
||||
static {
|
||||
map = new HashMap<Type, Template>();
|
||||
genericMap = new HashMap<Type, GenericTemplate>();
|
||||
BuiltInTemplateLoader.load();
|
||||
builderSelectorRegistry = BuilderSelectorRegistry.getInstance();
|
||||
}
|
||||
|
||||
public static void register(Class<?> target) { // auto-detect
|
||||
if(target.isEnum()) {
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if(builder != null){
|
||||
register(target,builder.buildTemplate(target));
|
||||
}else{
|
||||
register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target));
|
||||
}
|
||||
/*if(target.isEnum()) {
|
||||
register(target, TemplateBuilder.buildOrdinalEnum(target));
|
||||
} else {
|
||||
register(target, TemplateBuilder.build(target));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, FieldOption implicitOption) {
|
||||
register(target, TemplateBuilder.build(target, implicitOption));
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if(builder != null && builder instanceof CustomTemplateBuilder){
|
||||
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption));
|
||||
}else{
|
||||
throw new TemplateBuildException("cannot build template with filed option");
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, FieldList flist) throws NoSuchFieldException {
|
||||
register(target, TemplateBuilder.build(target, flist));
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if(builder != null && builder instanceof CustomTemplateBuilder){
|
||||
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist));
|
||||
}else{
|
||||
throw new TemplateBuildException("cannot build template with filed list");
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void register(Type rawType, Template tmpl) {
|
||||
@ -101,7 +123,7 @@ public class TemplateRegistry {
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
if(targetType instanceof GenericArrayType) {
|
||||
/*if(targetType instanceof GenericArrayType) {
|
||||
// GenericArrayType is not a Class<?>
|
||||
tmpl = TemplateBuilder.buildArray(targetType);
|
||||
register(targetType, tmpl);
|
||||
@ -135,8 +157,18 @@ 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);
|
||||
if(tmpl != null) {
|
||||
@ -156,7 +188,7 @@ public class TemplateRegistry {
|
||||
}
|
||||
|
||||
if(forceBuild) {
|
||||
tmpl = TemplateBuilder.build(target);
|
||||
tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target);
|
||||
register(target, tmpl);
|
||||
return tmpl;
|
||||
}
|
||||
@ -204,8 +236,5 @@ public class TemplateRegistry {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
public static void setTemplateBuilder(TemplateBuilder builder) {
|
||||
TemplateBuilder.setInstance(builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,190 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.msgpack.AbstractTemplate;
|
||||
import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.template.BooleanArrayTemplate;
|
||||
import org.msgpack.template.DoubleArrayTemplate;
|
||||
import org.msgpack.template.FloatArrayTemplate;
|
||||
import org.msgpack.template.IFieldEntry;
|
||||
import org.msgpack.template.IFieldEntryReader;
|
||||
import org.msgpack.template.IntArrayTemplate;
|
||||
import org.msgpack.template.LongArrayTemplate;
|
||||
import org.msgpack.template.ShortArrayTemplate;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
public class ArrayTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
|
||||
|
||||
|
||||
static class ReflectionObjectArrayTemplate extends AbstractTemplate {
|
||||
private Class<?> componentClass;
|
||||
private Template elementTemplate;
|
||||
|
||||
public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) {
|
||||
this.componentClass = componentClass;
|
||||
this.elementTemplate = elementTemplate;
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
Object[] array = (Object[])target;
|
||||
int length = array.length;
|
||||
pk.packArray(length);
|
||||
for(int i=0; i < length; i++) {
|
||||
elementTemplate.pack(pk, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException {
|
||||
int length = pac.unpackArray();
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = elementTemplate.unpack(pac, null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
MessagePackObject[] src = from.asArray();
|
||||
int length = src.length;
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = elementTemplate.convert(src[i], null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate {
|
||||
private Class<?> componentClass;
|
||||
private Template componentTemplate;
|
||||
|
||||
public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) {
|
||||
this.componentClass = componentClass;
|
||||
this.componentTemplate = componentTemplate;
|
||||
}
|
||||
|
||||
Class<?> getComponentClass() {
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
Object[] array = (Object[])target;
|
||||
int length = array.length;
|
||||
pk.packArray(length);
|
||||
for(int i=0; i < length; i++) {
|
||||
componentTemplate.pack(pk, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
int length = pac.unpackArray();
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = componentTemplate.unpack(pac, null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
MessagePackObject[] src = from.asArray();
|
||||
int length = src.length;
|
||||
Object[] array = (Object[])Array.newInstance(componentClass, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
array[i] = componentTemplate.convert(src[i], null);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Template buildTemplate(Type arrayType) {
|
||||
Type baseType;
|
||||
Class<?> baseClass;
|
||||
int dim = 1;
|
||||
if(arrayType instanceof GenericArrayType) {
|
||||
GenericArrayType type = (GenericArrayType)arrayType;
|
||||
baseType = type.getGenericComponentType();
|
||||
while(baseType instanceof GenericArrayType) {
|
||||
baseType = ((GenericArrayType)baseType).getGenericComponentType();
|
||||
dim += 1;
|
||||
}
|
||||
if(baseType instanceof ParameterizedType) {
|
||||
baseClass = (Class<?>)((ParameterizedType)baseType).getRawType();
|
||||
} else {
|
||||
baseClass = (Class<?>)baseType;
|
||||
}
|
||||
} else {
|
||||
Class<?> type = (Class<?>)arrayType;
|
||||
baseClass = type.getComponentType();
|
||||
while(baseClass.isArray()) {
|
||||
baseClass = baseClass.getComponentType();
|
||||
dim += 1;
|
||||
}
|
||||
baseType = baseClass;
|
||||
}
|
||||
return toTemplate(arrayType, baseType, baseClass, dim);
|
||||
|
||||
}
|
||||
private Template toTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) {
|
||||
if(dim == 1) {
|
||||
if(baseClass == boolean.class) {
|
||||
return BooleanArrayTemplate.getInstance();
|
||||
} else if(baseClass == short.class) {
|
||||
return ShortArrayTemplate.getInstance();
|
||||
} else if(baseClass == int.class) {
|
||||
return IntArrayTemplate.getInstance();
|
||||
} else if(baseClass == long.class) {
|
||||
return LongArrayTemplate.getInstance();
|
||||
} else if(baseClass == float.class) {
|
||||
return FloatArrayTemplate.getInstance();
|
||||
} else if(baseClass == double.class) {
|
||||
return DoubleArrayTemplate.getInstance();
|
||||
} else {
|
||||
Template baseTemplate = TemplateRegistry.lookup(genericBaseType);
|
||||
return new ReflectionObjectArrayTemplate(baseClass, baseTemplate);
|
||||
}
|
||||
} else if(dim == 2) {
|
||||
Class<?> componentClass = Array.newInstance(baseClass, 0).getClass();
|
||||
Template componentTemplate = toTemplate(arrayType, genericBaseType, baseClass, dim-1);
|
||||
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
} else {
|
||||
ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate)
|
||||
toTemplate(arrayType, genericBaseType, baseClass, dim-1);
|
||||
Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass();
|
||||
return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.msgpack.Template;
|
||||
|
||||
public class ArrayTemplateBuilderSelector implements BuilderSelector {
|
||||
|
||||
public static final String NAME = "ArrayTemplateBuilder";
|
||||
|
||||
@Override
|
||||
public String getName(){
|
||||
return NAME;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matchType(Type targetType) {
|
||||
if(targetType instanceof GenericArrayType){
|
||||
return true;
|
||||
}
|
||||
Class<?> targetClass = (Class<?>)targetType;
|
||||
return targetClass.isArray();
|
||||
}
|
||||
|
||||
ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder();
|
||||
|
||||
@Override
|
||||
public TemplateBuilder getTemplateBuilder(Type target) {
|
||||
return templateBuilder;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Match condition for TemplateBuilder.
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public interface BuilderSelector {
|
||||
|
||||
|
||||
/**
|
||||
* Name of this.
|
||||
* @return
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
|
||||
public abstract boolean matchType(Type targetType);
|
||||
|
||||
|
||||
public abstract TemplateBuilder getTemplateBuilder(Type targetType);
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,230 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.msgpack.template.BeansFieldEntryReader;
|
||||
import org.msgpack.template.BeansReflectionTemplateBuilder;
|
||||
import org.msgpack.template.JavassistTemplateBuilder;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder;
|
||||
import org.msgpack.template.javassist.BeansBuildContext;
|
||||
import org.msgpack.template.javassist.BuildContext;
|
||||
import org.msgpack.template.javassist.BuildContextBase;
|
||||
import org.msgpack.template.javassist.BuildContextFactory;
|
||||
|
||||
/**
|
||||
* Registry for BuilderSelectors.
|
||||
* You can modify BuilderSelector chain throw this class.
|
||||
*
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public class BuilderSelectorRegistry {
|
||||
|
||||
private static BuilderSelectorRegistry instance = new BuilderSelectorRegistry();
|
||||
static{
|
||||
initForJava();
|
||||
}
|
||||
|
||||
public static BuilderSelectorRegistry getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
TemplateBuilder forceBuilder;
|
||||
|
||||
|
||||
List<BuilderSelector> builderSelectors = new LinkedList<BuilderSelector>();
|
||||
|
||||
private BuilderSelectorRegistry(){
|
||||
}
|
||||
/**
|
||||
* initialize BuilderSelectors for basic java enviroment.
|
||||
*/
|
||||
private static void initForJava(){
|
||||
|
||||
instance.append(new ArrayTemplateBuilderSelector());
|
||||
|
||||
if(isSupportJavassist()){
|
||||
instance.append(
|
||||
new MessagePackMessageBuilderSelector(
|
||||
new JavassistTemplateBuilder()));
|
||||
instance.forceBuilder = new JavassistTemplateBuilder();
|
||||
|
||||
//Java beans
|
||||
instance.append(new MessagePackBeansBuilderSelector(
|
||||
new JavassistTemplateBuilder(
|
||||
new BeansFieldEntryReader(),
|
||||
new BuildContextFactory() {
|
||||
@Override
|
||||
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) {
|
||||
return new BeansBuildContext(builder);
|
||||
}
|
||||
}
|
||||
)));
|
||||
}else{
|
||||
instance.append(
|
||||
new MessagePackMessageBuilderSelector(
|
||||
new ReflectionTemplateBuilder()));
|
||||
instance.forceBuilder = new ReflectionTemplateBuilder();
|
||||
|
||||
//Java beans
|
||||
instance.append(new MessagePackBeansBuilderSelector(
|
||||
new BeansReflectionTemplateBuilder()));
|
||||
}
|
||||
|
||||
instance.append(new MessagePackOrdinalEnumBuilderSelector());
|
||||
instance.append(new EnumBuilderSelector());
|
||||
}
|
||||
public static boolean isSupportJavassist(){
|
||||
try {
|
||||
return System.getProperty("java.vm.name").equals("Dalvik");
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether same name BuilderSelector is registered.
|
||||
* @param builderSelectorName
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(String builderSelectorName){
|
||||
for(BuilderSelector bs : builderSelectors){
|
||||
if(bs.getName().equals(builderSelectorName)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Append BuilderSelector to tail
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void append(BuilderSelector builderSelector){
|
||||
|
||||
if(contains(builderSelector.getName())){
|
||||
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
|
||||
}
|
||||
this.builderSelectors.add(builderSelector);
|
||||
}
|
||||
/**
|
||||
* Insert BuiderSelector to head
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void prepend(BuilderSelector builderSelector){
|
||||
if(contains(builderSelector.getName())){
|
||||
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
|
||||
}
|
||||
if(builderSelectors.size() > 0){
|
||||
this.builderSelectors.add(0, builderSelector);
|
||||
}else{
|
||||
this.builderSelectors.add(builderSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert BuilderSelector
|
||||
* @param index
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void insert(int index,BuilderSelector builderSelector){
|
||||
if(contains(builderSelector.getName())){
|
||||
throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName());
|
||||
}
|
||||
if(builderSelectors.size() > 0){
|
||||
this.builderSelectors.add(index, builderSelector);
|
||||
|
||||
}else{
|
||||
this.builderSelectors.add(builderSelector);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Replace same name BuilderSelector
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void replace(BuilderSelector builderSelector){
|
||||
String name = builderSelector.getName();
|
||||
int index = getIndex(name);
|
||||
builderSelectors.add(index, builderSelector);
|
||||
builderSelectors.remove(index + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the BuilderSelector before BuilderSelector named "builderSelectorName".
|
||||
* @param builderSelectorName
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void insertBefore(String builderSelectorName,BuilderSelector builderSelector){
|
||||
int index = getIndex(builderSelectorName);
|
||||
|
||||
builderSelectors.add(index,builderSelector);
|
||||
}
|
||||
/**
|
||||
* Insert the BuilderSelector after BuilderSelector named "builderSelectorName".
|
||||
* @param builderSelectorName
|
||||
* @param builderSelector
|
||||
*/
|
||||
public void insertAfter(String builderSelectorName,BuilderSelector builderSelector){
|
||||
int index = getIndex(builderSelectorName);
|
||||
if(index + 1 == builderSelectors.size()){
|
||||
builderSelectors.add(builderSelector);
|
||||
}else{
|
||||
builderSelectors.add(index + 1 , builderSelector);
|
||||
}
|
||||
}
|
||||
private int getIndex(String builderSelectorName){
|
||||
int index = 0;
|
||||
for(BuilderSelector bs : builderSelectors){
|
||||
if(bs.getName().equals(builderSelectorName)){
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if(index >= builderSelectors.size()){
|
||||
throw new RuntimeException(
|
||||
String.format("BuilderSelector named %s does not exist",builderSelectorName));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
public TemplateBuilder select(Type target){
|
||||
for(BuilderSelector selector : builderSelectors){
|
||||
if(selector.matchType(target)){
|
||||
return selector.getTemplateBuilder(target);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TemplateBuilder getForceBuilder() {
|
||||
return forceBuilder;
|
||||
}
|
||||
|
||||
|
||||
public void setForceBuilder(TemplateBuilder forceBuilder) {
|
||||
this.forceBuilder = forceBuilder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.template.FieldList;
|
||||
import org.msgpack.template.FieldOption;
|
||||
import org.msgpack.template.IFieldEntry;
|
||||
import org.msgpack.template.IFieldEntryReader;
|
||||
import org.msgpack.template.TemplateBuildException;
|
||||
import org.msgpack.template.javassist.BuildContextFactory;
|
||||
|
||||
public abstract class CustomTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
|
||||
public abstract IFieldEntryReader getFieldEntryReader();
|
||||
|
||||
|
||||
public abstract Template buildTemplate(Class<?> targetClass , IFieldEntry[] entries);
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass ,FieldOption implicitOption ){
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass,
|
||||
getFieldEntryReader().readFieldEntries(targetClass, implicitOption));
|
||||
}
|
||||
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Template buildTemplate(Type targetType) {
|
||||
Class<?> targetClass = (Class<?>)targetType;
|
||||
IFieldEntryReader reader = getFieldEntryReader();
|
||||
FieldOption implicitOption = reader.readImplicitFieldOption(targetClass);
|
||||
checkValidation(targetClass);
|
||||
|
||||
IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption);
|
||||
|
||||
return buildTemplate(targetClass,entries);
|
||||
}
|
||||
private void checkValidation(Class<?> targetClass) {
|
||||
if(targetClass.isInterface()) {
|
||||
throw new TemplateBuildException("cannot build template of interface");
|
||||
}
|
||||
if(targetClass.isArray()) {
|
||||
throw new TemplateBuildException("cannot build template of array class");
|
||||
}
|
||||
if(targetClass.isPrimitive()) {
|
||||
throw new TemplateBuildException("cannot build template of primitive type");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class EnumBuilderSelector implements BuilderSelector {
|
||||
|
||||
public static final String NAME = "EnumTemplateBuilder";
|
||||
|
||||
public String getName(){
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchType(Type targetType) {
|
||||
return ((Class<?>)targetType).isEnum();
|
||||
}
|
||||
|
||||
|
||||
OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder();
|
||||
|
||||
@Override
|
||||
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.msgpack.annotation.MessagePackBeans;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
|
||||
public class MessagePackBeansBuilderSelector implements BuilderSelector{
|
||||
|
||||
public static final String NAME = "MessagePackBeansTemplateBuilder";
|
||||
|
||||
|
||||
TemplateBuilder builder;
|
||||
public MessagePackBeansBuilderSelector(TemplateBuilder builder){
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
|
||||
public String getName(){
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchType(Type targetType) {
|
||||
Class<?> target = (Class<?>)targetType;
|
||||
return isAnnotated(target, MessagePackBeans.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
|
||||
public class MessagePackMessageBuilderSelector implements BuilderSelector{
|
||||
|
||||
public static final String NAME = "MessagePackMessageTemplateBuilder";
|
||||
|
||||
|
||||
TemplateBuilder builder;
|
||||
public MessagePackMessageBuilderSelector(TemplateBuilder builder){
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchType(Type targetType) {
|
||||
Class<?> target = (Class<?>)targetType;
|
||||
return isAnnotated(target, MessagePackMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
|
||||
public class MessagePackOrdinalEnumBuilderSelector implements BuilderSelector {
|
||||
|
||||
public static final String NAME = "MessagePackOrdinalEnumBuilderTemplate";
|
||||
|
||||
public String getName(){
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchType(Type targetType) {
|
||||
Class<?> target = (Class<?>)targetType;
|
||||
return isAnnotated(target, MessagePackOrdinalEnum.class);
|
||||
}
|
||||
|
||||
OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder();
|
||||
|
||||
@Override
|
||||
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.msgpack.AbstractTemplate;
|
||||
import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.template.TemplateBuildException;
|
||||
|
||||
public class OrdinalEnumTemplateBuilder extends TemplateBuilder{
|
||||
|
||||
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
|
||||
protected Enum<?>[] entries;
|
||||
protected Map<Enum<?>, Integer> reverse;
|
||||
|
||||
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||
this.entries = entries;
|
||||
this.reverse = new HashMap<Enum<?>, Integer>();
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
this.reverse.put(entries[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
public void pack(Packer pk, Object target) throws IOException {
|
||||
Integer ord = reverse.get(target);
|
||||
if(ord == null) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
pk.pack((int)ord);
|
||||
}
|
||||
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
int ord = pac.unpackInt();
|
||||
if(entries.length <= ord) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return entries[ord];
|
||||
}
|
||||
|
||||
public Object convert(MessagePackObject from, Object to) throws MessageTypeException {
|
||||
int ord = from.asInt();
|
||||
if(entries.length <= ord) {
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
return entries[ord];
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Template buildTemplate(Type targetType) {
|
||||
Class<?> targetClass = (Class<?>)targetType;
|
||||
checkOrdinalEnumValidation(targetClass);
|
||||
Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants();
|
||||
|
||||
return new ReflectionOrdinalEnumTemplate(entries);
|
||||
}
|
||||
private void checkOrdinalEnumValidation(Class<?> targetClass) {
|
||||
if(!targetClass.isEnum()) {
|
||||
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
@ -25,89 +25,19 @@ import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.annotation.*;
|
||||
import org.msgpack.template.FieldList;
|
||||
import org.msgpack.template.FieldOption;
|
||||
import org.msgpack.template.IFieldEntry;
|
||||
import org.msgpack.template.IFieldEntryReader;
|
||||
import org.msgpack.template.JavassistTemplateBuilder;
|
||||
import org.msgpack.template.ReflectionTemplateBuilder;
|
||||
|
||||
public abstract class TemplateBuilder {
|
||||
public static class FieldEntry {
|
||||
private Field field;
|
||||
private FieldOption option;
|
||||
|
||||
public FieldEntry() {
|
||||
this.field = null;
|
||||
this.option = FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
public FieldEntry(FieldEntry e) {
|
||||
this.field = e.field;
|
||||
this.option = e.option;
|
||||
}
|
||||
|
||||
public FieldEntry(Field field, FieldOption option) {
|
||||
this.field = field;
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
public String getJavaTypeName() {
|
||||
Class<?> type = field.getType();
|
||||
if(type.isArray()) {
|
||||
return arrayTypeToString(type);
|
||||
} else {
|
||||
return type.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public Type getGenericType() {
|
||||
return field.getGenericType();
|
||||
}
|
||||
|
||||
public FieldOption getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return option != FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return option == FieldOption.REQUIRED;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return option == FieldOption.OPTIONAL;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return option == FieldOption.NULLABLE;
|
||||
}
|
||||
|
||||
static String arrayTypeToString(Class<?> type) {
|
||||
int dim = 1;
|
||||
Class<?> baseType = type.getComponentType();
|
||||
while(baseType.isArray()) {
|
||||
baseType = baseType.getComponentType();
|
||||
dim += 1;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseType.getName());
|
||||
for (int i = 0; i < dim; ++i) {
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Template buildTemplate(Type targetType);
|
||||
/*
|
||||
// Override this method
|
||||
<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java
|
||||
public abstract Class<?> loadTemplateClass(Class<?> targetClass);
|
||||
|
||||
// Override this method
|
||||
@ -118,6 +48,9 @@ public abstract class TemplateBuilder {
|
||||
|
||||
// Override this method
|
||||
public abstract Template buildTemplate(Class<?> targetClass, FieldEntry[] entries);
|
||||
=======
|
||||
public abstract Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries);
|
||||
>>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java
|
||||
|
||||
// Override this method
|
||||
public abstract void writeOrdinalEnumTemplateClass(Class<?> targetClass, Enum<?>[] entires, String directoryName);
|
||||
@ -131,6 +64,7 @@ public abstract class TemplateBuilder {
|
||||
|
||||
// Override this method
|
||||
public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim);
|
||||
<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java
|
||||
|
||||
public Template initializeTemplate(Class<?> targetClass, Class<?> tmplClass) {
|
||||
return initializeTemplate(targetClass, tmplClass, readFieldEntries(targetClass, readImplicitFieldOption(targetClass)));
|
||||
@ -140,10 +74,14 @@ public abstract class TemplateBuilder {
|
||||
checkValidation(targetClass);
|
||||
writeTemplateClass(targetClass, convertFieldEntries(targetClass, fList), directoryName);
|
||||
}
|
||||
=======
|
||||
|
||||
public abstract IFieldEntryReader getFieldEntryReader();
|
||||
>>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass, convertFieldEntries(targetClass, flist));
|
||||
return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist));
|
||||
}
|
||||
|
||||
public void writeTemplateClass(Class<?> targetClass, FieldOption implicitOption, String directoryName) {
|
||||
@ -153,7 +91,7 @@ public abstract class TemplateBuilder {
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) {
|
||||
checkValidation(targetClass);
|
||||
return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption));
|
||||
return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption));
|
||||
}
|
||||
|
||||
public void writeTemplateClass(Class<?> targetClass, final String directoryName) {
|
||||
@ -162,7 +100,7 @@ public abstract class TemplateBuilder {
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass) {
|
||||
FieldOption implicitOption = readImplicitFieldOption(targetClass);
|
||||
FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass);
|
||||
return buildTemplate(targetClass, implicitOption);
|
||||
}
|
||||
|
||||
@ -217,6 +155,22 @@ public abstract class TemplateBuilder {
|
||||
return ((Class<?>)arrayType).getComponentType();
|
||||
}
|
||||
}
|
||||
private void checkValidation(Class<?> targetClass) {
|
||||
if(targetClass.isInterface()) {
|
||||
throw new TemplateBuildException("cannot build template of interface");
|
||||
}
|
||||
if(targetClass.isArray()) {
|
||||
throw new TemplateBuildException("cannot build template of array class");
|
||||
}
|
||||
if(targetClass.isPrimitive()) {
|
||||
throw new TemplateBuildException("cannot build template of primitive type");
|
||||
}
|
||||
}
|
||||
private void checkOrdinalEnumValidation(Class<?> targetClass) {
|
||||
if(!targetClass.isEnum()) {
|
||||
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static TemplateBuilder instance;
|
||||
@ -235,7 +189,7 @@ public abstract class TemplateBuilder {
|
||||
return JavassistTemplateBuilder.getInstance();
|
||||
}
|
||||
|
||||
synchronized static void setInstance(TemplateBuilder builder) {
|
||||
public synchronized static void setInstance(TemplateBuilder builder) {
|
||||
instance = builder;
|
||||
}
|
||||
|
||||
@ -286,9 +240,9 @@ public abstract class TemplateBuilder {
|
||||
|
||||
public static Template buildArray(Type arrayType) {
|
||||
return instance.buildArrayTemplate(arrayType);
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
/*
|
||||
private static void checkValidation(Class<?> targetClass) {
|
||||
if(targetClass.isInterface()) {
|
||||
throw new TemplateBuildException("cannot build template of interface");
|
||||
@ -305,10 +259,10 @@ public abstract class TemplateBuilder {
|
||||
if(!targetClass.isEnum()) {
|
||||
throw new TemplateBuildException("tried to build ordinal enum template of non-enum class");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
static FieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
/*
|
||||
static IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||
List<FieldList.Entry> src = flist.getList();
|
||||
FieldEntry[] result = new FieldEntry[src.size()];
|
||||
for(int i=0; i < src.size(); i++) {
|
||||
@ -320,9 +274,9 @@ public abstract class TemplateBuilder {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}*/
|
||||
|
||||
static FieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) {
|
||||
/*static IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) {
|
||||
Field[] allFields = readAllFields(targetClass);
|
||||
|
||||
/* index:
|
||||
@ -332,7 +286,7 @@ public abstract class TemplateBuilder {
|
||||
* int field_d; // 4
|
||||
* @Index(2) int field_e; // 2
|
||||
* int field_f; // 5
|
||||
*/
|
||||
*//*
|
||||
List<FieldEntry> indexed = new ArrayList<FieldEntry>();
|
||||
int maxIndex = -1;
|
||||
for(Field f : allFields) {
|
||||
@ -372,8 +326,8 @@ public abstract class TemplateBuilder {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}*/
|
||||
/*
|
||||
private static Field[] readAllFields(Class<?> targetClass) {
|
||||
// order: [fields of super class, ..., fields of this class]
|
||||
List<Field[]> succ = new ArrayList<Field[]>();
|
||||
@ -449,6 +403,6 @@ public abstract class TemplateBuilder {
|
||||
|
||||
private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) {
|
||||
return ao.getAnnotation(with) != null;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -0,0 +1,289 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.Thread;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.*;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.ClassClassPath;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
|
||||
public class BeansBuildContext extends BuildContextBase<BeansFieldEntry> {
|
||||
protected BeansFieldEntry[] entries;
|
||||
protected Class<?> origClass;
|
||||
protected String origName;
|
||||
protected Template[] templates;
|
||||
protected int minimumArrayLength;
|
||||
|
||||
public BeansBuildContext(JavassistTemplateBuilder director) {
|
||||
super(director);
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, BeansFieldEntry[] entries, Template[] templates) {
|
||||
this.entries = entries;
|
||||
this.templates = templates;
|
||||
this.origClass = targetClass;
|
||||
this.origName = this.origClass.getName();
|
||||
return build(this.origName);
|
||||
}
|
||||
|
||||
protected void setSuperClass() throws CannotCompileException, NotFoundException {
|
||||
this.tmplCtClass.setSuperclass(
|
||||
director.getCtClass(JavassistTemplate.class.getName()));
|
||||
}
|
||||
|
||||
protected void buildConstructor() throws CannotCompileException, NotFoundException {
|
||||
// Constructor(Class targetClass, Template[] templates)
|
||||
CtConstructor newCtCons = CtNewConstructor.make(
|
||||
new CtClass[] {
|
||||
director.getCtClass(Class.class.getName()),
|
||||
director.getCtClass(Template.class.getName()+"[]")
|
||||
},
|
||||
new CtClass[0],
|
||||
this.tmplCtClass);
|
||||
this.tmplCtClass.addConstructor(newCtCons);
|
||||
}
|
||||
|
||||
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
Constructor<?> cons = c.getConstructor(new Class[] {
|
||||
Class.class,
|
||||
Template[].class
|
||||
});
|
||||
Object tmpl = cons.newInstance(new Object[] {
|
||||
this.origClass,
|
||||
this.templates
|
||||
});
|
||||
return (Template)tmpl;
|
||||
}
|
||||
|
||||
protected void buildMethodInit() {
|
||||
this.minimumArrayLength = 0;
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(e.isRequired() || e.isNullable()) {
|
||||
this.minimumArrayLength = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String buildPackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{");
|
||||
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
|
||||
buildString("$1.packArray(%d);", entries.length);
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
BeansFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.packNil();");
|
||||
continue;
|
||||
}
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("$1.%s(_$$_t.%s());", primitivePackName(type), e.getGetterName());
|
||||
} else {
|
||||
buildString("if(_$$_t.%s() == null) {", e.getGetterName());
|
||||
if(!e.isNullable() && !e.isOptional()) {
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else {
|
||||
buildString("$1.packNil();");
|
||||
}
|
||||
buildString("} else {");
|
||||
buildString(" this.templates[%d].pack($1, _$$_t.%s());", i, e.getGetterName());
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildUnpackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("int length = $1.unpackArray();");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
BeansFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s(null);", e.getSetterName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.set%s( $1.%s() );", e.getName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.set%s( (%s)this.templates[%d].unpack($1, _$$_t.get%s()) );", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
BeansFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s( $1.%s() );", e.getSetterName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s( (%s)this.templates[%d].unpack($1, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("for(int i=%d; i < length; i++) {", i);
|
||||
buildString(" $1.unpackObject();");
|
||||
buildString("}");
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildConvertMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
|
||||
buildString("int length = array.length;");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
buildString("%s obj;", MessagePackObject.class.getName());
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
BeansFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s( null );", e.getSetterName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
BeansFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,289 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.Thread;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.*;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.ClassClassPath;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
|
||||
public class BuildContext extends BuildContextBase<FieldEntry> {
|
||||
protected IFieldEntry[] entries;
|
||||
protected Class<?> origClass;
|
||||
protected String origName;
|
||||
protected Template[] templates;
|
||||
protected int minimumArrayLength;
|
||||
|
||||
public BuildContext(JavassistTemplateBuilder director) {
|
||||
super(director);
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) {
|
||||
this.entries = entries;
|
||||
this.templates = templates;
|
||||
this.origClass = targetClass;
|
||||
this.origName = this.origClass.getName();
|
||||
return build(this.origName);
|
||||
}
|
||||
|
||||
protected void setSuperClass() throws CannotCompileException, NotFoundException {
|
||||
this.tmplCtClass.setSuperclass(
|
||||
director.getCtClass(JavassistTemplate.class.getName()));
|
||||
}
|
||||
|
||||
protected void buildConstructor() throws CannotCompileException, NotFoundException {
|
||||
// Constructor(Class targetClass, Template[] templates)
|
||||
CtConstructor newCtCons = CtNewConstructor.make(
|
||||
new CtClass[] {
|
||||
director.getCtClass(Class.class.getName()),
|
||||
director.getCtClass(Template.class.getName()+"[]")
|
||||
},
|
||||
new CtClass[0],
|
||||
this.tmplCtClass);
|
||||
this.tmplCtClass.addConstructor(newCtCons);
|
||||
}
|
||||
|
||||
protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
Constructor<?> cons = c.getConstructor(new Class[] {
|
||||
Class.class,
|
||||
Template[].class
|
||||
});
|
||||
Object tmpl = cons.newInstance(new Object[] {
|
||||
this.origClass,
|
||||
this.templates
|
||||
});
|
||||
return (Template)tmpl;
|
||||
}
|
||||
|
||||
protected void buildMethodInit() {
|
||||
this.minimumArrayLength = 0;
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(e.isRequired() || e.isNullable()) {
|
||||
this.minimumArrayLength = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String buildPackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{");
|
||||
buildString("%s _$$_t = (%s)$2;", this.origName, this.origName);
|
||||
buildString("$1.packArray(%d);", entries.length);
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.packNil();");
|
||||
continue;
|
||||
}
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName());
|
||||
} else {
|
||||
buildString("if(_$$_t.%s == null) {", e.getName());
|
||||
if(!e.isNullable() && !e.isOptional()) {
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else {
|
||||
buildString("$1.packNil();");
|
||||
}
|
||||
buildString("} else {");
|
||||
buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName());
|
||||
buildString("}");
|
||||
}
|
||||
}
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildUnpackMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("int length = $1.unpackArray();");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s = null;", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
buildString("$1.unpackObject();");
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("if($1.tryUnpackNull()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("for(int i=%d; i < length; i++) {", i);
|
||||
buildString(" $1.unpackObject();");
|
||||
buildString("}");
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
protected String buildConvertMethodBody() {
|
||||
resetStringBuilder();
|
||||
buildString("{ ");
|
||||
|
||||
buildString("%s _$$_t;", this.origName);
|
||||
buildString("if($2 == null) {");
|
||||
buildString(" _$$_t = new %s();", this.origName);
|
||||
buildString("} else {");
|
||||
buildString(" _$$_t = (%s)$2;", this.origName);
|
||||
buildString("}");
|
||||
|
||||
buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName());
|
||||
buildString("int length = array.length;");
|
||||
buildString("if(length < %d) {", this.minimumArrayLength);
|
||||
buildString(" throw new %s();", MessageTypeException.class.getName());
|
||||
buildString("}");
|
||||
|
||||
buildString("%s obj;", MessagePackObject.class.getName());
|
||||
|
||||
int i;
|
||||
for(i=0; i < this.minimumArrayLength; i++) {
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
if(e.isRequired()) {
|
||||
// Required + nil => exception
|
||||
buildString("throw new %s();", MessageTypeException.class.getName());
|
||||
} else if(e.isOptional()) {
|
||||
// Optional + nil => keep default value
|
||||
} else { // Nullable
|
||||
// Nullable + nil => set null
|
||||
buildString("_$$_t.%s = null;", e.getName());
|
||||
}
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
for(; i < entries.length; i++) {
|
||||
buildString("if(length <= %d) { return _$$_t; }", i);
|
||||
|
||||
IFieldEntry e = entries[i];
|
||||
if(!e.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buildString("obj = array[%d];", i);
|
||||
buildString("if(obj.isNil()) {");
|
||||
// this is Optional field becaue i >= minimumArrayLength
|
||||
// Optional + nil => keep default value
|
||||
buildString("} else {");
|
||||
Class<?> type = e.getType();
|
||||
if(type.isPrimitive()) {
|
||||
buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type));
|
||||
} else {
|
||||
buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName());
|
||||
}
|
||||
buildString("}");
|
||||
}
|
||||
|
||||
// latter entries are all Optional + nil => keep default value
|
||||
|
||||
buildString("return _$$_t;");
|
||||
|
||||
buildString("}");
|
||||
return getBuiltString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,244 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.Thread;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.*;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.ClassClassPath;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public abstract class BuildContextBase<T extends IFieldEntry> {
|
||||
|
||||
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
|
||||
|
||||
|
||||
protected JavassistTemplateBuilder director;
|
||||
|
||||
protected String tmplName;
|
||||
|
||||
protected CtClass tmplCtClass;
|
||||
|
||||
protected abstract void setSuperClass() throws CannotCompileException, NotFoundException;
|
||||
|
||||
protected abstract void buildConstructor() throws CannotCompileException, NotFoundException;
|
||||
|
||||
protected void buildMethodInit() { }
|
||||
|
||||
protected abstract String buildPackMethodBody();
|
||||
|
||||
protected abstract String buildUnpackMethodBody();
|
||||
|
||||
protected abstract String buildConvertMethodBody();
|
||||
|
||||
protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException;
|
||||
|
||||
public BuildContextBase(JavassistTemplateBuilder director) {
|
||||
this.director = director;
|
||||
}
|
||||
|
||||
|
||||
public abstract Template buildTemplate(Class<?> targetClass, T[] entries, Template[] templates);
|
||||
|
||||
|
||||
protected Template build(final String className) {
|
||||
try {
|
||||
reset(className);
|
||||
buildClass();
|
||||
buildConstructor();
|
||||
buildMethodInit();
|
||||
buildPackMethod();
|
||||
buildUnpackMethod();
|
||||
buildConvertMethod();
|
||||
return buildInstance(createClass());
|
||||
} catch (Exception e) {
|
||||
String code = getBuiltString();
|
||||
if(code != null) {
|
||||
LOG.error("builder: " + code, e);
|
||||
throw new TemplateBuildException("cannot compile: " + code, e);
|
||||
} else {
|
||||
throw new TemplateBuildException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void reset(String className) {
|
||||
tmplName = className + "_$$_Template" + director.nextSeqId();
|
||||
tmplCtClass = director.makeCtClass(tmplName);
|
||||
}
|
||||
|
||||
protected void buildClass() throws CannotCompileException, NotFoundException {
|
||||
setSuperClass();
|
||||
tmplCtClass.addInterface(director.getCtClass(Template.class.getName()));
|
||||
}
|
||||
|
||||
protected void buildPackMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildPackMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = CtClass.voidType;
|
||||
String mname = "pack";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(Packer.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(IOException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected void buildUnpackMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildUnpackMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||
String mname = "unpack";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(Unpacker.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(MessageTypeException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected void buildConvertMethod() throws CannotCompileException, NotFoundException {
|
||||
String mbody = buildConvertMethodBody();
|
||||
int mod = javassist.Modifier.PUBLIC;
|
||||
CtClass returnType = director.getCtClass(Object.class.getName());
|
||||
String mname = "convert";
|
||||
CtClass[] paramTypes = new CtClass[] {
|
||||
director.getCtClass(MessagePackObject.class.getName()),
|
||||
director.getCtClass(Object.class.getName())
|
||||
};
|
||||
CtClass[] exceptTypes = new CtClass[] {
|
||||
director.getCtClass(MessageTypeException.class.getName())
|
||||
};
|
||||
CtMethod newCtMethod = CtNewMethod.make(
|
||||
mod, returnType, mname,
|
||||
paramTypes, exceptTypes, mbody, tmplCtClass);
|
||||
tmplCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
protected Class<?> createClass() throws CannotCompileException {
|
||||
return (Class<?>) tmplCtClass.toClass(null, null);
|
||||
}
|
||||
|
||||
protected StringBuilder stringBuilder = null;
|
||||
|
||||
protected void resetStringBuilder() {
|
||||
stringBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
protected void buildString(String str) {
|
||||
stringBuilder.append(str);
|
||||
}
|
||||
|
||||
protected void buildString(String format, Object... args) {
|
||||
stringBuilder.append(String.format(format, args));
|
||||
}
|
||||
|
||||
protected String getBuiltString() {
|
||||
if(stringBuilder == null) {
|
||||
return null;
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
protected String primitivePackName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "packBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "packByte";
|
||||
} else if(type == short.class) {
|
||||
return "packShort";
|
||||
} else if(type == int.class) {
|
||||
return "packInt";
|
||||
} else if(type == long.class) {
|
||||
return "packLong";
|
||||
} else if(type == float.class) {
|
||||
return "packFloat";
|
||||
} else if(type == double.class) {
|
||||
return "packDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String primitiveUnpackName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "unpackBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "unpackByte";
|
||||
} else if(type == short.class) {
|
||||
return "unpackShort";
|
||||
} else if(type == int.class) {
|
||||
return "unpackInt";
|
||||
} else if(type == long.class) {
|
||||
return "unpackLong";
|
||||
} else if(type == float.class) {
|
||||
return "unpackFloat";
|
||||
} else if(type == double.class) {
|
||||
return "unpackDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String primitiveConvertName(Class<?> type) {
|
||||
if(type == boolean.class) {
|
||||
return "asBoolean";
|
||||
} else if(type == byte.class) {
|
||||
return "asByte";
|
||||
} else if(type == short.class) {
|
||||
return "asShort";
|
||||
} else if(type == int.class) {
|
||||
return "asInt";
|
||||
} else if(type == long.class) {
|
||||
return "asLong";
|
||||
} else if(type == float.class) {
|
||||
return "asFloat";
|
||||
} else if(type == double.class) {
|
||||
return "asDouble";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import org.msgpack.template.JavassistTemplateBuilder;
|
||||
|
||||
public interface BuildContextFactory {
|
||||
|
||||
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder);
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template.javassist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.Thread;
|
||||
|
||||
import org.msgpack.*;
|
||||
import org.msgpack.template.*;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.LoaderClassPath;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.ClassClassPath;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class JavassistTemplate extends AbstractTemplate {
|
||||
public Class<?> targetClass;
|
||||
public Template[] templates;
|
||||
|
||||
public JavassistTemplate(Class<?> targetClass, Template[] templates) {
|
||||
this.targetClass = targetClass;
|
||||
this.templates = templates;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
83
java/src/test/java/org/msgpack/template/BeansEquals.java
Normal file
83
java/src/test/java/org/msgpack/template/BeansEquals.java
Normal file
@ -0,0 +1,83 @@
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.Description;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* This matcher compares all get***() methods(except getClass)
|
||||
* @author takeshita
|
||||
*
|
||||
*/
|
||||
public class BeansEquals extends BaseMatcher<Object>{
|
||||
|
||||
Object expected;
|
||||
|
||||
HashSet<String> ignoreNames = new HashSet<String>();
|
||||
|
||||
public BeansEquals(Object expected){
|
||||
this.expected = expected;
|
||||
}
|
||||
public BeansEquals(Object expected,String[] ignoreNames){
|
||||
this.expected = expected;
|
||||
for(int i = 0;i < ignoreNames.length;i++){
|
||||
this.ignoreNames.add(ignoreNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static String errorMessage = "hoge";
|
||||
|
||||
@Override
|
||||
public boolean matches(Object actual) {
|
||||
if(expected == actual){
|
||||
return true;
|
||||
}
|
||||
if(!actual.getClass().equals(expected.getClass())){
|
||||
errorMessage = String.format("Expected class is %s but actual %s",
|
||||
expected.getClass().getName(),
|
||||
actual.getClass().getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
for(Method m : expected.getClass().getMethods()){
|
||||
String n = m.getName();
|
||||
if(n.startsWith("get") &&
|
||||
!n.equals("getClass") &&
|
||||
!ignoreNames.contains(n)){
|
||||
|
||||
if(m.getParameterTypes().length == 0 &&
|
||||
!m.getReturnType().equals(void.class)){
|
||||
try {
|
||||
Object exp = m.invoke(expected);
|
||||
Object act = m.invoke(actual);
|
||||
|
||||
Assert.assertThat("@" + n,act, CoreMatchers.is(exp));
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Exception occured while comparing %s",n), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void describeTo(Description desc) {
|
||||
|
||||
desc.appendText(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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);
|
||||
|
40
scala/.gitignore
vendored
Normal file
40
scala/.gitignore
vendored
Normal file
@ -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
scala/pom.xml
Normal file
158
scala/pom.xml
Normal file
@ -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>
|
15
scala/src/main/scala/org/msgpack/App.scala
Normal file
15
scala/src/main/scala/org/msgpack/App.scala
Normal file
@ -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
|
||||
|
||||
}
|
76
scala/src/main/scala/org/msgpack/ScalaMessagePack.scala
Normal file
76
scala/src/main/scala/org/msgpack/ScalaMessagePack.scala
Normal file
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
16
scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala
Normal file
16
scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala
Normal file
@ -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 :_*)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
21
scala/src/test/scala/org/msgpack/ClassWithList.scala
Normal file
21
scala/src/test/scala/org/msgpack/ClassWithList.scala
Normal file
@ -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)
|
||||
}
|
19
scala/src/test/scala/org/msgpack/ClassWithMap.scala
Normal file
19
scala/src/test/scala/org/msgpack/ClassWithMap.scala
Normal file
@ -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
|
||||
|
||||
}
|
71
scala/src/test/scala/org/msgpack/CollectionPackSpec.scala
Normal file
71
scala/src/test/scala/org/msgpack/CollectionPackSpec.scala
Normal file
@ -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)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
77
scala/src/test/scala/org/msgpack/SampleClass.scala
Normal file
77
scala/src/test/scala/org/msgpack/SampleClass.scala
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
}
|
120
scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala
Normal file
120
scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala
Normal file
@ -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)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
90
scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala
Normal file
90
scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala
Normal file
@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user