[DIRECTMEMORY-102] Lightning Serializer Contribution
Submitted by Christoph Engelbert.
Patch submitted as provided. some changes later :-)
git-svn-id: https://svn.apache.org/repos/asf/directmemory/lightning/trunk@1392595 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lightning-api/pom.xml b/lightning-api/pom.xml
new file mode 100644
index 0000000..58134d7
--- /dev/null
+++ b/lightning-api/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-api</artifactId>
+ <name>Lightning: API</name>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.carrotsearch</groupId>
+ <artifactId>hppc</artifactId>
+ <version>0.4.1</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/ClassComparisonStrategy.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/ClassComparisonStrategy.java
new file mode 100644
index 0000000..1268095
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/ClassComparisonStrategy.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+/**
+ * Defines the comparison strategy of classes between different serializers. The standard strategy of Java is
+ * SerialVersionUID but Lightning has some lighter algorithm which only takes properties into account.
+ */
+public enum ClassComparisonStrategy
+{
+
+ /**
+ * Default Java Serialization like SerialVersionUID
+ */
+ SerialVersionUID,
+
+ /**
+ * Lightning checksum calculation
+ */
+ LightningChecksum,
+
+ /**
+ * Instructs Lightning to skip all kinds of comparison between the different ClassDefinitionContainers. This is not
+ * recommended but is required for possible schema evolution features.
+ */
+ SkipComparison
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/Marshaller.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/Marshaller.java
new file mode 100644
index 0000000..03a56e8
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/Marshaller.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public interface Marshaller
+{
+
+ boolean acceptType( Class<?> type );
+
+ void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException;
+
+ <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException;
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerContext.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerContext.java
new file mode 100644
index 0000000..39944dc
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerContext.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.lang.reflect.Type;
+
+public interface MarshallerContext
+{
+
+ Marshaller getMarshaller( Type type );
+
+ void bindMarshaller( Type type, Marshaller marshaller );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerStrategy.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerStrategy.java
new file mode 100644
index 0000000..79dfd75
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/MarshallerStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.lang.reflect.Type;
+
+public interface MarshallerStrategy
+{
+
+ Marshaller getMarshaller( Type type, MarshallerContext marshallerContext );
+
+ Marshaller getMarshaller( Type type, MarshallerContext marshallerContext, boolean baseMarshallersOnly );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationContext.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationContext.java
new file mode 100644
index 0000000..8a83e26
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationContext.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.lang.reflect.Type;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+public interface SerializationContext
+{
+
+ ClassDefinitionContainer getClassDefinitionContainer();
+
+ SerializationStrategy getSerializationStrategy();
+
+ ObjectInstantiatorFactory getObjectInstantiatorFactory();
+
+ Marshaller findMarshaller( Type type );
+
+ ValueNullableEvaluator getValueNullableEvaluator();
+
+ long findReferenceIdByObject( Object instance );
+
+ Object findObjectByReferenceId( long referenceId );
+
+ boolean containsReferenceId( long referenceId );
+
+ long putMarshalledInstance( Object instance );
+
+ long putUnmarshalledInstance( long refrenceId, Object instance );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationStrategy.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationStrategy.java
new file mode 100644
index 0000000..6fc9b20
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/SerializationStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+public enum SerializationStrategy
+{
+
+ /**
+ * This strategy does not force same instances to become same instances on deserialization since only values are
+ * written to the stream.<br>
+ * To be clear, deserialized instances of same objects are non identity-equal!
+ */
+ SpeedOptimized,
+
+ /**
+ * This strategy forces same instances to become same instances on deserialization. This needs to collect instances
+ * by hashCode on both sides while serialization and deserialization, which in case needs time.<br>
+ * To be clear, deserialized instances of same objects are identity-equal!
+ */
+ SizeOptimized
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/Serializer.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/Serializer.java
new file mode 100644
index 0000000..0826c3d
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/Serializer.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+
+public interface Serializer
+{
+
+ ClassDefinitionContainer getClassDefinitionContainer();
+
+ void setClassDefinitionContainer( ClassDefinitionContainer classDefinitionContainer );
+
+ <V> void serialize( V value, DataOutput dataOutput );
+
+ <V> void serialize( V value, OutputStream outputStream );
+
+ <V> void serialize( V value, Writer writer );
+
+ <V> void serialize( V value, ByteBuffer buffer );
+
+ <V> V deserialize( DataInput dataInput );
+
+ <V> V deserialize( InputStream inputStream );
+
+ <V> V deserialize( Reader reader );
+
+ <V> V deserialize( ByteBuffer buffer );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/Streamed.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/Streamed.java
new file mode 100644
index 0000000..18ce20f
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/Streamed.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public interface Streamed
+{
+
+ void writeTo( DataOutput dataOutput )
+ throws IOException;
+
+ void readFrom( DataInput dataInput )
+ throws IOException;
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/TypeBindableMarshaller.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/TypeBindableMarshaller.java
new file mode 100644
index 0000000..31a730d
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/TypeBindableMarshaller.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.lang.reflect.Type;
+
+public interface TypeBindableMarshaller
+{
+
+ Marshaller bindType( Type... bindingTypes );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/SerializerDefinition.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/SerializerDefinition.java
new file mode 100644
index 0000000..2e840f5
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/SerializerDefinition.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.configuration;
+
+import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
+import org.apache.directmemory.lightning.generator.DefinitionVisitor;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+
+public interface SerializerDefinition
+{
+
+ void configure( DefinitionBuildingContext definitionBuildingContext, ObjectInstantiatorFactory instantiator );
+
+ void acceptVisitor( DefinitionVisitor visitor );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/TypeIntrospector.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/TypeIntrospector.java
new file mode 100644
index 0000000..389964d
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/configuration/TypeIntrospector.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.configuration;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public interface TypeIntrospector
+{
+
+ List<PropertyDescriptor> introspect( Type type, MarshallerStrategy marshallerStrategy,
+ MarshallerContext marshallerContext,
+ PropertyDescriptorFactory propertyDescriptorFactory );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/ClassDefinitionInconsistentException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/ClassDefinitionInconsistentException.java
new file mode 100644
index 0000000..f9a7970
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/ClassDefinitionInconsistentException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class ClassDefinitionInconsistentException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = -1585228404035281265L;
+
+ public ClassDefinitionInconsistentException()
+ {
+ super();
+ }
+
+ public ClassDefinitionInconsistentException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public ClassDefinitionInconsistentException( String message )
+ {
+ super( message );
+ }
+
+ public ClassDefinitionInconsistentException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalAccessorException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalAccessorException.java
new file mode 100644
index 0000000..b1202d4
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalAccessorException.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class IllegalAccessorException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = 4787626329337667393L;
+
+ public IllegalAccessorException()
+ {
+ super();
+ }
+
+ public IllegalAccessorException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public IllegalAccessorException( String message )
+ {
+ super( message );
+ }
+
+ public IllegalAccessorException( Throwable cause )
+ {
+ super( cause );
+ }
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalPropertyAccessException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalPropertyAccessException.java
new file mode 100644
index 0000000..2590bec
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/IllegalPropertyAccessException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class IllegalPropertyAccessException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = 967346776852344538L;
+
+ public IllegalPropertyAccessException()
+ {
+ super();
+ }
+
+ public IllegalPropertyAccessException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public IllegalPropertyAccessException( String message )
+ {
+ super( message );
+ }
+
+ public IllegalPropertyAccessException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerDefinitionException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerDefinitionException.java
new file mode 100644
index 0000000..1c057f3
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerDefinitionException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class SerializerDefinitionException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = -5334852575035142159L;
+
+ public SerializerDefinitionException()
+ {
+ super();
+ }
+
+ public SerializerDefinitionException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public SerializerDefinitionException( String message )
+ {
+ super( message );
+ }
+
+ public SerializerDefinitionException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerExecutionException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerExecutionException.java
new file mode 100644
index 0000000..4988cdf
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerExecutionException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class SerializerExecutionException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = 6304044942065057900L;
+
+ public SerializerExecutionException()
+ {
+ super();
+ }
+
+ public SerializerExecutionException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public SerializerExecutionException( String message )
+ {
+ super( message );
+ }
+
+ public SerializerExecutionException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerMarshallerGeneratorException.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerMarshallerGeneratorException.java
new file mode 100644
index 0000000..e95c42e
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/exceptions/SerializerMarshallerGeneratorException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.exceptions;
+
+public class SerializerMarshallerGeneratorException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = 3794029259705664064L;
+
+ public SerializerMarshallerGeneratorException()
+ {
+ super();
+ }
+
+ public SerializerMarshallerGeneratorException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public SerializerMarshallerGeneratorException( String message )
+ {
+ super( message );
+ }
+
+ public SerializerMarshallerGeneratorException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionBuildingContext.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionBuildingContext.java
new file mode 100644
index 0000000..52f049f
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionBuildingContext.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.generator;
+
+import org.apache.directmemory.lightning.MarshallerStrategy;
+
+public interface DefinitionBuildingContext
+{
+
+ PropertyDescriptorFactory getPropertyDescriptorFactory();
+
+ MarshallerStrategy getMarshallerStrategy();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionVisitor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionVisitor.java
new file mode 100644
index 0000000..55ffcb4
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/DefinitionVisitor.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.generator;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public interface DefinitionVisitor
+{
+
+ void visitSerializerDefinition( SerializerDefinition serializerDefinition );
+
+ void visitAttributeAnnotation( Class<? extends Annotation> attributeAnnotation );
+
+ void visitClassDefine( Type type, Marshaller marshaller );
+
+ void visitAnnotatedAttribute( PropertyDescriptor propertyDescriptor, Marshaller marshaller );
+
+ void visitPropertyDescriptor( PropertyDescriptor propertyDescriptor, Marshaller marshaller );
+
+ void visitFinalizeSerializerDefinition( SerializerDefinition serializerDefinition );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/PropertyDescriptorFactory.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/PropertyDescriptorFactory.java
new file mode 100644
index 0000000..335b574
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/generator/PropertyDescriptorFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.generator;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public interface PropertyDescriptorFactory
+{
+
+ PropertyDescriptor byMethod( Method method, Marshaller marshaller, Class<?> definedClass );
+
+ PropertyDescriptor byField( Field field, Marshaller marshaller, Class<?> definedClass );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiator.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiator.java
new file mode 100644
index 0000000..a922ba3
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiator.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.instantiator;
+
+/**
+ * Instantiates a new object.
+ *
+ * @author Leonardo Mesquita
+ */
+public interface ObjectInstantiator
+{
+
+ /**
+ * Returns a new instance of an object. The returned object's class is defined by the implementation.
+ *
+ * @return A new instance of an object.
+ */
+ Object newInstance();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiatorFactory.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiatorFactory.java
new file mode 100644
index 0000000..3f64694
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/instantiator/ObjectInstantiatorFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.instantiator;
+
+/**
+ * Common interface to all kind of Objenesis objects
+ *
+ * @author Henri Tremblay
+ */
+public interface ObjectInstantiatorFactory
+{
+
+ /**
+ * Will create a new object without any constructor being called
+ *
+ * @param clazz Class to instantiate
+ * @return New instance of clazz
+ */
+ Object newInstance( Class<?> clazz );
+
+ /**
+ * Will pick the best instantiator for the provided class. If you need to create a lot of instances from the same
+ * class, it is way more efficient to create them from the same ObjectInstantiator than calling
+ * {@link #newInstance(Class)}.
+ *
+ * @param clazz Class to instantiate
+ * @return Instantiator dedicated to the class
+ */
+ ObjectInstantiator getInstantiatorOf( Class<?> clazz );
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerInputStream.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerInputStream.java
new file mode 100644
index 0000000..35e0133
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerInputStream.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.io;
+
+import java.io.DataInput;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.PushbackInputStream;
+import java.io.UTFDataFormatException;
+
+import org.apache.directmemory.lightning.Serializer;
+
+/**
+ * Parts of this class taken from Hazelcast project
+ */
+public class SerializerInputStream
+ extends FilterInputStream
+ implements ObjectInput
+{
+
+ private final Serializer serializer;
+
+ private final byte[] longReadBuffer = new byte[8];
+
+ private char lineBuffer[];
+
+ public SerializerInputStream( InputStream in, Serializer serializer )
+ {
+ super( in );
+ this.serializer = serializer;
+ }
+
+ @Override
+ public Object readObject()
+ {
+ return serializer.deserialize( (DataInput) this );
+ }
+
+ @Override
+ public void readFully( byte[] b )
+ throws IOException
+ {
+ in.read( b );
+ }
+
+ @Override
+ public void readFully( byte[] b, int off, int len )
+ throws IOException
+ {
+ in.read( b, off, len );
+ }
+
+ @Override
+ public int skipBytes( int n )
+ throws IOException
+ {
+ return (int) in.skip( n );
+ }
+
+ @Override
+ public boolean readBoolean()
+ throws IOException
+ {
+ return in.read() == 1;
+ }
+
+ @Override
+ public byte readByte()
+ throws IOException
+ {
+ return (byte) in.read();
+ }
+
+ @Override
+ public int readUnsignedByte()
+ throws IOException
+ {
+ return in.read();
+ }
+
+ @Override
+ public short readShort()
+ throws IOException
+ {
+ int byte1 = read();
+ int byte2 = read();
+ return (short) ( ( byte1 << 8 ) + ( byte2 << 0 ) );
+ }
+
+ @Override
+ public int readUnsignedShort()
+ throws IOException
+ {
+ int byte1 = read();
+ int byte2 = read();
+ return (short) ( ( byte1 << 8 ) + ( byte2 << 0 ) );
+ }
+
+ @Override
+ public char readChar()
+ throws IOException
+ {
+ return (char) readUnsignedShort();
+ }
+
+ @Override
+ public int readInt()
+ throws IOException
+ {
+ final int byte1 = read();
+ final int byte2 = read();
+ final int byte3 = read();
+ final int byte4 = read();
+ return ( ( byte1 << 24 ) + ( byte2 << 16 ) + ( byte3 << 8 ) + ( byte4 << 0 ) );
+ }
+
+ @Override
+ public long readLong()
+ throws IOException
+ {
+ in.read( longReadBuffer );
+ return ( ( (long) longReadBuffer[0] << 56 ) + ( (long) ( longReadBuffer[1] & 255 ) << 48 )
+ + ( (long) ( longReadBuffer[2] & 255 ) << 40 ) + ( (long) ( longReadBuffer[3] & 255 ) << 32 )
+ + ( (long) ( longReadBuffer[4] & 255 ) << 24 ) + ( ( longReadBuffer[5] & 255 ) << 16 )
+ + ( ( longReadBuffer[6] & 255 ) << 8 ) + ( ( longReadBuffer[7] & 255 ) << 0 ) );
+ }
+
+ @Override
+ public float readFloat()
+ throws IOException
+ {
+ return Float.intBitsToFloat( readInt() );
+ }
+
+ @Override
+ public double readDouble()
+ throws IOException
+ {
+ return Double.longBitsToDouble( readLong() );
+ }
+
+ @Override
+ public String readLine()
+ throws IOException
+ {
+ char buf[] = lineBuffer;
+ if ( buf == null )
+ {
+ buf = lineBuffer = new char[128];
+ }
+ int room = buf.length;
+ int offset = 0;
+ int c;
+ loop: while ( true )
+ {
+ switch ( c = read() )
+ {
+ case -1:
+ case '\n':
+ break loop;
+ case '\r':
+ final int c2 = read();
+ if ( ( c2 != '\n' ) && ( c2 != -1 ) )
+ {
+ new PushbackInputStream( this ).unread( c2 );
+ }
+ break loop;
+ default:
+ if ( --room < 0 )
+ {
+ buf = new char[offset + 128];
+ room = buf.length - offset - 1;
+ System.arraycopy( lineBuffer, 0, buf, 0, offset );
+ lineBuffer = buf;
+ }
+ buf[offset++] = (char) c;
+ break;
+ }
+ }
+ if ( ( c == -1 ) && ( offset == 0 ) )
+ {
+ return null;
+ }
+ return String.copyValueOf( buf, 0, offset );
+
+ }
+
+ @Override
+ public String readUTF()
+ throws IOException
+ {
+ boolean isNull = readBoolean();
+ if ( isNull )
+ return null;
+ int length = readInt();
+ StringBuilder result = new StringBuilder( length );
+ int chunkSize = length / SerializerOutputStream.STRING_CHUNK_SIZE + 1;
+ while ( chunkSize > 0 )
+ {
+ result.append( readShortUTF() );
+ chunkSize--;
+ }
+ return result.toString();
+ }
+
+ private final String readShortUTF()
+ throws IOException
+ {
+ final int utflen = readShort();
+ byte[] bytearr = null;
+ char[] chararr = null;
+ bytearr = new byte[utflen];
+ chararr = new char[utflen];
+ int c, char2, char3;
+ int count = 0;
+ int chararr_count = 0;
+ readFully( bytearr, 0, utflen );
+ while ( count < utflen )
+ {
+ c = bytearr[count] & 0xff;
+ if ( c > 127 )
+ break;
+ count++;
+ chararr[chararr_count++] = (char) c;
+ }
+ while ( count < utflen )
+ {
+ c = bytearr[count] & 0xff;
+ switch ( c >> 4 )
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ /* 0xxxxxxx */
+ count++;
+ chararr[chararr_count++] = (char) c;
+ break;
+ case 12:
+ case 13:
+ /* 110x xxxx 10xx xxxx */
+ count += 2;
+ if ( count > utflen )
+ throw new UTFDataFormatException( "malformed input: partial character at end" );
+ char2 = bytearr[count - 1];
+ if ( ( char2 & 0xC0 ) != 0x80 )
+ throw new UTFDataFormatException( "malformed input around byte " + count );
+ chararr[chararr_count++] = (char) ( ( ( c & 0x1F ) << 6 ) | ( char2 & 0x3F ) );
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ count += 3;
+ if ( count > utflen )
+ throw new UTFDataFormatException( "malformed input: partial character at end" );
+ char2 = bytearr[count - 2];
+ char3 = bytearr[count - 1];
+ if ( ( ( char2 & 0xC0 ) != 0x80 ) || ( ( char3 & 0xC0 ) != 0x80 ) )
+ throw new UTFDataFormatException( "malformed input around byte " + ( count - 1 ) );
+ chararr[chararr_count++] =
+ (char) ( ( ( c & 0x0F ) << 12 ) | ( ( char2 & 0x3F ) << 6 ) | ( ( char3 & 0x3F ) << 0 ) );
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw new UTFDataFormatException( "malformed input around byte " + count );
+ }
+ }
+ // The number of chars produced may be less than utflen
+ return new String( chararr, 0, chararr_count );
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerOutputStream.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerOutputStream.java
new file mode 100644
index 0000000..14eabc1
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/io/SerializerOutputStream.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.io;
+
+import java.io.DataOutput;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+
+import org.apache.directmemory.lightning.Serializer;
+
+/**
+ * Parts of this class taken from Hazelcast project
+ */
+public class SerializerOutputStream
+ extends FilterOutputStream
+ implements ObjectOutput
+{
+
+ static final int STRING_CHUNK_SIZE = 16 * 1024;
+
+ private final Serializer serializer;
+
+ private int written = 0;
+
+ public SerializerOutputStream( OutputStream out, Serializer serializer )
+ {
+ super( out );
+ this.serializer = serializer;
+ }
+
+ @Override
+ public void writeObject( Object object )
+ {
+ serializer.serialize( object, (DataOutput) this );
+ }
+
+ @Override
+ public synchronized void write( int b )
+ throws IOException
+ {
+ out.write( b );
+ increaseWritten( 1 );
+ }
+
+ @Override
+ public synchronized void write( byte[] b, int off, int len )
+ throws IOException
+ {
+ out.write( b, off, len );
+ increaseWritten( len );
+ }
+
+ @Override
+ public void writeBoolean( boolean v )
+ throws IOException
+ {
+ out.write( v ? 1 : 0 );
+ }
+
+ @Override
+ public void writeByte( int v )
+ throws IOException
+ {
+ out.write( v );
+ increaseWritten( 1 );
+ }
+
+ @Override
+ public void writeShort( int v )
+ throws IOException
+ {
+ out.write( ( v >>> 8 ) & 0xFF );
+ out.write( ( v >>> 0 ) & 0xFF );
+ increaseWritten( 2 );
+ }
+
+ @Override
+ public void writeChar( int v )
+ throws IOException
+ {
+ out.write( ( v >>> 8 ) & 0xFF );
+ out.write( ( v >>> 0 ) & 0xFF );
+ increaseWritten( 2 );
+ }
+
+ @Override
+ public void writeInt( int v )
+ throws IOException
+ {
+ out.write( ( v >>> 24 ) & 0xFF );
+ out.write( ( v >>> 16 ) & 0xFF );
+ out.write( ( v >>> 8 ) & 0xFF );
+ out.write( ( v >>> 0 ) & 0xFF );
+ increaseWritten( 4 );
+ }
+
+ @Override
+ public void writeLong( long v )
+ throws IOException
+ {
+ byte[] buffer = new byte[8];
+ buffer[0] = (byte) ( v >>> 56 );
+ buffer[1] = (byte) ( v >>> 48 );
+ buffer[2] = (byte) ( v >>> 40 );
+ buffer[3] = (byte) ( v >>> 32 );
+ buffer[4] = (byte) ( v >>> 24 );
+ buffer[5] = (byte) ( v >>> 16 );
+ buffer[6] = (byte) ( v >>> 8 );
+ buffer[7] = (byte) ( v >>> 0 );
+ out.write( buffer, 0, 8 );
+ increaseWritten( 8 );
+ }
+
+ @Override
+ public void writeFloat( float v )
+ throws IOException
+ {
+ writeInt( Float.floatToIntBits( v ) );
+ }
+
+ @Override
+ public void writeDouble( double v )
+ throws IOException
+ {
+ writeLong( Double.doubleToLongBits( v ) );
+ }
+
+ @Override
+ public void writeBytes( String s )
+ throws IOException
+ {
+ int len = s.length();
+ for ( int i = 0; i < len; i++ )
+ {
+ out.write( (byte) s.charAt( i ) );
+ }
+ increaseWritten( len );
+ }
+
+ @Override
+ public void writeChars( String s )
+ throws IOException
+ {
+ int len = s.length();
+ for ( int i = 0; i < len; i++ )
+ {
+ int v = s.charAt( i );
+ out.write( ( v >>> 8 ) & 0xFF );
+ out.write( ( v >>> 0 ) & 0xFF );
+ }
+ increaseWritten( len * 2 );
+ }
+
+ @Override
+ public void writeUTF( String s )
+ throws IOException
+ {
+ boolean isNull = ( s == null );
+ writeBoolean( isNull );
+ if ( isNull )
+ return;
+ int length = s.length();
+ writeInt( length );
+ int chunkSize = length / STRING_CHUNK_SIZE + 1;
+ for ( int i = 0; i < chunkSize; i++ )
+ {
+ int beginIndex = Math.max( 0, i * STRING_CHUNK_SIZE - 1 );
+ int endIndex = Math.min( ( i + 1 ) * STRING_CHUNK_SIZE - 1, length );
+ writeShortUTF( s.substring( beginIndex, endIndex ) );
+ }
+ }
+
+ private final void writeShortUTF( final String str )
+ throws IOException
+ {
+ final int strlen = str.length();
+ int utflen = 0;
+ int c, count = 0;
+ /* use charAt instead of copying String to char array */
+ for ( int i = 0; i < strlen; i++ )
+ {
+ c = str.charAt( i );
+ if ( ( c >= 0x0001 ) && ( c <= 0x007F ) )
+ {
+ utflen++;
+ }
+ else if ( c > 0x07FF )
+ {
+ utflen += 3;
+ }
+ else
+ {
+ utflen += 2;
+ }
+ }
+ // if (utflen > 65535)
+ // throw new UTFDataFormatException("encoded string too long: " + utflen
+ // + " bytes");
+ final byte[] bytearr = new byte[utflen + 2];
+ bytearr[count++] = (byte) ( ( utflen >>> 8 ) & 0xFF );
+ bytearr[count++] = (byte) ( ( utflen ) & 0xFF );
+ int i;
+ for ( i = 0; i < strlen; i++ )
+ {
+ c = str.charAt( i );
+ if ( !( ( c >= 0x0001 ) && ( c <= 0x007F ) ) )
+ break;
+ bytearr[count++] = (byte) c;
+ }
+ for ( ; i < strlen; i++ )
+ {
+ c = str.charAt( i );
+ if ( ( c >= 0x0001 ) && ( c <= 0x007F ) )
+ {
+ bytearr[count++] = (byte) c;
+ }
+ else if ( c > 0x07FF )
+ {
+ bytearr[count++] = (byte) ( 0xE0 | ( ( c >> 12 ) & 0x0F ) );
+ bytearr[count++] = (byte) ( 0x80 | ( ( c >> 6 ) & 0x3F ) );
+ bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) );
+ }
+ else
+ {
+ bytearr[count++] = (byte) ( 0xC0 | ( ( c >> 6 ) & 0x1F ) );
+ bytearr[count++] = (byte) ( 0x80 | ( ( c ) & 0x3F ) );
+ }
+ }
+ write( bytearr, 0, utflen + 2 );
+ }
+
+ public int size()
+ {
+ return written;
+ }
+
+ private void increaseWritten( int count )
+ {
+ int temp = written + count;
+ if ( temp < 0 )
+ {
+ temp = Integer.MAX_VALUE;
+ }
+ written = temp;
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LogLevel.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LogLevel.java
new file mode 100644
index 0000000..bb8cc45
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LogLevel.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.logging;
+
+public enum LogLevel
+{
+
+ Trace, Debug, Info, Warn, Error, Fatal
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/Logger.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/Logger.java
new file mode 100644
index 0000000..9524ca1
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/Logger.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.logging;
+
+public interface Logger
+{
+
+ Logger getChildLogger( Class<?> clazz );
+
+ Logger getChildLogger( String name );
+
+ String getName();
+
+ boolean isLogLevelEnabled( LogLevel logLevel );
+
+ boolean isTraceEnabled();
+
+ boolean isDebugEnabled();
+
+ boolean isInfoEnabled();
+
+ boolean isWarnEnabled();
+
+ boolean isErrorEnabled();
+
+ boolean isFatalEnabled();
+
+ void trace( String message );
+
+ void trace( String message, Throwable throwable );
+
+ void debug( String message );
+
+ void debug( String message, Throwable throwable );
+
+ void info( String message );
+
+ void info( String message, Throwable throwable );
+
+ void warn( String message );
+
+ void warn( String message, Throwable throwable );
+
+ void error( String message );
+
+ void error( String message, Throwable throwable );
+
+ void fatal( String message );
+
+ void fatal( String message, Throwable throwable );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LoggerAdapter.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LoggerAdapter.java
new file mode 100644
index 0000000..fb58d78
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/logging/LoggerAdapter.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.logging;
+
+public class LoggerAdapter
+ implements Logger
+{
+
+ private final String name;
+
+ public LoggerAdapter()
+ {
+ this( "Default" );
+ }
+
+ public LoggerAdapter( Class<?> clazz )
+ {
+ this( clazz.getCanonicalName() );
+ }
+
+ public LoggerAdapter( String name )
+ {
+ this.name = name;
+ }
+
+ @Override
+ public Logger getChildLogger( Class<?> clazz )
+ {
+ return getChildLogger( clazz.getCanonicalName() );
+ }
+
+ @Override
+ public Logger getChildLogger( final String name )
+ {
+ final Logger that = this;
+ return new Logger()
+ {
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ that.warn( message, throwable );
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ that.warn( message );
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ that.trace( message, throwable );
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ that.trace( message );
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return that.isWarnEnabled();
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return that.isTraceEnabled();
+ }
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ return that.isLogLevelEnabled( logLevel );
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return that.isInfoEnabled();
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return that.isFatalEnabled();
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return that.isErrorEnabled();
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return that.isDebugEnabled();
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ that.info( message, throwable );
+ }
+
+ @Override
+ public void info( String message )
+ {
+ that.info( message );
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public Logger getChildLogger( String name )
+ {
+ return that.getChildLogger( name );
+ }
+
+ @Override
+ public Logger getChildLogger( Class<?> clazz )
+ {
+ return getChildLogger( clazz.getCanonicalName() );
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ that.fatal( message, throwable );
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ that.fatal( message );
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ that.error( message, throwable );
+ }
+
+ @Override
+ public void error( String message )
+ {
+ that.error( message );
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ that.debug( message, throwable );
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ that.debug( message );
+ }
+ };
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ }
+
+ @Override
+ public void info( String message )
+ {
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ }
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ }
+
+ @Override
+ public void error( String message )
+ {
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ }
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/AccessorType.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/AccessorType.java
new file mode 100644
index 0000000..0f77548
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/AccessorType.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public enum AccessorType
+{
+ Field, Method
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ArrayPropertyAccessor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ArrayPropertyAccessor.java
new file mode 100644
index 0000000..ba458fa
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ArrayPropertyAccessor.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public interface ArrayPropertyAccessor
+ extends ValuePropertyAccessor
+{
+
+ <T> void writeObject( Object instance, int index, T value );
+
+ <T> T readObject( Object instance, int index );
+
+ void writeBoolean( Object instance, int index, boolean value );
+
+ boolean readBoolean( Object instance, int index );
+
+ void writeByte( Object instance, int index, byte value );
+
+ byte readByte( Object instance, int index );
+
+ void writeChar( Object instance, int index, char value );
+
+ char readChar( Object instance, int index );
+
+ void writeShort( Object instance, int index, short value );
+
+ short readShort( Object instance, int index );
+
+ void writeInt( Object instance, int index, int value );
+
+ int readInt( Object instance, int index );
+
+ void writeLong( Object instance, int index, long value );
+
+ long readLong( Object instance, int index );
+
+ void writeFloat( Object instance, int index, float value );
+
+ float readFloat( Object instance, int index );
+
+ void writeDouble( Object instance, int index, double value );
+
+ double readDouble( Object instance, int index );
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/Attribute.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/Attribute.java
new file mode 100644
index 0000000..93b6d62
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/Attribute.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a property (annotated field or method) as an attribute to be serialized by Lightning.<br>
+ *
+ * <pre>
+ *
+ * public class MyEntity
+ * {
+ *
+ * private long id;
+ *
+ * @Attribute
+ * private String name;
+ *
+ * @Attribute
+ * public long getId()
+ * {
+ * return id;
+ * }
+ *
+ * public void setId( long id )
+ * {
+ * this.id = id;
+ * }
+ *
+ * public String getName()
+ * {
+ * return name;
+ * }
+ *
+ * public void setName( String name )
+ * {
+ * this.name = name;
+ * }
+ * }
+ * </pre>
+ */
+@Documented
+@Inherited
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.METHOD } )
+public @interface Attribute
+{
+
+ public static final String NULL = "~~NULL~~";
+
+ /**
+ * If a method is annotated this value defines a property name differs from property name extracted from methodname.<br>
+ * Means if method is "getFoo" property name defaults to "foo", but if the method is annotated by @Attribute("bar")
+ * the property name will be explicitly "bar".
+ *
+ * @return the defined property name
+ */
+ String property() default NULL;
+
+ boolean nullable() default false;
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinition.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinition.java
new file mode 100644
index 0000000..e8b986d
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinition.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public interface ClassDefinition
+{
+
+ String getCanonicalName();
+
+ Class<?> getType();
+
+ byte[] getChecksum();
+
+ long getId();
+
+ long getSerialVersionUID();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinitionContainer.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinitionContainer.java
new file mode 100644
index 0000000..1f0e960
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDefinitionContainer.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+import java.util.Collection;
+
+public interface ClassDefinitionContainer
+{
+
+ Collection<ClassDefinition> getClassDefinitions();
+
+ Class<?> getTypeById( long id );
+
+ ClassDefinition getClassDefinitionByCanonicalName( String canonicalName );
+
+ ClassDefinition getClassDefinitionById( long id );
+
+ ClassDefinition getClassDefinitionByType( Class<?> type );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDescriptor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDescriptor.java
new file mode 100644
index 0000000..fb49377
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ClassDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+import java.util.List;
+
+import org.apache.directmemory.lightning.Marshaller;
+
+public interface ClassDescriptor
+{
+
+ ClassDefinition getClassDefinition();
+
+ Class<?> getType();
+
+ List<PropertyDescriptor> getPropertyDescriptors();
+
+ Marshaller getMarshaller();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyAccessor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyAccessor.java
new file mode 100644
index 0000000..0528024
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyAccessor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public interface PropertyAccessor
+{
+
+ Class<?> getDeclaringClass();
+
+ Class<?> getDefinedClass();
+
+ AccessorType getAccessorType();
+
+ Class<?> getType();
+
+ boolean isArrayType();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyDescriptor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyDescriptor.java
new file mode 100644
index 0000000..29e30b6
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/PropertyDescriptor.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.directmemory.lightning.Marshaller;
+
+public interface PropertyDescriptor
+ extends Comparable<PropertyDescriptor>
+{
+
+ Annotation[] getAnnotations();
+
+ Class<?> getDefinedClass();
+
+ Class<?> getDeclaringClass();
+
+ PropertyAccessor getPropertyAccessor();
+
+ String getName();
+
+ String getPropertyName();
+
+ Class<?> getType();
+
+ String getInternalSignature();
+
+ Marshaller getMarshaller();
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValueNullableEvaluator.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValueNullableEvaluator.java
new file mode 100644
index 0000000..a9a73fc
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValueNullableEvaluator.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public interface ValueNullableEvaluator
+{
+
+ boolean isValueNullable( PropertyDescriptor propertyDescriptor );
+
+}
diff --git a/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValuePropertyAccessor.java b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValuePropertyAccessor.java
new file mode 100644
index 0000000..9f013b8
--- /dev/null
+++ b/lightning-api/src/main/java/org/apache/directmemory/lightning/metadata/ValuePropertyAccessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.metadata;
+
+public interface ValuePropertyAccessor
+ extends PropertyAccessor
+{
+
+ <T> void writeObject( Object instance, T value );
+
+ <T> T readObject( Object instance );
+
+ void writeBoolean( Object instance, boolean value );
+
+ boolean readBoolean( Object instance );
+
+ void writeByte( Object instance, byte value );
+
+ byte readByte( Object instance );
+
+ void writeChar( Object instance, char value );
+
+ char readChar( Object instance );
+
+ void writeShort( Object instance, short value );
+
+ short readShort( Object instance );
+
+ void writeInt( Object instance, int value );
+
+ int readInt( Object instance );
+
+ void writeLong( Object instance, long value );
+
+ long readLong( Object instance );
+
+ void writeFloat( Object instance, float value );
+
+ float readFloat( Object instance );
+
+ void writeDouble( Object instance, double value );
+
+ double readDouble( Object instance );
+
+}
diff --git a/lightning-core/pom.xml b/lightning-core/pom.xml
new file mode 100644
index 0000000..2895264
--- /dev/null
+++ b/lightning-core/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-core</artifactId>
+ <name>Lightning: Core</name>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode</groupId>
+ <artifactId>reflectasm</artifactId>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>jarjar</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ <property>
+ <name>jarjar</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>jarjar-maven-plugin</artifactId>
+ <version>1.4</version>
+ <configuration>
+ <includes>
+ <include>com.carrotsearch:hppc</include>
+ <include>${project.groupId}:lightning-api</include>
+ <include>asm:asm</include>
+ <include>com.googlecode:reflectasm</include>
+ </includes>
+ <rules>
+ <rule>
+ <pattern>com.carrotsearch.**</pattern>
+ <result>org.apache.directmemory.lightning.internal.bundle.@1</result>
+ </rule>
+ <rule>
+ <pattern>org.objectweb.**</pattern>
+ <result>org.apache.directmemory.lightning.internal.bundle.@1</result>
+ </rule>
+ <rule>
+ <pattern>com.esotericsoftware.**</pattern>
+ <result>org.apache.directmemory.lightning.internal.bundle.@1</result>
+ </rule>
+ </rules>
+ </configuration>
+ <executions>
+ <execution>
+ <id>jarjar-classes</id>
+ <phase>process-test-classes</phase>
+ <goals>
+ <goal>jarjar</goal>
+ </goals>
+ <configuration>
+ <input>{classes}</input>
+ </configuration>
+ </execution>
+ <execution>
+ <id>jarjar-test-classes</id>
+ <phase>process-test-classes</phase>
+ <goals>
+ <goal>jarjar</goal>
+ </goals>
+ <configuration>
+ <input>{test-classes}</input>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/Lightning.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/Lightning.java
new file mode 100644
index 0000000..34c39aa
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/Lightning.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.ClassComparisonStrategy;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.DefaultValueNullableEvaluator;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.internal.InternalSerializerCreator;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.logging.LoggerAdapter;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+public final class Lightning
+{
+
+ private Lightning()
+ {
+ }
+
+ public static final Builder newBuilder()
+ {
+ return new Builder();
+ }
+
+ public static final Serializer createSerializer( SerializerDefinition... serializerDefinitions )
+ {
+ return createSerializer( Arrays.asList( serializerDefinitions ) );
+ }
+
+ public static final Serializer createSerializer( Iterable<? extends SerializerDefinition> serializerDefinitions )
+ {
+ return new Builder().serializerDefinitions( serializerDefinitions ).build();
+ }
+
+ public static class Builder
+ {
+
+ private Set<SerializerDefinition> serializerDefinitions = new HashSet<SerializerDefinition>();
+
+ private SerializationStrategy serializationStrategy = SerializationStrategy.SpeedOptimized;
+
+ private Class<? extends Annotation> attributeAnnotation = null;
+
+ private ClassComparisonStrategy classComparisonStrategy = ClassComparisonStrategy.LightningChecksum;
+
+ private ValueNullableEvaluator valueNullableEvaluator = new DefaultValueNullableEvaluator();
+
+ private File debugCacheDirectory = null;
+
+ private Logger logger = new LoggerAdapter();
+
+ private Builder()
+ {
+ }
+
+ public Builder describesAttributs( Class<? extends Annotation> attributeAnnotation )
+ {
+ this.attributeAnnotation = attributeAnnotation;
+ return this;
+ }
+
+ public Builder debugCacheDirectory( File debugCacheDirectory )
+ {
+ this.debugCacheDirectory = debugCacheDirectory;
+ return this;
+ }
+
+ public Builder serializationStrategy( SerializationStrategy serializationStrategy )
+ {
+ this.serializationStrategy = serializationStrategy;
+ return this;
+ }
+
+ public Builder classComparisonStrategy( ClassComparisonStrategy classComparisonStrategy )
+ {
+ this.classComparisonStrategy = classComparisonStrategy;
+ return this;
+ }
+
+ public Builder serializerDefinitions( SerializerDefinition... serializerDefinitions )
+ {
+ return serializerDefinitions( Arrays.asList( serializerDefinitions ) );
+ }
+
+ public Builder serializerDefinitions( Iterable<? extends SerializerDefinition> serializerDefinitions )
+ {
+ for ( SerializerDefinition serializerDefinition : serializerDefinitions )
+ {
+ this.serializerDefinitions.add( serializerDefinition );
+ }
+ return this;
+ }
+
+ public Builder setValueNullableEvaluator( ValueNullableEvaluator valueNullableEvaluator )
+ {
+ this.valueNullableEvaluator = valueNullableEvaluator;
+ return this;
+ }
+
+ public Builder logger( Logger logger )
+ {
+ this.logger = logger;
+ return this;
+ }
+
+ public Serializer build()
+ {
+ return new InternalSerializerCreator().setLogger( logger ).setSerializationStrategy( serializationStrategy ).setClassComparisonStrategy( classComparisonStrategy ).setAttributeAnnotation( attributeAnnotation ).setDebugCacheDirectory( debugCacheDirectory ).setValueNullableEvaluator( valueNullableEvaluator ).addSerializerDefinitions( serializerDefinitions ).build();
+ }
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractMarshaller.java
new file mode 100644
index 0000000..7e91f86
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractMarshaller.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.base;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public abstract class AbstractMarshaller
+ implements Marshaller
+{
+
+ @Override
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ return null;
+ }
+
+ protected boolean writePossibleNull( Object value, DataOutput dataOutput )
+ throws IOException
+ {
+ dataOutput.writeByte( value == null ? 1 : 0 );
+ return value != null;
+ }
+
+ protected boolean isNull( DataInput dataInput )
+ throws IOException
+ {
+ byte isNull = dataInput.readByte();
+ return isNull == 1 ? true : false;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractObjectMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractObjectMarshaller.java
new file mode 100644
index 0000000..1344edf
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractObjectMarshaller.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.base;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public abstract class AbstractObjectMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public final <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ Object value =
+ serializationContext.getObjectInstantiatorFactory().getInstantiatorOf( propertyDescriptor.getType() );
+ return unmarshall( (V) value, propertyDescriptor, dataInput, serializationContext );
+ }
+
+ public abstract <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException;
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractSerializerDefinition.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractSerializerDefinition.java
new file mode 100644
index 0000000..81435e6
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/AbstractSerializerDefinition.java
@@ -0,0 +1,445 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.base;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.bindings.AnnotatedBinder;
+import org.apache.directmemory.lightning.bindings.AttributeBinder;
+import org.apache.directmemory.lightning.bindings.ClassBinder;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.configuration.TypeIntrospector;
+import org.apache.directmemory.lightning.exceptions.SerializerDefinitionException;
+import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
+import org.apache.directmemory.lightning.generator.DefinitionVisitor;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.InternalMarshallerContext;
+import org.apache.directmemory.lightning.internal.beans.introspection.AnnotatedTypeIntrospector;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
+
+public abstract class AbstractSerializerDefinition
+ implements SerializerDefinition
+{
+
+ private final InternalMarshallerContext marshallerContext = new InternalMarshallerContext();
+
+ private final Set<SerializerDefinition> children = new HashSet<SerializerDefinition>();
+
+ private final Map<PropertyDescriptor, Marshaller> propertyMarshallers =
+ new HashMap<PropertyDescriptor, Marshaller>();
+
+ private final Map<AnnotatedBinder, AnnotationBinderDefinition<?>> annotationBinders =
+ new HashMap<AnnotatedBinder, AnnotationBinderDefinition<?>>();
+
+ private DefinitionBuildingContext definitionBuildingContext;
+
+ private ObjectInstantiatorFactory objectInstantiatorFactory = null;
+
+ private Class<? extends Annotation> attributeAnnotation = null;
+
+ private AbstractSerializerDefinition parent = null;
+
+ @Override
+ public final void configure( DefinitionBuildingContext definitionBuildingContext,
+ ObjectInstantiatorFactory objectInstantiatorFactory )
+ {
+ // Save PropertyDescriptorFactory for later use in configure()
+ this.definitionBuildingContext = definitionBuildingContext;
+
+ // Save ObjectInstantiatorFactory for later use in configure()
+ this.objectInstantiatorFactory = objectInstantiatorFactory;
+
+ // Read the configuration
+ configure();
+ }
+
+ @Override
+ public final void acceptVisitor( DefinitionVisitor visitor )
+ {
+ // Start visiting
+ visitor.visitSerializerDefinition( this );
+
+ // Visit the attribute annotation if set
+ Class<? extends Annotation> attributeAnnotation = findAttributeAnnotation( this );
+ if ( attributeAnnotation != null )
+ {
+ visitor.visitAttributeAnnotation( attributeAnnotation );
+ }
+
+ // Visit all direct marshallers
+ Iterator<ObjectObjectCursor<Type, Marshaller>> iterator = marshallerContext.getInternalMap().iterator();
+ while ( iterator.hasNext() )
+ {
+ ObjectObjectCursor<Type, Marshaller> entry = iterator.next();
+ visitor.visitClassDefine( entry.key, entry.value );
+ }
+
+ // Visit annotated properties
+ Iterator<AnnotationBinderDefinition<?>> annotationIterator = annotationBinders.values().iterator();
+ while ( annotationIterator.hasNext() )
+ {
+ AnnotationBinderDefinition<?> annotationBinderDefinition = annotationIterator.next();
+ annotationBinderDefinition.acceptVisitor( visitor );
+ }
+
+ // Visit all property definitions
+ for ( Entry<PropertyDescriptor, Marshaller> entry : propertyMarshallers.entrySet() )
+ {
+ visitor.visitPropertyDescriptor( entry.getKey(), entry.getValue() );
+
+ Class<?> type = entry.getKey().getType();
+ if ( type.isPrimitive() || type.isArray() && type.getComponentType().isPrimitive() )
+ {
+ continue;
+ }
+
+ visitor.visitClassDefine( type, entry.getValue() );
+ }
+
+ // Visit all children
+ for ( SerializerDefinition child : children )
+ {
+ child.configure( definitionBuildingContext, objectInstantiatorFactory );
+ child.acceptVisitor( visitor );
+ }
+
+ // Finalize visit
+ visitor.visitFinalizeSerializerDefinition( this );
+ }
+
+ protected abstract void configure();
+
+ protected <T> ClassBinder<T> serialize( final Class<T> clazz )
+ {
+ return buildClassBinder( clazz );
+ }
+
+ protected void install( SerializerDefinition childSerializer )
+ {
+ children.add( childSerializer );
+ if ( childSerializer instanceof AbstractSerializerDefinition )
+ {
+ ( (AbstractSerializerDefinition) childSerializer ).parent = this;
+ }
+ }
+
+ protected void describesAttributes( Class<? extends Annotation> attributeAnnotation )
+ {
+ this.attributeAnnotation = attributeAnnotation;
+ }
+
+ protected <V> AttributeBinder<V> attribute( final String attribute )
+ {
+ return new DefinedAttributeBinder<V>()
+ {
+
+ @Override
+ protected void setDeclaringClass( Class<?> declaringClass )
+ {
+ super.setDeclaringClass( declaringClass );
+ try
+ {
+ Field reflectiveField = declaringClass.getDeclaredField( attribute );
+ reflectiveField.setAccessible( true );
+ property = reflectiveField;
+ }
+ catch ( Exception e )
+ {
+ throw new SerializerDefinitionException( "Property " + property + " could not be found for type "
+ + declaringClass.getCanonicalName(), e );
+ }
+ }
+ };
+ }
+
+ protected <V> AttributeBinder<V> attribute( final Field attribute )
+ {
+ return new DefinedAttributeBinder<V>()
+ {
+
+ {
+ property = attribute;
+ declaringClass = attribute.getDeclaringClass();
+ }
+ };
+ }
+
+ private <T> ClassBinder<T> buildClassBinder( final Class<T> clazz )
+ {
+ return new ClassBinder<T>()
+ {
+
+ @Override
+ public AnnotatedBinder attributes()
+ {
+ return buildAnnotatedBinder( this, attributeAnnotation );
+ }
+
+ @Override
+ public AnnotatedBinder attributes( Class<? extends Annotation> annotation )
+ {
+ return buildAnnotatedBinder( this, annotation );
+ }
+
+ @Override
+ public Class<T> getType()
+ {
+ return clazz;
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public void using( Class<?> clazz )
+ {
+ if ( Marshaller.class.isAssignableFrom( clazz ) )
+ {
+ try
+ {
+ using( ( (Class<Marshaller>) clazz ).newInstance() );
+ }
+ catch ( Exception e )
+ {
+ throw new SerializerDefinitionException( "Marshaller class " + clazz.getCanonicalName()
+ + " could not be instantiated. Is there a standard (public) constructor?", e );
+ }
+ }
+
+ }
+
+ @Override
+ public void using( Marshaller marshaller )
+ {
+ if ( marshaller instanceof AbstractObjectMarshaller )
+ {
+ marshallerContext.bindMarshaller( clazz,
+ new ObjenesisDelegatingMarshaller(
+ (AbstractObjectMarshaller) marshaller,
+ objectInstantiatorFactory ) );
+ }
+ else
+ {
+ marshallerContext.bindMarshaller( clazz, marshaller );
+ }
+ }
+
+ @Override
+ public void using( TypeIntrospector typeIntrospector )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void attributes( AttributeBinder<?>... attributes )
+ {
+ for ( AttributeBinder<?> attribute : attributes )
+ {
+ if ( attribute instanceof DefinedAttributeBinder )
+ {
+ DefinedAttributeBinder<?> binder = (DefinedAttributeBinder<?>) attribute;
+ binder.setDeclaringClass( getType() );
+ binder.build();
+ }
+ }
+ }
+ };
+ }
+
+ private <T> AnnotatedBinder buildAnnotatedBinder( final ClassBinder<T> classBinder,
+ final Class<? extends Annotation> annotation )
+ {
+
+ return new AnnotatedBinder()
+ {
+
+ private final AnnotationBinderDefinition<T> binder = new AnnotationBinderDefinition<T>( classBinder );
+
+ {
+ annotationBinders.put( this, binder );
+ }
+
+ @Override
+ public AnnotatedBinder exclude( String property )
+ {
+ binder.addExclude( property );
+ return this;
+ }
+
+ @Override
+ public AnnotatedBinder excludes( String... properties )
+ {
+ for ( String property : properties )
+ {
+ binder.addExclude( property );
+ }
+ return this;
+ }
+ };
+ }
+
+ private Class<? extends Annotation> findAttributeAnnotation( AbstractSerializerDefinition abstractSerializerDefinition )
+ {
+ if ( attributeAnnotation != null )
+ {
+ return attributeAnnotation;
+ }
+
+ if ( parent != null )
+ {
+ return abstractSerializerDefinition.findAttributeAnnotation( parent );
+ }
+
+ return Attribute.class;
+ }
+
+ private class AnnotationBinderDefinition<T>
+ {
+
+ private final AnnotatedTypeIntrospector typeIntrospector;
+
+ private final ClassBinder<T> classBinder;
+
+ private final List<String> excludes = new ArrayList<String>();
+
+ private AnnotationBinderDefinition( ClassBinder<T> classBinder )
+ {
+ this.typeIntrospector =
+ new AnnotatedTypeIntrospector( findAttributeAnnotation( AbstractSerializerDefinition.this ), excludes );
+ this.classBinder = classBinder;
+ }
+
+ public void addExclude( String exclude )
+ {
+ excludes.add( exclude );
+ }
+
+ public void acceptVisitor( DefinitionVisitor visitor )
+ {
+ MarshallerContext marshallers = combineMarshallers( AbstractSerializerDefinition.this );
+ List<PropertyDescriptor> propertyDescriptors =
+ typeIntrospector.introspect( classBinder.getType(), definitionBuildingContext.getMarshallerStrategy(),
+ marshallers, definitionBuildingContext.getPropertyDescriptorFactory() );
+
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
+ {
+ Class<?> fieldType = propertyDescriptor.getType();
+ Marshaller marshaller = propertyDescriptor.getMarshaller();
+ visitor.visitAnnotatedAttribute( propertyDescriptor, marshaller );
+
+ if ( fieldType.isPrimitive() || fieldType.isArray() && fieldType.getComponentType().isPrimitive() )
+ {
+ continue;
+ }
+
+ visitor.visitClassDefine( !fieldType.isArray() ? fieldType : fieldType.getComponentType(), marshaller );
+ if ( marshaller == null )
+ {
+ visitFieldTypeAnnotatedProperties( !fieldType.isArray() ? fieldType : fieldType.getComponentType(),
+ visitor );
+ }
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <F> void visitFieldTypeAnnotatedProperties( Class<?> type, DefinitionVisitor visitor )
+ {
+ ClassBinder<F> classBinder = (ClassBinder<F>) buildClassBinder( type );
+ new AnnotationBinderDefinition<F>( classBinder ).acceptVisitor( visitor );
+ }
+
+ private MarshallerContext combineMarshallers( AbstractSerializerDefinition abstractSerializerDefinition )
+ {
+ return new InternalMarshallerContext( abstractSerializerDefinition.marshallerContext );
+ }
+ }
+
+ private abstract class DefinedAttributeBinder<V>
+ implements AttributeBinder<V>
+ {
+
+ protected Marshaller marshaller;
+
+ protected Field property;
+
+ protected Class<?> declaringClass;
+
+ protected void setDeclaringClass( Class<?> declaringClass )
+ {
+ this.declaringClass = declaringClass;
+ }
+
+ @Override
+ public AttributeBinder<V> using( Class<? extends Marshaller> marshaller )
+ {
+ try
+ {
+ using( marshaller.newInstance() );
+ return this;
+ }
+ catch ( Exception e )
+ {
+ throw new SerializerDefinitionException( "Marshaller class " + marshaller.getCanonicalName()
+ + " could not be instantiated. Is there a standard (public) constructor?", e );
+ }
+ }
+
+ @Override
+ public AttributeBinder<V> using( Marshaller marshaller )
+ {
+ if ( marshaller instanceof TypeBindableMarshaller )
+ {
+ Type[] typeArguments = TypeUtil.getTypeArgument( property.getGenericType() );
+ this.marshaller = ( (TypeBindableMarshaller) marshaller ).bindType( typeArguments );
+ }
+
+ return this;
+ }
+
+ private void build()
+ {
+ if ( marshaller == null )
+ {
+ marshaller =
+ definitionBuildingContext.getMarshallerStrategy().getMarshaller( property.getType(),
+ marshallerContext, true );
+ }
+ propertyMarshallers.put( definitionBuildingContext.getPropertyDescriptorFactory().byField( property,
+ marshaller,
+ declaringClass ),
+ marshaller );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/base/DefaultValueNullableEvaluator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/DefaultValueNullableEvaluator.java
new file mode 100644
index 0000000..e93aed1
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/DefaultValueNullableEvaluator.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.base;
+
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+public class DefaultValueNullableEvaluator
+ implements ValueNullableEvaluator
+{
+
+ @Override
+ public boolean isValueNullable( PropertyDescriptor propertyDescriptor )
+ {
+ return !propertyDescriptor.getType().isPrimitive();
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/base/ObjenesisDelegatingMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/ObjenesisDelegatingMarshaller.java
new file mode 100644
index 0000000..f3596a9
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/base/ObjenesisDelegatingMarshaller.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.base;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+class ObjenesisDelegatingMarshaller
+ implements Marshaller
+{
+
+ private final ObjectInstantiatorFactory objectInstantiatorFactory;
+
+ private final AbstractObjectMarshaller delegatedMarshaller;
+
+ ObjenesisDelegatingMarshaller( AbstractObjectMarshaller delegatedMarshaller,
+ ObjectInstantiatorFactory objectInstantiatorFactory )
+ {
+ this.delegatedMarshaller = delegatedMarshaller;
+ this.objectInstantiatorFactory = objectInstantiatorFactory;
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return delegatedMarshaller.acceptType( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ delegatedMarshaller.marshall( value, propertyDescriptor, dataOutput, serializationContext );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ V value = (V) objectInstantiatorFactory.newInstance( propertyDescriptor.getType() );
+ return delegatedMarshaller.unmarshall( value, propertyDescriptor, dataInput, serializationContext );
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AnnotatedBinder.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AnnotatedBinder.java
new file mode 100644
index 0000000..40d20c6
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AnnotatedBinder.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.bindings;
+
+public interface AnnotatedBinder
+{
+
+ AnnotatedBinder exclude( String property );
+
+ AnnotatedBinder excludes( String... properties );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AttributeBinder.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AttributeBinder.java
new file mode 100644
index 0000000..d86edd9
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/AttributeBinder.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.bindings;
+
+import org.apache.directmemory.lightning.Marshaller;
+
+public interface AttributeBinder<V>
+{
+
+ AttributeBinder<V> using( Class<? extends Marshaller> marshaller );
+
+ AttributeBinder<V> using( Marshaller marshaller );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/ClassBinder.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/ClassBinder.java
new file mode 100644
index 0000000..76539e7
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/ClassBinder.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.bindings;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.configuration.TypeIntrospector;
+
+public interface ClassBinder<T>
+{
+
+ AnnotatedBinder attributes();
+
+ AnnotatedBinder attributes( Class<? extends Annotation> annotation );
+
+ void attributes( AttributeBinder<?>... attributes );
+
+ void using( Class<?> clazz );
+
+ void using( Marshaller marshaller );
+
+ void using( TypeIntrospector typeIntrospector );
+
+ Class<T> getType();
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/MarshallerBinder.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/MarshallerBinder.java
new file mode 100644
index 0000000..fc9ea7b
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/bindings/MarshallerBinder.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.bindings;
+
+import org.apache.directmemory.lightning.Marshaller;
+
+public interface MarshallerBinder
+{
+
+ void using( Class<? extends Marshaller> marshaller );
+
+ void using( Marshaller marshaller );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/CheatPropertyDescriptor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/CheatPropertyDescriptor.java
new file mode 100644
index 0000000..3f9002d
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/CheatPropertyDescriptor.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.metadata.AccessorType;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class CheatPropertyDescriptor
+ implements PropertyDescriptor
+{
+
+ private final String name;
+
+ private final String propertyName;
+
+ private final String internalSignature;
+
+ private final String declaringCanonicalClassname;
+
+ private final PropertyAccessor propertyAccessor;
+
+ private final Marshaller marshaller;
+
+ public CheatPropertyDescriptor( String propertyName, final Class<?> type, Marshaller marshaller )
+ {
+ this.name = propertyName;
+ this.propertyName = propertyName;
+ this.marshaller = marshaller;
+ this.propertyAccessor = new PropertyAccessor()
+ {
+
+ @Override
+ public boolean isArrayType()
+ {
+ return type.isArray();
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return type;
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return type;
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return type;
+ }
+
+ @Override
+ public AccessorType getAccessorType()
+ {
+ return AccessorType.Field;
+ }
+ };
+
+ this.declaringCanonicalClassname = null;
+ this.internalSignature = null;
+ }
+
+ @Override
+ public int compareTo( PropertyDescriptor o )
+ {
+ return propertyName.compareTo( o.getPropertyName() );
+ }
+
+ @Override
+ public Annotation[] getAnnotations()
+ {
+ return new Annotation[0];
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return propertyAccessor.getDefinedClass();
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return propertyAccessor.getDeclaringClass();
+ }
+
+ @Override
+ public PropertyAccessor getPropertyAccessor()
+ {
+ return propertyAccessor;
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public String getPropertyName()
+ {
+ return propertyName;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return propertyAccessor.getType();
+ }
+
+ @Override
+ public String getInternalSignature()
+ {
+ return internalSignature;
+ }
+
+ @Override
+ public Marshaller getMarshaller()
+ {
+ return marshaller;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result =
+ prime * result + ( ( declaringCanonicalClassname == null ) ? 0 : declaringCanonicalClassname.hashCode() );
+ result = prime * result + ( ( internalSignature == null ) ? 0 : internalSignature.hashCode() );
+ result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
+ result = prime * result + ( ( propertyName == null ) ? 0 : propertyName.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ CheatPropertyDescriptor other = (CheatPropertyDescriptor) obj;
+ if ( declaringCanonicalClassname == null )
+ {
+ if ( other.declaringCanonicalClassname != null )
+ return false;
+ }
+ else if ( !declaringCanonicalClassname.equals( other.declaringCanonicalClassname ) )
+ return false;
+ if ( internalSignature == null )
+ {
+ if ( other.internalSignature != null )
+ return false;
+ }
+ else if ( !internalSignature.equals( other.internalSignature ) )
+ return false;
+ if ( name == null )
+ {
+ if ( other.name != null )
+ return false;
+ }
+ else if ( !name.equals( other.name ) )
+ return false;
+ if ( propertyName == null )
+ {
+ if ( other.propertyName != null )
+ return false;
+ }
+ else if ( !propertyName.equals( other.propertyName ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CheatingPropertyDescriptor [name=" + name + ", propertyName=" + propertyName + ", internalSignature="
+ + internalSignature + ", declaringCanonicalClassname=" + declaringCanonicalClassname
+ + ", propertyAccessor=" + propertyAccessor + ", marshaller=" + marshaller + "]";
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/ClassDescriptorAwareSerializer.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/ClassDescriptorAwareSerializer.java
new file mode 100644
index 0000000..83f5873
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/ClassDescriptorAwareSerializer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+
+public interface ClassDescriptorAwareSerializer
+ extends Serializer
+{
+
+ ClassDescriptor findClassDescriptor( Class<?> type );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinition.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinition.java
new file mode 100644
index 0000000..cb078bc
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinition.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.internal.util.Crc64Util;
+import org.apache.directmemory.lightning.internal.util.InternalUtil;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.objectweb.asm.Type;
+
+class InternalClassDefinition
+ implements ClassDefinition, Comparable<ClassDefinition>
+{
+
+ private final String canonicalName;
+
+ private final Class<?> type;
+
+ private final byte[] checksum;
+
+ private final long serialVersionUID;
+
+ private long id;
+
+ InternalClassDefinition( Class<?> type, List<PropertyDescriptor> propertyDescriptors, Logger logger )
+ {
+ this.canonicalName = Type.getInternalName( type ).replace( "/", "." );
+ this.type = type;
+
+ byte[] classData = ClassUtil.getClassBytes( !type.isArray() ? type : type.getComponentType() );
+ this.checksum = InternalUtil.getChecksum( propertyDescriptors, logger );
+ this.id = Crc64Util.checksum( classData );
+ this.serialVersionUID = ClassUtil.calculateSerialVersionUID( type );
+ }
+
+ InternalClassDefinition( long id, Class<?> type, byte[] checksum, long serialVersionUID )
+ {
+ this.canonicalName = Type.getInternalName( type ).replace( "/", "." );
+ this.type = type;
+ this.id = id;
+ this.checksum = checksum;
+ this.serialVersionUID = serialVersionUID;
+ }
+
+ @Override
+ public String getCanonicalName()
+ {
+ return canonicalName;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return type;
+ }
+
+ @Override
+ public byte[] getChecksum()
+ {
+ return Arrays.copyOf( checksum, checksum.length );
+ }
+
+ @Override
+ public long getId()
+ {
+ return id;
+ }
+
+ @Override
+ public long getSerialVersionUID()
+ {
+ return serialVersionUID;
+ }
+
+ @Override
+ public int compareTo( ClassDefinition o )
+ {
+ return canonicalName.compareTo( o.getCanonicalName() );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( canonicalName == null ) ? 0 : canonicalName.hashCode() );
+ result = prime * result + Arrays.hashCode( checksum );
+ result = prime * result + (int) ( id ^ ( id >>> 32 ) );
+ result = prime * result + (int) ( serialVersionUID ^ ( serialVersionUID >>> 32 ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ InternalClassDefinition other = (InternalClassDefinition) obj;
+ if ( canonicalName == null )
+ {
+ if ( other.canonicalName != null )
+ return false;
+ }
+ else if ( !canonicalName.equals( other.canonicalName ) )
+ return false;
+ if ( !Arrays.equals( checksum, other.checksum ) )
+ return false;
+ if ( id != other.id )
+ return false;
+ if ( serialVersionUID != other.serialVersionUID )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "InternalClassDefinition [canonicalName=" + canonicalName + ", type=" + type + ", checksum="
+ + Arrays.toString( checksum ) + ", serialVersionUID=" + serialVersionUID + ", id=" + id + "]";
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinitionContainer.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinitionContainer.java
new file mode 100644
index 0000000..70549c7
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDefinitionContainer.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+
+import com.carrotsearch.hppc.LongObjectMap;
+import com.carrotsearch.hppc.LongObjectOpenHashMap;
+
+class InternalClassDefinitionContainer
+ implements ClassDefinitionContainer, Serializable
+{
+
+ private static final long serialVersionUID = -8496850178968208567L;
+
+ private final ClassDefinition[] classDefinitions;
+
+ private final LongObjectMap<ClassDefinition> classDefinitionsMappings;
+
+ // Serialization
+ private InternalClassDefinitionContainer( ClassDefinition[] classDefinitions )
+ {
+ this.classDefinitions = classDefinitions;
+ this.classDefinitionsMappings = new LongObjectOpenHashMap<ClassDefinition>();
+ }
+
+ InternalClassDefinitionContainer( Set<ClassDefinition> classDefinitions )
+ {
+ this.classDefinitions = classDefinitions.toArray( new ClassDefinition[classDefinitions.size()] );
+ this.classDefinitionsMappings = new LongObjectOpenHashMap<ClassDefinition>( classDefinitions.size() );
+ initMappings( this.classDefinitions );
+ }
+
+ @Override
+ public Collection<ClassDefinition> getClassDefinitions()
+ {
+ return Arrays.asList( Arrays.copyOf( classDefinitions, classDefinitions.length ) );
+ }
+
+ @Override
+ public Class<?> getTypeById( long id )
+ {
+ ClassDefinition classDefinition = classDefinitionsMappings.get( id );
+ return classDefinition != null ? classDefinition.getType() : null;
+ }
+
+ @Override
+ public ClassDefinition getClassDefinitionByCanonicalName( String canonicalName )
+ {
+ for ( ClassDefinition classDefinition : classDefinitions )
+ {
+ if ( classDefinition.getCanonicalName().equals( canonicalName ) )
+ {
+ return classDefinition;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ClassDefinition getClassDefinitionById( long id )
+ {
+ ClassDefinition classDefinition = classDefinitionsMappings.get( id );
+ return classDefinition != null ? classDefinition : null;
+ }
+
+ @Override
+ public ClassDefinition getClassDefinitionByType( Class<?> type )
+ {
+ if ( List.class.isAssignableFrom( type ) )
+ {
+ type = List.class;
+ }
+ else if ( Set.class.isAssignableFrom( type ) )
+ {
+ type = Set.class;
+ }
+ else if ( Map.class.isAssignableFrom( type ) )
+ {
+ type = Map.class;
+ }
+
+ for ( ClassDefinition classDefinition : classDefinitions )
+ {
+ if ( classDefinition.getType() == type )
+ {
+ return classDefinition;
+ }
+ }
+ return null;
+ }
+
+ private void initMappings( ClassDefinition[] classDefinitions )
+ {
+ for ( ClassDefinition classDefinition : classDefinitions )
+ {
+ classDefinitionsMappings.put( classDefinition.getId(), classDefinition );
+ }
+ }
+
+ Object writeReplace()
+ {
+ return new InternalClassDefinitionProxy( this );
+ }
+
+ /**
+ * SerializationProxy
+ */
+ private static class InternalClassDefinitionProxy
+ implements Externalizable
+ {
+
+ private static final long serialVersionUID = 3127589236225504001L;
+
+ private final InternalClassDefinitionContainer classDefinitionContainer;
+
+ private ClassDefinition[] classDefinitions;
+
+ @SuppressWarnings( "unused" )
+ public InternalClassDefinitionProxy()
+ {
+ this.classDefinitionContainer = null;
+ }
+
+ private InternalClassDefinitionProxy( InternalClassDefinitionContainer classDefinitionContainer )
+ {
+ this.classDefinitionContainer = classDefinitionContainer;
+ }
+
+ @Override
+ public void writeExternal( ObjectOutput out )
+ throws IOException
+ {
+ List<ClassDefinition> selectedClassDefinitions = new ArrayList<ClassDefinition>();
+ for ( ClassDefinition classDefinition : classDefinitionContainer.classDefinitions )
+ {
+ if ( classDefinition.getId() < 1000 )
+ {
+ continue;
+ }
+
+ selectedClassDefinitions.add( classDefinition );
+ }
+
+ out.writeInt( selectedClassDefinitions.size() );
+ for ( ClassDefinition classDefinition : selectedClassDefinitions )
+ {
+ final long id = classDefinition.getId();
+ final byte[] checksum = classDefinition.getChecksum();
+ final String canonicalName = classDefinition.getCanonicalName();
+ final long serialVersionUID = classDefinition.getSerialVersionUID();
+
+ out.writeLong( id );
+ out.writeUTF( canonicalName );
+ out.write( checksum );
+ out.writeLong( serialVersionUID );
+ }
+ }
+
+ @Override
+ public void readExternal( ObjectInput in )
+ throws IOException, ClassNotFoundException
+ {
+ int size = in.readInt();
+
+ classDefinitions = new ClassDefinition[size + ClassUtil.CLASS_DESCRIPTORS.length];
+ for ( int i = 0; i < ClassUtil.CLASS_DESCRIPTORS.length; i++ )
+ {
+ classDefinitions[i] = ClassUtil.CLASS_DESCRIPTORS[i];
+ }
+
+ for ( int i = 0; i < size; i++ )
+ {
+ final long id = in.readLong();
+ final String canonicalName = in.readUTF();
+ final byte[] checksum = new byte[20];
+ in.readFully( checksum );
+ final long serialVersionUID = in.readLong();
+
+ try
+ {
+ Class<?> type = ClassUtil.loadClass( canonicalName );
+ classDefinitions[i + ClassUtil.CLASS_DESCRIPTORS.length] =
+ new InternalClassDefinition( id, type, checksum, serialVersionUID );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new IOException( "Class " + canonicalName + " could not be loaded", e );
+ }
+ }
+ }
+
+ private Object readResolve()
+ {
+ InternalClassDefinitionContainer classDefinitionContainer =
+ new InternalClassDefinitionContainer( classDefinitions );
+ classDefinitionContainer.initMappings( classDefinitions );
+ return classDefinitionContainer;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDescriptor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDescriptor.java
new file mode 100644
index 0000000..e9cfd17
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalClassDescriptor.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class InternalClassDescriptor
+ implements ClassDescriptor
+{
+
+ private final Set<PropertyDescriptor> propertyDescriptors = new HashSet<PropertyDescriptor>();
+
+ private final Logger logger;
+
+ private final Class<?> type;
+
+ private ClassDefinition classDefinition;
+
+ private Marshaller marshaller;
+
+ public InternalClassDescriptor( Class<?> type, Logger logger )
+ {
+ this.type = type;
+ this.logger = logger;
+ }
+
+ @Override
+ public ClassDefinition getClassDefinition()
+ {
+ return classDefinition;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return type;
+ }
+
+ @Override
+ public List<PropertyDescriptor> getPropertyDescriptors()
+ {
+ return new ArrayList<PropertyDescriptor>( propertyDescriptors );
+ }
+
+ @Override
+ public Marshaller getMarshaller()
+ {
+ return marshaller;
+ }
+
+ public boolean push( PropertyDescriptor propertyDescriptor )
+ {
+ return propertyDescriptors.add( propertyDescriptor );
+ }
+
+ public void setMarshaller( Marshaller marshaller )
+ {
+ this.marshaller = marshaller;
+ }
+
+ public ClassDescriptor build( ClassDefinition[] classDefinitions )
+ {
+ for ( ClassDefinition classDefinition : classDefinitions )
+ {
+ if ( classDefinition.getType() == type )
+ {
+ this.classDefinition = classDefinition;
+ return this;
+ }
+ }
+
+ classDefinition = new InternalClassDefinition( getType(), getPropertyDescriptors(), logger );
+ return this;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( type == null ) ? 0 : type.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ InternalClassDescriptor other = (InternalClassDescriptor) obj;
+ if ( type == null )
+ {
+ if ( other.type != null )
+ return false;
+ }
+ else if ( !type.equals( other.type ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "InternalClassDescriptor [propertyDescriptors=" + propertyDescriptors + ", type=" + type
+ + ", classDefinition=" + classDefinition + ", marshaller=" + marshaller + "]";
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalDefinitionBuildingContext.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalDefinitionBuildingContext.java
new file mode 100644
index 0000000..3a654cc
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalDefinitionBuildingContext.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+
+public class InternalDefinitionBuildingContext
+ implements DefinitionBuildingContext
+{
+
+ private final PropertyDescriptorFactory propertyDescriptorFactory;
+
+ private final MarshallerStrategy marshallerStrategy;
+
+ public InternalDefinitionBuildingContext( MarshallerStrategy marshallerStrategy,
+ PropertyDescriptorFactory propertyDescriptorFactory )
+ {
+ this.marshallerStrategy = marshallerStrategy;
+ this.propertyDescriptorFactory = propertyDescriptorFactory;
+ }
+
+ @Override
+ public PropertyDescriptorFactory getPropertyDescriptorFactory()
+ {
+ return propertyDescriptorFactory;
+ }
+
+ @Override
+ public MarshallerStrategy getMarshallerStrategy()
+ {
+ return marshallerStrategy;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerContext.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerContext.java
new file mode 100644
index 0000000..c729890
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerContext.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.lang.reflect.Type;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+
+import com.carrotsearch.hppc.ObjectObjectMap;
+import com.carrotsearch.hppc.ObjectObjectOpenHashMap;
+
+public class InternalMarshallerContext
+ implements MarshallerContext
+{
+
+ private final MarshallerContext parentMarshallerContext;
+
+ private final ObjectObjectMap<Type, Marshaller> marshallers = new ObjectObjectOpenHashMap<Type, Marshaller>();
+
+ public InternalMarshallerContext()
+ {
+ this( null );
+ }
+
+ public InternalMarshallerContext( MarshallerContext parentMarshallerContext )
+ {
+ this.parentMarshallerContext = parentMarshallerContext;
+ }
+
+ @Override
+ public Marshaller getMarshaller( Type type )
+ {
+ Marshaller marshaller = marshallers.get( type );
+ if ( marshaller != null )
+ {
+ return marshaller;
+ }
+
+ if ( parentMarshallerContext != null )
+ {
+ return parentMarshallerContext.getMarshaller( type );
+ }
+
+ return null;
+ }
+
+ @Override
+ public void bindMarshaller( Type type, Marshaller marshaller )
+ {
+ marshallers.put( type, marshaller );
+ }
+
+ public ObjectObjectMap<Type, Marshaller> getInternalMap()
+ {
+ return marshallers;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerStrategy.java
new file mode 100644
index 0000000..7750f84
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalMarshallerStrategy.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.io.Externalizable;
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.Streamed;
+import org.apache.directmemory.lightning.internal.marshaller.BigDecimalMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.BigIntegerMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.BooleanArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.BooleanMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ByteArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ByteMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.CharacterArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.CharacterMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.DoubleArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.DoubleMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.EnumMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ExternalizableMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.FloatArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.FloatMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.IntegerArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.IntegerMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ListMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.LongArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.LongMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.MapMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.SerializableMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.SetMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ShortArrayMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.ShortMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.StreamedMarshaller;
+import org.apache.directmemory.lightning.internal.marshaller.StringMarshaller;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+
+public class InternalMarshallerStrategy
+ implements MarshallerStrategy
+{
+
+ public static final List<Marshaller> baseMarshaller;
+
+ static
+ {
+ List<Marshaller> marshallers = new ArrayList<Marshaller>();
+ marshallers.add( new StreamedMarshaller() );
+ marshallers.add( new ExternalizableMarshaller() );
+ marshallers.add( new BooleanMarshaller() );
+ marshallers.add( new ByteMarshaller() );
+ marshallers.add( new CharacterMarshaller() );
+ marshallers.add( new ShortMarshaller() );
+ marshallers.add( new IntegerMarshaller() );
+ marshallers.add( new LongMarshaller() );
+ marshallers.add( new FloatMarshaller() );
+ marshallers.add( new DoubleMarshaller() );
+ marshallers.add( new StringMarshaller() );
+ marshallers.add( new EnumMarshaller() );
+ marshallers.add( new ListMarshaller() );
+ marshallers.add( new SetMarshaller() );
+ marshallers.add( new MapMarshaller() );
+ marshallers.add( new BigIntegerMarshaller() );
+ marshallers.add( new BigDecimalMarshaller() );
+ marshallers.add( new BooleanArrayMarshaller() );
+ marshallers.add( new ByteArrayMarshaller() );
+ marshallers.add( new CharacterArrayMarshaller() );
+ marshallers.add( new ShortArrayMarshaller() );
+ marshallers.add( new IntegerArrayMarshaller() );
+ marshallers.add( new LongArrayMarshaller() );
+ marshallers.add( new FloatArrayMarshaller() );
+ marshallers.add( new DoubleArrayMarshaller() );
+
+ baseMarshaller = Collections.unmodifiableList( marshallers );
+ }
+
+ private final Marshaller externalizableMarshaller = new ExternalizableMarshaller();
+
+ private final Marshaller serializableMarshaller = new SerializableMarshaller();
+
+ private final Marshaller streamedMarshaller = new StreamedMarshaller();
+
+ @Override
+ public Marshaller getMarshaller( Type type, MarshallerContext marshallerContext )
+ {
+ return getMarshaller( type, marshallerContext, false );
+ }
+
+ @Override
+ public Marshaller getMarshaller( Type type, MarshallerContext marshallerContext, boolean baseMarshallersOnly )
+ {
+ Class<?> rawType = TypeUtil.getBaseType( type );
+ if ( Streamed.class.isAssignableFrom( rawType ) )
+ {
+ return streamedMarshaller;
+ }
+
+ if ( !baseMarshallersOnly && Externalizable.class.isAssignableFrom( rawType ) )
+ {
+ return externalizableMarshaller;
+ }
+
+ if ( marshallerContext != null )
+ {
+ Marshaller marshaller = marshallerContext.getMarshaller( type );
+ if ( marshaller != null )
+ {
+ return marshaller;
+ }
+ }
+
+ for ( Marshaller temp : baseMarshaller )
+ {
+ if ( temp.acceptType( rawType ) )
+ {
+ return temp;
+ }
+ }
+
+ if ( !baseMarshallersOnly && Serializable.class.isAssignableFrom( rawType ) && !rawType.isArray() )
+ {
+ return serializableMarshaller;
+ }
+
+ return null;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializationContext.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializationContext.java
new file mode 100644
index 0000000..b005214
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializationContext.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.lang.reflect.Type;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+import com.carrotsearch.hppc.LongObjectMap;
+import com.carrotsearch.hppc.LongObjectOpenHashMap;
+
+public class InternalSerializationContext
+ implements SerializationContext
+{
+
+ private final Map<Object, Long> referencesMarshall;
+
+ private final LongObjectMap<Object> referencesUnmarshall;
+
+ private final MarshallerContext marshallerContext = new InternalMarshallerContext();
+
+ private final ClassDefinitionContainer classDefinitionContainer;
+
+ private final SerializationStrategy serializationStrategy;
+
+ private final MarshallerStrategy marshallerStrategy;
+
+ private final ObjectInstantiatorFactory objectInstantiatorFactory;
+
+ private final ValueNullableEvaluator valueNullableEvaluator;
+
+ private long nextReferenceIdMarshall = 10000;
+
+ public InternalSerializationContext( ClassDefinitionContainer classDefinitionContainer,
+ SerializationStrategy serializationStrategy,
+ MarshallerStrategy marshallerStrategy,
+ ObjectInstantiatorFactory objectInstantiatorFactory,
+ ValueNullableEvaluator valueNullableEvaluator,
+ Map<Class<?>, Marshaller> definedMarshallers )
+ {
+
+ this.classDefinitionContainer = classDefinitionContainer;
+ this.serializationStrategy = serializationStrategy;
+ this.marshallerStrategy = marshallerStrategy;
+ this.objectInstantiatorFactory = objectInstantiatorFactory;
+ this.valueNullableEvaluator = valueNullableEvaluator;
+
+ for ( Entry<Class<?>, Marshaller> entry : definedMarshallers.entrySet() )
+ {
+ this.marshallerContext.bindMarshaller( entry.getKey(), entry.getValue() );
+ }
+
+ if ( serializationStrategy == SerializationStrategy.SizeOptimized )
+ {
+ this.referencesMarshall = new IdentityHashMap<Object, Long>();
+ this.referencesUnmarshall = new LongObjectOpenHashMap<Object>();
+ }
+ else
+ {
+ this.referencesMarshall = null;
+ this.referencesUnmarshall = null;
+ }
+ }
+
+ @Override
+ public ClassDefinitionContainer getClassDefinitionContainer()
+ {
+ return classDefinitionContainer;
+ }
+
+ @Override
+ public SerializationStrategy getSerializationStrategy()
+ {
+ return serializationStrategy;
+ }
+
+ @Override
+ public ObjectInstantiatorFactory getObjectInstantiatorFactory()
+ {
+ return objectInstantiatorFactory;
+ }
+
+ @Override
+ public long findReferenceIdByObject( Object instance )
+ {
+ Long referenceId = referencesMarshall.get( instance );
+ if ( referenceId == null )
+ {
+ return -1;
+ }
+ return referenceId;
+ }
+
+ @Override
+ public long putMarshalledInstance( Object instance )
+ {
+ long newId = getNextReferenceIdMarshall();
+ referencesMarshall.put( instance, newId );
+ return newId;
+ }
+
+ @Override
+ public Object findObjectByReferenceId( long referenceId )
+ {
+ return referencesUnmarshall.get( referenceId );
+ }
+
+ @Override
+ public boolean containsReferenceId( long referenceId )
+ {
+ return referencesUnmarshall.containsKey( referenceId );
+ }
+
+ @Override
+ public long putUnmarshalledInstance( long refrenceId, Object instance )
+ {
+ referencesUnmarshall.put( refrenceId, instance );
+ return refrenceId;
+ }
+
+ @Override
+ public Marshaller findMarshaller( Type type )
+ {
+ Class<?> rawType = TypeUtil.getBaseType( type );
+ Marshaller marshaller = marshallerStrategy.getMarshaller( rawType, marshallerContext, false );
+
+ if ( marshaller instanceof TypeBindableMarshaller )
+ {
+ Type[] typeArguments = TypeUtil.getTypeArgument( type );
+ marshaller = ( (TypeBindableMarshaller) marshaller ).bindType( typeArguments );
+ }
+
+ return marshaller;
+ }
+
+ public Map<Object, Long> getReferencesMarshall()
+ {
+ return referencesMarshall;
+ }
+
+ public LongObjectMap<Object> getReferencesUnmarshall()
+ {
+ return referencesUnmarshall;
+ }
+
+ public long getNextReferenceIdMarshall()
+ {
+ long newId = nextReferenceIdMarshall++;
+ return newId;
+ }
+
+ @Override
+ public ValueNullableEvaluator getValueNullableEvaluator()
+ {
+ return valueNullableEvaluator;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializer.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializer.java
new file mode 100644
index 0000000..c3811b8
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializer.java
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.directmemory.lightning.ClassComparisonStrategy;
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.exceptions.ClassDefinitionInconsistentException;
+import org.apache.directmemory.lightning.exceptions.SerializerExecutionException;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.generator.BytecodeMarshallerGenerator;
+import org.apache.directmemory.lightning.internal.generator.MarshallerGenerator;
+import org.apache.directmemory.lightning.internal.io.BufferInputStream;
+import org.apache.directmemory.lightning.internal.io.BufferOutputStream;
+import org.apache.directmemory.lightning.internal.io.ReaderInputStream;
+import org.apache.directmemory.lightning.internal.io.WriterOutputStream;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+class InternalSerializer
+ implements ClassDescriptorAwareSerializer
+{
+
+ private final AtomicReference<ClassDefinitionContainer> classDefinitionContainer =
+ new AtomicReference<ClassDefinitionContainer>();
+
+ private final MarshallerGenerator marshallerGenerator = new BytecodeMarshallerGenerator();
+
+ private final ObjectInstantiatorFactory objectInstantiatorFactory;
+
+ private final ClassComparisonStrategy classComparisonStrategy;
+
+ private final Map<Class<?>, ClassDescriptor> classDescriptors;
+
+ private final SerializationStrategy serializationStrategy;
+
+ private final Map<Class<?>, Marshaller> definedMarshallers;
+
+ private final MarshallerStrategy marshallerStrategy;
+
+ private final ValueNullableEvaluator valueNullableEvaluator;
+
+ InternalSerializer( ClassDefinitionContainer classDefinitionContainer, SerializationStrategy serializationStrategy,
+ ClassComparisonStrategy classComparisonStrategy,
+ Map<Class<?>, ClassDescriptor> classDescriptors, Map<Class<?>, Marshaller> marshallers,
+ ObjectInstantiatorFactory objectInstantiatorFactory, Logger logger,
+ MarshallerStrategy marshallerStrategy, File debugCacheDirectory,
+ ValueNullableEvaluator valueNullableEvaluator )
+ {
+
+ this.classDefinitionContainer.set( classDefinitionContainer );
+ this.classComparisonStrategy = classComparisonStrategy;
+ this.classDescriptors = Collections.unmodifiableMap( classDescriptors );
+ this.serializationStrategy = serializationStrategy;
+ this.valueNullableEvaluator = valueNullableEvaluator;
+
+ for ( ClassDescriptor classDescriptor : classDescriptors.values() )
+ {
+ if ( classDescriptor instanceof InternalClassDescriptor && classDescriptor.getMarshaller() == null )
+ {
+ Marshaller marshaller =
+ marshallerGenerator.generateMarshaller( classDescriptor.getType(),
+ classDescriptor.getPropertyDescriptors(), marshallers,
+ this, serializationStrategy, objectInstantiatorFactory,
+ debugCacheDirectory );
+
+ ( (InternalClassDescriptor) classDescriptor ).setMarshaller( marshaller );
+ marshallers.put( classDescriptor.getType(), marshaller );
+ }
+ }
+
+ this.definedMarshallers = marshallers;
+ this.marshallerStrategy = marshallerStrategy;
+ this.objectInstantiatorFactory = objectInstantiatorFactory;
+ }
+
+ @Override
+ public ClassDefinitionContainer getClassDefinitionContainer()
+ {
+ return classDefinitionContainer.get();
+ }
+
+ @Override
+ public void setClassDefinitionContainer( ClassDefinitionContainer classDefinitionContainer )
+ {
+ // Pre-check if checksums of remote classes passing
+ ClassDefinitionContainer oldClassDefinitionContainer = getClassDefinitionContainer();
+ consistencyCheckClassChecksums( oldClassDefinitionContainer, classDefinitionContainer );
+
+ // Set new ClassDefinitionContainer if checking succeed
+ this.classDefinitionContainer.set( classDefinitionContainer );
+ }
+
+ @Override
+ public <V> void serialize( V value, DataOutput dataOutput )
+ {
+ try
+ {
+ SerializationContext serializationContext =
+ new InternalSerializationContext( classDefinitionContainer.get(), serializationStrategy,
+ marshallerStrategy, objectInstantiatorFactory,
+ valueNullableEvaluator, definedMarshallers );
+
+ Class<?> type = value.getClass();
+ ClassDescriptor classDescriptor = findClassDescriptor( type );
+ Marshaller marshaller = classDescriptor.getMarshaller();
+ PropertyDescriptor pd = new CheatPropertyDescriptor( "serialize", classDescriptor.getType(), marshaller );
+
+ dataOutput.writeLong( classDescriptor.getClassDefinition().getId() );
+ marshaller.marshall( value, pd, dataOutput, serializationContext );
+ }
+ catch ( IOException e )
+ {
+ throw new SerializerExecutionException( "Error while serializing value", e );
+ }
+ }
+
+ @Override
+ public <V> void serialize( V value, OutputStream outputStream )
+ {
+ if ( outputStream instanceof DataOutput )
+ serialize( value, (DataOutput) outputStream );
+ else
+ serialize( value, (DataOutput) new DataOutputStream( outputStream ) );
+ }
+
+ @Override
+ public <V> void serialize( V value, Writer writer )
+ {
+ serialize( value, (DataOutput) new DataOutputStream( new WriterOutputStream( writer, "UTF-8" ) ) );
+ }
+
+ @Override
+ public <V> void serialize( V value, ByteBuffer buffer )
+ {
+ serialize( value, (DataOutput) new DataOutputStream( new BufferOutputStream( buffer ) ) );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V deserialize( DataInput dataInput )
+ {
+ try
+ {
+ SerializationContext serializationContext =
+ new InternalSerializationContext( classDefinitionContainer.get(), serializationStrategy,
+ marshallerStrategy, objectInstantiatorFactory,
+ valueNullableEvaluator, definedMarshallers );
+
+ long typeId = dataInput.readLong();
+ Class<?> clazz = classDefinitionContainer.get().getTypeById( typeId );
+ ClassDescriptor classDescriptor = findClassDescriptor( clazz );
+ Marshaller marshaller = classDescriptor.getMarshaller();
+ PropertyDescriptor pd = new CheatPropertyDescriptor( "serialize", classDescriptor.getType(), marshaller );
+
+ return (V) marshaller.unmarshall( pd, dataInput, serializationContext );
+ }
+ catch ( IOException e )
+ {
+ throw new SerializerExecutionException( "Error while deserializing value", e );
+ }
+ }
+
+ @Override
+ public <V> V deserialize( InputStream inputStream )
+ {
+ if ( inputStream instanceof DataInput )
+ {
+ return deserialize( (DataInput) inputStream );
+ }
+
+ return deserialize( (DataInput) new DataInputStream( inputStream ) );
+ }
+
+ @Override
+ public <V> V deserialize( Reader reader )
+ {
+ return deserialize( (DataInput) new DataInputStream( new ReaderInputStream( reader, "UTF-8" ) ) );
+ }
+
+ @Override
+ public <V> V deserialize( ByteBuffer buffer )
+ {
+ return deserialize( (DataInput) new DataInputStream( new BufferInputStream( buffer ) ) );
+ }
+
+ @Override
+ public ClassDescriptor findClassDescriptor( Class<?> type )
+ {
+ return classDescriptors.get( type );
+ }
+
+ private void consistencyCheckClassChecksums( ClassDefinitionContainer oldClassDefinitionContainer,
+ ClassDefinitionContainer classDefinitionContainer )
+ {
+ for ( ClassDefinition classDefinition : classDefinitionContainer.getClassDefinitions() )
+ {
+ ClassDefinition oldClassDefinition =
+ oldClassDefinitionContainer.getClassDefinitionByCanonicalName( classDefinition.getCanonicalName() );
+ if ( oldClassDefinition == null )
+ {
+ throw new ClassDefinitionInconsistentException( "No ClassDefinition for type "
+ + classDefinition.getCanonicalName() + " was found" );
+ }
+
+ if ( classComparisonStrategy != ClassComparisonStrategy.SkipComparison )
+ {
+ if ( classComparisonStrategy == ClassComparisonStrategy.SerialVersionUID )
+ {
+ long serialVersionUID = classDefinition.getSerialVersionUID();
+ long oldSerialVersionUID = oldClassDefinition.getSerialVersionUID();
+ if ( serialVersionUID != oldSerialVersionUID )
+ {
+ throw new ClassDefinitionInconsistentException( "SerialVersionUID of type "
+ + classDefinition.getCanonicalName() + " is not constistent" );
+ }
+ }
+ else
+ {
+ byte[] checksum = classDefinition.getChecksum();
+ byte[] oldChecksum = oldClassDefinition.getChecksum();
+ if ( !Arrays.equals( checksum, oldChecksum ) )
+ {
+ throw new ClassDefinitionInconsistentException( "Signature checksum of type "
+ + classDefinition.getCanonicalName() + " is not constistent" );
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializerCreator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializerCreator.java
new file mode 100644
index 0000000..a186123
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/InternalSerializerCreator.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.Stack;
+
+import org.apache.directmemory.lightning.ClassComparisonStrategy;
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
+import org.apache.directmemory.lightning.generator.DefinitionVisitor;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.beans.InternalPropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisSerializer;
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.logging.LoggerAdapter;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.apache.directmemory.lightning.metadata.ValueNullableEvaluator;
+
+public final class InternalSerializerCreator
+{
+
+ private final Map<Class<?>, InternalClassDescriptor> classDescriptors =
+ new HashMap<Class<?>, InternalClassDescriptor>();
+
+ private final List<SerializerDefinition> serializerDefinitions = new ArrayList<SerializerDefinition>();
+
+ private final Map<Class<?>, Marshaller> marshallers = new HashMap<Class<?>, Marshaller>();
+
+ private final ObjectInstantiatorFactory objectInstantiatorFactory = new ObjenesisSerializer( true );
+
+ private ValueNullableEvaluator valueNullableEvaluator;
+
+ private SerializationStrategy serializationStrategy = SerializationStrategy.SpeedOptimized;
+
+ private Class<? extends Annotation> attributeAnnotation = Attribute.class;
+
+ private ClassComparisonStrategy classComparisonStrategy = ClassComparisonStrategy.LightningChecksum;
+
+ private File debugCacheDirectory = null;
+
+ private Logger logger = new LoggerAdapter();
+
+ public InternalSerializerCreator()
+ {
+ }
+
+ public InternalSerializerCreator addSerializerDefinitions( Iterable<? extends SerializerDefinition> serializerDefinitions )
+ {
+ for ( SerializerDefinition serializerDefinition : serializerDefinitions )
+ {
+ this.serializerDefinitions.add( serializerDefinition );
+ }
+
+ return this;
+ }
+
+ public InternalSerializerCreator setDebugCacheDirectory( File debugCacheDirectory )
+ {
+ this.debugCacheDirectory = debugCacheDirectory;
+ return this;
+ }
+
+ public InternalSerializerCreator setLogger( Logger logger )
+ {
+ this.logger = logger;
+ return this;
+ }
+
+ public InternalSerializerCreator setAttributeAnnotation( Class<? extends Annotation> attributeAnnotation )
+ {
+ this.attributeAnnotation = attributeAnnotation;
+ return this;
+ }
+
+ public InternalSerializerCreator setSerializationStrategy( SerializationStrategy serializationStrategy )
+ {
+ this.serializationStrategy = serializationStrategy;
+ return this;
+ }
+
+ public InternalSerializerCreator setClassComparisonStrategy( ClassComparisonStrategy classComparisonStrategy )
+ {
+ this.classComparisonStrategy = classComparisonStrategy;
+ return this;
+ }
+
+ public InternalSerializerCreator setValueNullableEvaluator( ValueNullableEvaluator valueNullableEvaluator )
+ {
+ this.valueNullableEvaluator = valueNullableEvaluator;
+ return this;
+ }
+
+ public Serializer build()
+ {
+ PropertyDescriptorFactory propertyDescriptorFactory = new InternalPropertyDescriptorFactory( logger );
+ MarshallerStrategy marshallerStrategy = new InternalMarshallerStrategy();
+ DefinitionBuildingContext definitionBuildingContext =
+ new InternalDefinitionBuildingContext( marshallerStrategy, propertyDescriptorFactory );
+
+ DefinitionVisitor definitionVisitor = new InternalDefinitionVisitor();
+ for ( SerializerDefinition serializerDefinition : serializerDefinitions )
+ {
+ serializerDefinition.configure( definitionBuildingContext, objectInstantiatorFactory );
+ serializerDefinition.acceptVisitor( definitionVisitor );
+ }
+
+ Set<ClassDefinition> classDefinitions =
+ new HashSet<ClassDefinition>( Arrays.asList( ClassUtil.CLASS_DESCRIPTORS ) );
+ for ( InternalClassDescriptor classDescriptor : classDescriptors.values() )
+ {
+ classDefinitions.add( classDescriptor.build( ClassUtil.CLASS_DESCRIPTORS ).getClassDefinition() );
+ }
+
+ Map<Class<?>, ClassDescriptor> cleanedClassDescriptors =
+ new HashMap<Class<?>, ClassDescriptor>( classDescriptors.size() );
+ for ( Entry<Class<?>, InternalClassDescriptor> entry : classDescriptors.entrySet() )
+ {
+ cleanedClassDescriptors.put( entry.getKey(), entry.getValue() );
+ }
+
+ return new InternalSerializer( new InternalClassDefinitionContainer( classDefinitions ), serializationStrategy,
+ classComparisonStrategy, cleanedClassDescriptors, marshallers,
+ objectInstantiatorFactory, logger, marshallerStrategy, debugCacheDirectory,
+ valueNullableEvaluator );
+ }
+
+ private InternalClassDescriptor findClassDescriptor( Class<?> type )
+ {
+ InternalClassDescriptor classDescriptor = classDescriptors.get( type );
+ if ( classDescriptor == null )
+ {
+ classDescriptor = new InternalClassDescriptor( type, logger );
+ classDescriptors.put( type, classDescriptor );
+ }
+
+ return classDescriptor;
+ }
+
+ private class InternalDefinitionVisitor
+ implements DefinitionVisitor
+ {
+
+ private final Stack<Class<? extends Annotation>> attributeAnnotation = new Stack<Class<? extends Annotation>>();
+
+ @Override
+ public void visitSerializerDefinition( SerializerDefinition serializerDefinition )
+ {
+ // If at top level definition just add the base annotation
+ if ( attributeAnnotation.size() == 0 )
+ {
+ if ( InternalSerializerCreator.this.attributeAnnotation == null )
+ {
+ attributeAnnotation.push( Attribute.class );
+ }
+ else
+ {
+ attributeAnnotation.push( InternalSerializerCreator.this.attributeAnnotation );
+ }
+ }
+ else
+ {
+ Class<? extends Annotation> annotation = attributeAnnotation.peek();
+ attributeAnnotation.push( annotation );
+ }
+ }
+
+ @Override
+ public void visitAttributeAnnotation( Class<? extends Annotation> attributeAnnotation )
+ {
+ // Remove last element and replace it with the real annotation to
+ // use right from that moment
+ this.attributeAnnotation.pop();
+ this.attributeAnnotation.push( attributeAnnotation );
+ }
+
+ @Override
+ public void visitClassDefine( Type type, Marshaller marshaller )
+ {
+ Class<?> rawType = TypeUtil.getBaseType( type );
+ InternalClassDescriptor classDescriptor = findClassDescriptor( rawType );
+ classDescriptor.setMarshaller( marshaller );
+
+ marshallers.put( rawType, marshaller );
+ }
+
+ @Override
+ public void visitAnnotatedAttribute( PropertyDescriptor propertyDescriptor, Marshaller marshaller )
+ {
+ InternalClassDescriptor classDescriptor = findClassDescriptor( propertyDescriptor.getDefinedClass() );
+
+ if ( logger.isTraceEnabled() )
+ {
+ logger.trace( "Found property " + propertyDescriptor.getName() + " ("
+ + propertyDescriptor.getInternalSignature() + ") on type "
+ + propertyDescriptor.getDefinedClass().getCanonicalName() );
+ }
+
+ classDescriptor.push( propertyDescriptor );
+ }
+
+ @Override
+ public void visitPropertyDescriptor( PropertyDescriptor propertyDescriptor, Marshaller marshaller )
+ {
+ InternalClassDescriptor classDescriptor = findClassDescriptor( propertyDescriptor.getDefinedClass() );
+
+ if ( logger.isTraceEnabled() )
+ {
+ logger.trace( "Found property " + propertyDescriptor.getName() + " ("
+ + propertyDescriptor.getInternalSignature() + ") on type "
+ + propertyDescriptor.getDefinedClass().getCanonicalName() );
+ }
+
+ classDescriptor.push( propertyDescriptor );
+ }
+
+ @Override
+ public void visitFinalizeSerializerDefinition( SerializerDefinition serializerDefinition )
+ {
+ // Clean this level up
+ this.attributeAnnotation.pop();
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractPropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractPropertyAccessor.java
new file mode 100644
index 0000000..4860e3b
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractPropertyAccessor.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+abstract class AbstractPropertyAccessor
+ implements PropertyAccessor
+{
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractValuePropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractValuePropertyAccessor.java
new file mode 100644
index 0000000..7dbe2ea
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/AbstractValuePropertyAccessor.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import org.apache.directmemory.lightning.metadata.ValuePropertyAccessor;
+
+public abstract class AbstractValuePropertyAccessor
+ extends AbstractPropertyAccessor
+ implements ValuePropertyAccessor
+{
+
+ @Override
+ public boolean isArrayType()
+ {
+ return false;
+ }
+
+ @Override
+ public void writeShort( Object instance, short value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeLong( Object instance, long value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeInt( Object instance, int value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeFloat( Object instance, float value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeDouble( Object instance, double value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeChar( Object instance, char value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeByte( Object instance, byte value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public void writeBoolean( Object instance, boolean value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public short readShort( Object instance )
+ {
+ return (Short) readObject( instance );
+ }
+
+ @Override
+ public long readLong( Object instance )
+ {
+ return (Long) readObject( instance );
+ }
+
+ @Override
+ public int readInt( Object instance )
+ {
+ return (Integer) readObject( instance );
+ }
+
+ @Override
+ public float readFloat( Object instance )
+ {
+ return (Float) readObject( instance );
+ }
+
+ @Override
+ public double readDouble( Object instance )
+ {
+ return (Double) readObject( instance );
+ }
+
+ @Override
+ public char readChar( Object instance )
+ {
+ return (Character) readObject( instance );
+ }
+
+ @Override
+ public byte readByte( Object instance )
+ {
+ return (Byte) readObject( instance );
+ }
+
+ @Override
+ public boolean readBoolean( Object instance )
+ {
+ return (Boolean) readObject( instance );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldArrayPropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldArrayPropertyAccessor.java
new file mode 100644
index 0000000..6740168
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldArrayPropertyAccessor.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+
+import org.apache.directmemory.lightning.metadata.AccessorType;
+import org.apache.directmemory.lightning.metadata.ArrayPropertyAccessor;
+
+public abstract class FieldArrayPropertyAccessor
+ extends FieldValuePropertyAccessor
+ implements ArrayPropertyAccessor
+{
+
+ private final Field field;
+
+ private final Class<?> definedClass;
+
+ protected FieldArrayPropertyAccessor( Field field, Class<?> definedClass )
+ {
+ super( field, definedClass );
+ this.field = field;
+ this.definedClass = definedClass;
+ }
+
+ @Override
+ public boolean isArrayType()
+ {
+ return true;
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return definedClass;
+ }
+
+ @Override
+ public AccessorType getAccessorType()
+ {
+ return AccessorType.Field;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return field.getType();
+ }
+
+ @Override
+ protected Field getField()
+ {
+ return field;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldValuePropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldValuePropertyAccessor.java
new file mode 100644
index 0000000..4e50831
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/FieldValuePropertyAccessor.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+
+import org.apache.directmemory.lightning.metadata.AccessorType;
+
+public abstract class FieldValuePropertyAccessor
+ extends AbstractValuePropertyAccessor
+{
+
+ private final Field field;
+
+ private final Class<?> definedClass;
+
+ protected FieldValuePropertyAccessor( Field field, Class<?> definedClass )
+ {
+ this.field = field;
+ this.definedClass = definedClass;
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return definedClass;
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return field.getDeclaringClass();
+ }
+
+ @Override
+ public AccessorType getAccessorType()
+ {
+ return AccessorType.Field;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return field.getType();
+ }
+
+ protected Field getField()
+ {
+ return field;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptor.java
new file mode 100644
index 0000000..83e0ceb
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptor.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.apache.directmemory.lightning.internal.util.StringUtil;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+class InternalPropertyDescriptor
+ implements PropertyDescriptor
+{
+
+ private final String name;
+
+ private final String propertyName;
+
+ private final String internalSignature;
+
+ private final String declaringCanonicalClassname;
+
+ private final Class<?> definedClass;
+
+ private final Class<?> declaringClass;
+
+ private final PropertyAccessor propertyAccessor;
+
+ private final Annotation[] annotations;
+
+ private final Marshaller marshaller;
+
+ InternalPropertyDescriptor( String propertyName, Marshaller marshaller, Annotation[] annotations,
+ PropertyAccessor propertyAccessor )
+ {
+ this.name = StringUtil.toUpperCamelCase( propertyName );
+ this.propertyName = propertyName;
+ this.propertyAccessor = propertyAccessor;
+ this.marshaller = marshaller;
+ this.declaringCanonicalClassname = propertyAccessor.getType().getCanonicalName();
+ this.internalSignature = BeanUtil.buildInternalSignature( propertyName, propertyAccessor );
+ this.annotations = Arrays.copyOf( annotations, annotations.length );
+ this.definedClass = propertyAccessor.getDefinedClass();
+ this.declaringClass = propertyAccessor.getDeclaringClass();
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return definedClass;
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return declaringClass;
+ }
+
+ @Override
+ public PropertyAccessor getPropertyAccessor()
+ {
+ return propertyAccessor;
+ }
+
+ @Override
+ public Annotation[] getAnnotations()
+ {
+ return Arrays.copyOf( annotations, annotations.length );
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public String getPropertyName()
+ {
+ return propertyName;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return propertyAccessor.getType();
+ }
+
+ @Override
+ public String getInternalSignature()
+ {
+ return internalSignature;
+ }
+
+ @Override
+ public Marshaller getMarshaller()
+ {
+ return marshaller;
+ }
+
+ @Override
+ public int compareTo( PropertyDescriptor o )
+ {
+ return propertyName.compareTo( o.getPropertyName() );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( annotations );
+ result =
+ prime * result + ( ( declaringCanonicalClassname == null ) ? 0 : declaringCanonicalClassname.hashCode() );
+ result = prime * result + ( ( declaringClass == null ) ? 0 : declaringClass.hashCode() );
+ result = prime * result + ( ( definedClass == null ) ? 0 : definedClass.hashCode() );
+ result = prime * result + ( ( internalSignature == null ) ? 0 : internalSignature.hashCode() );
+ result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
+ result = prime * result + ( ( propertyName == null ) ? 0 : propertyName.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ InternalPropertyDescriptor other = (InternalPropertyDescriptor) obj;
+ if ( !Arrays.equals( annotations, other.annotations ) )
+ return false;
+ if ( declaringCanonicalClassname == null )
+ {
+ if ( other.declaringCanonicalClassname != null )
+ return false;
+ }
+ else if ( !declaringCanonicalClassname.equals( other.declaringCanonicalClassname ) )
+ return false;
+ if ( declaringClass == null )
+ {
+ if ( other.declaringClass != null )
+ return false;
+ }
+ else if ( !declaringClass.equals( other.declaringClass ) )
+ return false;
+ if ( definedClass == null )
+ {
+ if ( other.definedClass != null )
+ return false;
+ }
+ else if ( !definedClass.equals( other.definedClass ) )
+ return false;
+ if ( internalSignature == null )
+ {
+ if ( other.internalSignature != null )
+ return false;
+ }
+ else if ( !internalSignature.equals( other.internalSignature ) )
+ return false;
+ if ( name == null )
+ {
+ if ( other.name != null )
+ return false;
+ }
+ else if ( !name.equals( other.name ) )
+ return false;
+ if ( propertyName == null )
+ {
+ if ( other.propertyName != null )
+ return false;
+ }
+ else if ( !propertyName.equals( other.propertyName ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "InternalPropertyDescriptor [name=" + name + ", propertyName=" + propertyName + ", internalSignature="
+ + internalSignature + ", declaringCanonicalClassname=" + declaringCanonicalClassname + ", definedClass="
+ + definedClass + ", declaringClass=" + declaringClass + ", propertyAccessor=" + propertyAccessor
+ + ", annotations=" + Arrays.toString( annotations ) + ", marshaller=" + marshaller + "]";
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptorFactory.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptorFactory.java
new file mode 100644
index 0000000..f206ca9
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/InternalPropertyDescriptorFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class InternalPropertyDescriptorFactory
+ implements PropertyDescriptorFactory
+{
+
+ private final PropertyAccessorStrategy propertyAccessorStrategy;
+
+ public InternalPropertyDescriptorFactory( Logger logger )
+ {
+ propertyAccessorStrategy = new PropertyAccessorStrategy( logger );
+ }
+
+ @Override
+ public PropertyDescriptor byMethod( Method method, Marshaller marshaller, Class<?> definedClass )
+ {
+ PropertyAccessor propertyAccessor = propertyAccessorStrategy.byMethod( method, definedClass );
+ String propertyName = BeanUtil.buildPropertyName( method );
+ return new InternalPropertyDescriptor( propertyName, marshaller, method.getAnnotations(), propertyAccessor );
+ }
+
+ @Override
+ public PropertyDescriptor byField( Field field, Marshaller marshaller, Class<?> definedClass )
+ {
+ PropertyAccessor propertyAccessor = propertyAccessorStrategy.byField( field, definedClass );
+ return new InternalPropertyDescriptor( field.getName(), marshaller, field.getAnnotations(), propertyAccessor );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodArrayPropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodArrayPropertyAccessor.java
new file mode 100644
index 0000000..7ebe96e
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodArrayPropertyAccessor.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.metadata.AccessorType;
+import org.apache.directmemory.lightning.metadata.ArrayPropertyAccessor;
+
+public abstract class MethodArrayPropertyAccessor
+ extends AbstractValuePropertyAccessor
+ implements ArrayPropertyAccessor
+{
+
+ private final Method setter;
+
+ private final Method getter;
+
+ private final Class<?> definedClass;
+
+ protected MethodArrayPropertyAccessor( Method setter, Method getter, Class<?> definedClass )
+ {
+ this.setter = setter;
+ this.getter = getter;
+ this.definedClass = definedClass;
+ }
+
+ @Override
+ public boolean isArrayType()
+ {
+ return true;
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return definedClass;
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return getter.getDeclaringClass();
+ }
+
+ @Override
+ public AccessorType getAccessorType()
+ {
+ return AccessorType.Method;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return getter.getReturnType();
+ }
+
+ protected Method getGetterMethod()
+ {
+ return getter;
+ }
+
+ protected Method getSetterMethod()
+ {
+ return setter;
+ }
+
+ @Override
+ public void writeBoolean( Object instance, int index, boolean value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public boolean readBoolean( Object instance, int index )
+ {
+ return (Boolean) readObject( instance, index );
+ }
+
+ @Override
+ public void writeByte( Object instance, int index, byte value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public byte readByte( Object instance, int index )
+ {
+ return (Byte) readObject( instance, index );
+ }
+
+ @Override
+ public void writeChar( Object instance, int index, char value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public char readChar( Object instance, int index )
+ {
+ return (Character) readObject( instance, index );
+ }
+
+ @Override
+ public void writeShort( Object instance, int index, short value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public short readShort( Object instance, int index )
+ {
+ return (Short) readObject( instance, index );
+ }
+
+ @Override
+ public void writeInt( Object instance, int index, int value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public int readInt( Object instance, int index )
+ {
+ return (Integer) readObject( instance, index );
+ }
+
+ @Override
+ public void writeLong( Object instance, int index, long value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public long readLong( Object instance, int index )
+ {
+ return (Long) readObject( instance, index );
+ }
+
+ @Override
+ public void writeFloat( Object instance, int index, float value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public float readFloat( Object instance, int index )
+ {
+ return (Float) readObject( instance, index );
+ }
+
+ @Override
+ public void writeDouble( Object instance, int index, double value )
+ {
+ writeObject( instance, index, value );
+ }
+
+ @Override
+ public double readDouble( Object instance, int index )
+ {
+ return (Double) readObject( instance, index );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodValuePropertyAccessor.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodValuePropertyAccessor.java
new file mode 100644
index 0000000..7657c41
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/MethodValuePropertyAccessor.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.metadata.AccessorType;
+
+public abstract class MethodValuePropertyAccessor
+ extends AbstractValuePropertyAccessor
+{
+
+ private final Method setter;
+
+ private final Method getter;
+
+ private final Class<?> definedClass;
+
+ protected MethodValuePropertyAccessor( Method setter, Method getter, Class<?> definedClass )
+ {
+ this.setter = setter;
+ this.getter = getter;
+ this.definedClass = definedClass;
+ }
+
+ @Override
+ public Class<?> getDefinedClass()
+ {
+ return definedClass;
+ }
+
+ @Override
+ public Class<?> getDeclaringClass()
+ {
+ return getter.getDeclaringClass();
+ }
+
+ @Override
+ public AccessorType getAccessorType()
+ {
+ return AccessorType.Method;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return getter.getReturnType();
+ }
+
+ protected Method getGetterMethod()
+ {
+ return getter;
+ }
+
+ protected Method getSetterMethod()
+ {
+ return setter;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorFactory.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorFactory.java
new file mode 100644
index 0000000..ff447c3
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+public interface PropertyAccessorFactory
+{
+
+ PropertyAccessor fieldAccess( Field field, Class<?> definedClass );
+
+ PropertyAccessor methodAccess( Method method, Class<?> definedClass );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorStrategy.java
new file mode 100644
index 0000000..ca276ce
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/PropertyAccessorStrategy.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.internal.util.InternalUtil;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+public class PropertyAccessorStrategy
+{
+
+ private final PropertyAccessorFactory reflectionPropertyAccessorFactory = new ReflectionPropertyAccessorFactory();
+
+ private final PropertyAccessorFactory reflectASMPropertyAccessorFactory = new ReflectASMPropertyAccessorFactory();
+
+ private final PropertyAccessorFactory sunUnsafePropertyAccessorFactory;
+
+ private final Logger logger;
+
+ PropertyAccessorStrategy( Logger logger )
+ {
+ this.logger = logger.getChildLogger( getClass() );
+
+ PropertyAccessorFactory factory = null;
+ if ( InternalUtil.isUnsafeAvailable() )
+ {
+ factory = InternalUtil.buildSunUnsafePropertyAccessor();
+ this.logger.trace( "Found sun.misc.Unsafe" );
+ }
+ sunUnsafePropertyAccessorFactory = factory;
+ }
+
+ PropertyAccessor byField( Field field, Class<?> definedClass )
+ {
+ PropertyAccessor propertyAccessor = null;
+ if ( sunUnsafePropertyAccessorFactory != null )
+ {
+ propertyAccessor = sunUnsafePropertyAccessorFactory.fieldAccess( field, definedClass );
+ }
+
+ if ( propertyAccessor == null )
+ {
+ propertyAccessor = reflectASMPropertyAccessorFactory.fieldAccess( field, definedClass );
+ }
+
+ if ( propertyAccessor != null )
+ {
+ return propertyAccessor;
+ }
+
+ return reflectionPropertyAccessorFactory.fieldAccess( field, definedClass );
+ }
+
+ PropertyAccessor byMethod( Method method, Class<?> definedClass )
+ {
+ PropertyAccessor propertyAccessor = reflectASMPropertyAccessorFactory.methodAccess( method, definedClass );
+ if ( propertyAccessor != null )
+ {
+ return propertyAccessor;
+ }
+
+ return reflectionPropertyAccessorFactory.methodAccess( method, definedClass );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectASMPropertyAccessorFactory.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectASMPropertyAccessorFactory.java
new file mode 100644
index 0000000..892d0ec
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectASMPropertyAccessorFactory.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+import com.esotericsoftware.reflectasm.FieldAccess;
+import com.esotericsoftware.reflectasm.MethodAccess;
+
+public class ReflectASMPropertyAccessorFactory
+ implements PropertyAccessorFactory
+{
+
+ private final Map<Class<?>, MethodAccess> methodAccessCache = new HashMap<Class<?>, MethodAccess>();
+
+ private final Map<Class<?>, FieldAccess> fieldAccessCache = new HashMap<Class<?>, FieldAccess>();
+
+ @Override
+ public PropertyAccessor fieldAccess( Field field, Class<?> definedClass )
+ {
+ if ( field.getType().isArray() )
+ {
+ return null;
+ }
+
+ try
+ {
+ return buildForField( field, definedClass );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ // If field is not public
+ return null;
+ }
+ }
+
+ @Override
+ public PropertyAccessor methodAccess( Method method, Class<?> definedClass )
+ {
+ if ( method.getReturnType().isArray() )
+ {
+ return null;
+ }
+
+ try
+ {
+ return buildForMethod( method, definedClass );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ return null;
+ }
+ }
+
+ private FieldAccess getFieldAccess( Field field )
+ {
+ Class<?> declaringClass = field.getDeclaringClass();
+
+ FieldAccess fieldAccess = fieldAccessCache.get( declaringClass );
+ if ( fieldAccess != null )
+ {
+ return fieldAccess;
+ }
+
+ fieldAccess = FieldAccess.get( declaringClass );
+ fieldAccessCache.put( declaringClass, fieldAccess );
+
+ return fieldAccess;
+ }
+
+ private MethodAccess getMethodAccess( Method method )
+ {
+ Class<?> definedClass = method.getDeclaringClass();
+
+ MethodAccess methodAccess = methodAccessCache.get( definedClass );
+ if ( methodAccess != null )
+ {
+ return methodAccess;
+ }
+
+ methodAccess = MethodAccess.get( definedClass );
+ methodAccessCache.put( definedClass, methodAccess );
+
+ return methodAccess;
+ }
+
+ private PropertyAccessor buildForField( Field field, Class<?> definedClass )
+ {
+ final FieldAccess fieldAccess = getFieldAccess( field );
+ final int fieldIndex = fieldAccess.getIndex( field.getName() );
+ return new FieldValuePropertyAccessor( field, definedClass )
+ {
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ fieldAccess.set( instance, fieldIndex, value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ return (T) fieldAccess.get( instance, fieldIndex );
+ }
+ };
+ }
+
+ private PropertyAccessor buildForMethod( Method method, Class<?> definedClass )
+ {
+ final MethodAccess methodAccess = getMethodAccess( method );
+
+ Method getter = BeanUtil.findGetterMethod( method );
+ Method setter = BeanUtil.findSetterMethod( method );
+
+ final int getterMethodIndex = methodAccess.getIndex( getter.getName(), method.getParameterTypes() );
+ final int setterMethodIndex = methodAccess.getIndex( setter.getName(), method.getParameterTypes() );
+
+ return new MethodValuePropertyAccessor( setter, getter, definedClass )
+ {
+
+ @Override
+ public void writeShort( Object instance, short value )
+ {
+ writeObject( instance, value );
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ methodAccess.invoke( instance, setterMethodIndex, value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ return (T) methodAccess.invoke( instance, getterMethodIndex );
+ }
+
+ };
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorFactory.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorFactory.java
new file mode 100644
index 0000000..7838179
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorFactory.java
@@ -0,0 +1,496 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.exceptions.IllegalPropertyAccessException;
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+public class ReflectionPropertyAccessorFactory
+ implements PropertyAccessorFactory
+{
+
+ @Override
+ public PropertyAccessor fieldAccess( Field field, Class<?> definedClass )
+ {
+ if ( field.getType().isArray() )
+ {
+ return buildForArrayField( field, definedClass );
+ }
+
+ return buildForValueField( field, definedClass );
+ }
+
+ @Override
+ public PropertyAccessor methodAccess( Method method, Class<?> definedClass )
+ {
+ if ( method.getReturnType().isArray() )
+ {
+ return buildForArrayMethod( method, definedClass );
+ }
+
+ return buildForValueMethod( method, definedClass );
+ }
+
+ private PropertyAccessor buildForValueField( final Field field, final Class<?> definedClass )
+ {
+ field.setAccessible( true );
+ return new FieldValuePropertyAccessor( field, definedClass )
+ {
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ try
+ {
+ getField().set( instance, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ try
+ {
+ return (T) getField().get( instance );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+ };
+ }
+
+ private PropertyAccessor buildForArrayField( final Field field, final Class<?> definedClass )
+ {
+ field.setAccessible( true );
+ return new FieldArrayPropertyAccessor( field, definedClass )
+ {
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ try
+ {
+ getField().set( instance, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ try
+ {
+ return (T) getField().get( instance );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, int index, T value )
+ {
+ try
+ {
+ Array.set( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance, int index )
+ {
+ try
+ {
+ return (T) Array.get( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeShort( Object instance, int index, short value )
+ {
+ try
+ {
+ Array.setShort( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeLong( Object instance, int index, long value )
+ {
+ try
+ {
+ Array.setLong( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeInt( Object instance, int index, int value )
+ {
+ try
+ {
+ Array.setInt( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeFloat( Object instance, int index, float value )
+ {
+ try
+ {
+ Array.setFloat( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeDouble( Object instance, int index, double value )
+ {
+ try
+ {
+ Array.setDouble( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeChar( Object instance, int index, char value )
+ {
+ try
+ {
+ Array.setChar( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeByte( Object instance, int index, byte value )
+ {
+ try
+ {
+ Array.setByte( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public void writeBoolean( Object instance, int index, boolean value )
+ {
+ try
+ {
+ Array.setBoolean( instance, index, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public short readShort( Object instance, int index )
+ {
+ try
+ {
+ return Array.getShort( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public long readLong( Object instance, int index )
+ {
+ try
+ {
+ return Array.getLong( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public int readInt( Object instance, int index )
+ {
+ try
+ {
+ return Array.getInt( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public float readFloat( Object instance, int index )
+ {
+ try
+ {
+ return Array.getFloat( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public double readDouble( Object instance, int index )
+ {
+ try
+ {
+ return Array.getDouble( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public char readChar( Object instance, int index )
+ {
+ try
+ {
+ return Array.getChar( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public byte readByte( Object instance, int index )
+ {
+ try
+ {
+ return Array.getByte( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+
+ @Override
+ public boolean readBoolean( Object instance, int index )
+ {
+ try
+ {
+ return Array.getBoolean( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading field " + getField().getName(),
+ e );
+ }
+ }
+ };
+ }
+
+ private PropertyAccessor buildForValueMethod( Method method, Class<?> definedClass )
+ {
+ Method getter = BeanUtil.findGetterMethod( method );
+ Method setter = BeanUtil.findSetterMethod( method );
+
+ getter.setAccessible( true );
+ setter.setAccessible( true );
+
+ return new MethodValuePropertyAccessor( setter, getter, definedClass )
+ {
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ try
+ {
+ getSetterMethod().invoke( instance, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing with method "
+ + getSetterMethod().getName(), e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ try
+ {
+ return (T) getGetterMethod().invoke( instance );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading with method "
+ + getGetterMethod().getName(), e );
+ }
+ }
+ };
+ }
+
+ private PropertyAccessor buildForArrayMethod( Method method, Class<?> definedClass )
+ {
+ final Method getter = BeanUtil.findGetterMethod( method );
+ final Method setter = BeanUtil.findSetterMethod( method );
+ final Method arrayGetter = BeanUtil.findArrayGetterMethod( method );
+ final Method arraySetter = BeanUtil.findArraySetterMethod( method );
+
+ getter.setAccessible( true );
+ setter.setAccessible( true );
+
+ return new MethodArrayPropertyAccessor( setter, getter, definedClass )
+ {
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ try
+ {
+ getSetterMethod().invoke( instance, value );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing with method "
+ + getSetterMethod().getName(), e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ try
+ {
+ return (T) getGetterMethod().invoke( instance );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading with method "
+ + getGetterMethod().getName(), e );
+ }
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, int index, T value )
+ {
+ try
+ {
+ arraySetter.invoke( instance, value, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while writing with method "
+ + getSetterMethod().getName(), e );
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance, int index )
+ {
+ try
+ {
+ return (T) arrayGetter.invoke( instance, index );
+ }
+ catch ( Exception e )
+ {
+ throw new IllegalPropertyAccessException( "Exception while reading with method "
+ + getGetterMethod().getName(), e );
+ }
+ }
+ };
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/SunUnsafePropertyAccessorFactory.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/SunUnsafePropertyAccessorFactory.java
new file mode 100644
index 0000000..c59c4d2
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/SunUnsafePropertyAccessorFactory.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.internal.util.UnsafeUtil;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+
+@SuppressWarnings( "restriction" )
+final class SunUnsafePropertyAccessorFactory
+ implements PropertyAccessorFactory
+{
+
+ private static final sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe();
+
+ SunUnsafePropertyAccessorFactory()
+ {
+ }
+
+ @Override
+ public PropertyAccessor fieldAccess( Field field, Class<?> definedClass )
+ {
+ if ( field.getType().isArray() )
+ {
+ return buildForArrayField( field, definedClass );
+ }
+
+ return buildForValueField( field, definedClass );
+ }
+
+ @Override
+ public PropertyAccessor methodAccess( Method method, Class<?> definedClass )
+ {
+ throw new UnsupportedOperationException( "Method access is not supported by Unsafe style" );
+ }
+
+ private PropertyAccessor buildForValueField( final Field field, final Class<?> definedClass )
+ {
+ return new FieldValuePropertyAccessor( field, definedClass )
+ {
+
+ private final long offset;
+
+ {
+ offset = UNSAFE.objectFieldOffset( field );
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ UNSAFE.putObject( instance, offset, value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ return (T) UNSAFE.getObject( instance, offset );
+ }
+
+ @Override
+ public void writeBoolean( Object instance, boolean value )
+ {
+ UNSAFE.putBoolean( instance, offset, value );
+ }
+
+ @Override
+ public boolean readBoolean( Object instance )
+ {
+ return UNSAFE.getBoolean( instance, offset );
+ }
+
+ @Override
+ public void writeByte( Object instance, byte value )
+ {
+ UNSAFE.putByte( instance, offset, value );
+ }
+
+ @Override
+ public byte readByte( Object instance )
+ {
+ return UNSAFE.getByte( instance, offset );
+ }
+
+ @Override
+ public void writeShort( Object instance, short value )
+ {
+ UNSAFE.putShort( instance, offset, value );
+ }
+
+ @Override
+ public short readShort( Object instance )
+ {
+ return UNSAFE.getShort( instance, offset );
+ }
+
+ @Override
+ public void writeChar( Object instance, char value )
+ {
+ UNSAFE.putChar( instance, offset, value );
+ }
+
+ @Override
+ public char readChar( Object instance )
+ {
+ return UNSAFE.getChar( instance, offset );
+ }
+
+ @Override
+ public void writeInt( Object instance, int value )
+ {
+ UNSAFE.putInt( instance, offset, value );
+ }
+
+ @Override
+ public int readInt( Object instance )
+ {
+ return UNSAFE.getInt( instance, offset );
+ }
+
+ @Override
+ public void writeLong( Object instance, long value )
+ {
+ UNSAFE.putLong( instance, offset, value );
+ }
+
+ @Override
+ public long readLong( Object instance )
+ {
+ return UNSAFE.getLong( instance, offset );
+ }
+
+ @Override
+ public void writeFloat( Object instance, float value )
+ {
+ UNSAFE.putFloat( instance, offset, value );
+ }
+
+ @Override
+ public float readFloat( Object instance )
+ {
+ return UNSAFE.getFloat( instance, offset );
+ }
+
+ @Override
+ public void writeDouble( Object instance, double value )
+ {
+ UNSAFE.putDouble( instance, offset, value );
+ }
+
+ @Override
+ public double readDouble( Object instance )
+ {
+ return UNSAFE.getDouble( instance, offset );
+ }
+ };
+ }
+
+ private PropertyAccessor buildForArrayField( final Field field, final Class<?> definedClass )
+ {
+ return new FieldArrayPropertyAccessor( field, definedClass )
+ {
+
+ private final long offset;
+
+ private final int arrayBaseOffset;
+
+ private final int arrayIndexScale;
+
+ {
+ offset = UNSAFE.objectFieldOffset( field );
+ arrayBaseOffset = UNSAFE.arrayBaseOffset( field.getType() );
+ arrayIndexScale = UNSAFE.arrayIndexScale( field.getType() );
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, T value )
+ {
+ UNSAFE.putObject( instance, offset, value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance )
+ {
+ return (T) UNSAFE.getObject( instance, offset );
+ }
+
+ @Override
+ public <T> void writeObject( Object instance, int index, T value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putObject( instance, offset, value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T readObject( Object instance, int index )
+ {
+ long localOffset = calculateIndexOffset( index );
+ return (T) UNSAFE.getObject( instance, localOffset );
+ }
+
+ @Override
+ public void writeBoolean( Object instance, int index, boolean value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putBoolean( instance, offset, value );
+ }
+
+ @Override
+ public boolean readBoolean( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getBoolean( instance, offset );
+ }
+
+ @Override
+ public void writeByte( Object instance, int index, byte value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putByte( instance, offset, value );
+ }
+
+ @Override
+ public byte readByte( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getByte( instance, offset );
+ }
+
+ @Override
+ public void writeShort( Object instance, int index, short value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putShort( instance, offset, value );
+ }
+
+ @Override
+ public short readShort( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getShort( instance, offset );
+ }
+
+ @Override
+ public void writeChar( Object instance, int index, char value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putChar( instance, offset, value );
+ }
+
+ @Override
+ public char readChar( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getChar( instance, offset );
+ }
+
+ @Override
+ public void writeInt( Object instance, int index, int value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putInt( instance, offset, value );
+ }
+
+ @Override
+ public int readInt( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getInt( instance, offset );
+ }
+
+ @Override
+ public void writeLong( Object instance, int index, long value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putLong( instance, offset, value );
+ }
+
+ @Override
+ public long readLong( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getLong( instance, offset );
+ }
+
+ @Override
+ public void writeFloat( Object instance, int index, float value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putFloat( instance, offset, value );
+ }
+
+ @Override
+ public float readFloat( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getFloat( instance, offset );
+ }
+
+ @Override
+ public void writeDouble( Object instance, int index, double value )
+ {
+ long offset = calculateIndexOffset( index );
+ UNSAFE.putDouble( instance, offset, value );
+ }
+
+ @Override
+ public double readDouble( Object instance, int index )
+ {
+ long offset = calculateIndexOffset( index );
+ return UNSAFE.getDouble( instance, offset );
+ }
+
+ private long calculateIndexOffset( int index )
+ {
+ return arrayBaseOffset + ( index * arrayIndexScale );
+ }
+ };
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/introspection/AnnotatedTypeIntrospector.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/introspection/AnnotatedTypeIntrospector.java
new file mode 100644
index 0000000..05e7c24
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/beans/introspection/AnnotatedTypeIntrospector.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans.introspection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.configuration.TypeIntrospector;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class AnnotatedTypeIntrospector
+ implements TypeIntrospector
+{
+
+ private final Class<? extends Annotation> annotationType;
+
+ private final List<String> excludes;
+
+ public AnnotatedTypeIntrospector( Class<? extends Annotation> annotationType, List<String> excludes )
+ {
+ this.annotationType = annotationType;
+ this.excludes = excludes;
+ }
+
+ @Override
+ public List<PropertyDescriptor> introspect( Type type, MarshallerStrategy marshallerStrategy,
+ MarshallerContext marshallerContext,
+ PropertyDescriptorFactory propertyDescriptorFactory )
+ {
+
+ if ( !( type instanceof Class ) )
+ {
+ return Collections.emptyList();
+ }
+
+ Class<?> clazz = (Class<?>) type;
+ Set<Field> properties = BeanUtil.findPropertiesByClass( clazz, annotationType );
+
+ List<PropertyDescriptor> propertyDescriptors = new ArrayList<PropertyDescriptor>();
+ for ( Field property : properties )
+ {
+ if ( isExcluded( property.getName() ) )
+ {
+ continue;
+ }
+
+ Class<?> fieldType = property.getType();
+
+ Marshaller marshaller = marshallerStrategy.getMarshaller( fieldType, marshallerContext, false );
+
+ if ( marshaller == null && fieldType.isArray() )
+ {
+ marshaller = marshallerStrategy.getMarshaller( fieldType.getComponentType(), marshallerContext, false );
+ }
+
+ if ( marshaller instanceof TypeBindableMarshaller )
+ {
+ Type[] typeArguments = TypeUtil.getTypeArgument( property.getGenericType() );
+ marshaller = ( (TypeBindableMarshaller) marshaller ).bindType( typeArguments );
+ }
+
+ propertyDescriptors.add( propertyDescriptorFactory.byField( property, marshaller, clazz ) );
+ }
+
+ return propertyDescriptors;
+ }
+
+ private boolean isExcluded( String propertyName )
+ {
+ return excludes.contains( propertyName );
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/AbstractGeneratedMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/AbstractGeneratedMarshaller.java
new file mode 100644
index 0000000..ab8b9bb
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/AbstractGeneratedMarshaller.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.exceptions.SerializerDefinitionException;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public abstract class AbstractGeneratedMarshaller
+ implements Marshaller
+{
+
+ private final Class<?> clazz;
+
+ private final Map<Class<?>, Marshaller> marshallers;
+
+ private final ClassDescriptor classDescriptor;
+
+ private final List<PropertyDescriptor> propertyDescriptors;
+
+ private final ObjectInstantiator objectInstantiator;
+
+ public AbstractGeneratedMarshaller( Class<?> clazz, Map<Class<?>, Marshaller> marshallers,
+ ClassDescriptorAwareSerializer serializer,
+ ObjectInstantiatorFactory objectInstantiatorFactory )
+ {
+
+ this.clazz = clazz;
+ this.marshallers = marshallers;
+ this.classDescriptor = serializer.findClassDescriptor( clazz );
+ this.propertyDescriptors = Collections.unmodifiableList( classDescriptor.getPropertyDescriptors() );
+ this.objectInstantiator = objectInstantiatorFactory.getInstantiatorOf( clazz );
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return clazz.isAssignableFrom( type );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( serializationContext.getSerializationStrategy() == SerializationStrategy.SizeOptimized )
+ {
+ if ( ClassUtil.isReferenceCapable( propertyDescriptor.getType() ) )
+ {
+ long referenceId = dataInput.readLong();
+ V instance;
+ if ( containsReferenceId( referenceId, serializationContext ) )
+ {
+ instance = (V) findObjectByReferenceId( referenceId, serializationContext );
+ }
+ else
+ {
+ // Instance not yet received, for first time deserialize it
+ instance = unmarshall( (V) newInstance(), propertyDescriptor, dataInput, serializationContext );
+ cacheObjectForUnmarshall( referenceId, instance, serializationContext );
+ }
+
+ return instance;
+ }
+ }
+
+ V value = null;
+ if ( !propertyDescriptor.getType().isArray() )
+ {
+ value = (V) newInstance();
+ }
+
+ return unmarshall( value, propertyDescriptor, dataInput, serializationContext );
+ }
+
+ protected abstract <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException;
+
+ protected boolean isAlreadyMarshalled( Object value, Class<?> type, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( serializationContext.getSerializationStrategy() != SerializationStrategy.SizeOptimized )
+ {
+ return false;
+ }
+
+ if ( !ClassUtil.isReferenceCapable( type ) )
+ {
+ return false;
+ }
+
+ long referenceId = findReferenceIdByObject( value, serializationContext );
+ if ( referenceId == -1 )
+ {
+ referenceId = cacheObjectForMarshall( value, serializationContext );
+ dataOutput.writeLong( referenceId );
+ return false;
+ }
+
+ dataOutput.writeLong( referenceId );
+ return true;
+ }
+
+ protected ClassDescriptor getClassDescriptor()
+ {
+ return classDescriptor;
+ }
+
+ protected Object newInstance()
+ {
+ return objectInstantiator.newInstance();
+ }
+
+ protected PropertyDescriptor getPropertyDescriptor( String propertyName )
+ {
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
+ {
+ if ( propertyDescriptor.getPropertyName().equals( propertyName ) )
+ {
+ return propertyDescriptor;
+ }
+ }
+
+ // This should never happen
+ return null;
+ }
+
+ protected PropertyAccessor getPropertyAccessor( String propertyName )
+ {
+ return getPropertyDescriptor( propertyName ).getPropertyAccessor();
+ }
+
+ protected Marshaller findMarshaller( PropertyDescriptor propertyDescriptor )
+ {
+ if ( propertyDescriptor.getMarshaller() != null )
+ {
+ return propertyDescriptor.getMarshaller();
+ }
+
+ Marshaller marshaller = marshallers.get( propertyDescriptor.getType() );
+ if ( marshaller != null )
+ {
+ return marshaller;
+ }
+
+ return new DelegatingMarshaller( propertyDescriptor );
+ }
+
+ protected long findReferenceIdByObject( Object instance, SerializationContext serializationContext )
+ {
+ return serializationContext.findReferenceIdByObject( instance );
+ }
+
+ protected Object findObjectByReferenceId( long referenceId, SerializationContext serializationContext )
+ {
+ return serializationContext.findObjectByReferenceId( referenceId );
+ }
+
+ protected boolean containsReferenceId( long referenceId, SerializationContext serializationContext )
+ {
+ return serializationContext.containsReferenceId( referenceId );
+ }
+
+ protected long cacheObjectForMarshall( Object instance, SerializationContext serializationContext )
+ {
+ return serializationContext.putMarshalledInstance( instance );
+ }
+
+ protected long cacheObjectForUnmarshall( long referenceId, Object instance,
+ SerializationContext serializationContext )
+ {
+ return serializationContext.putUnmarshalledInstance( referenceId, instance );
+ }
+
+ private class DelegatingMarshaller
+ implements Marshaller
+ {
+
+ private final PropertyDescriptor marshalledProperty;
+
+ private Marshaller marshaller;
+
+ private DelegatingMarshaller( PropertyDescriptor marshalledProperty )
+ {
+ this.marshalledProperty = marshalledProperty;
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return marshalledProperty.getType().isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ Marshaller marshaller = this.marshaller;
+ if ( marshaller == null )
+ {
+ marshaller = getMarshaller();
+ }
+
+ if ( marshaller == null )
+ {
+ throw new SerializerDefinitionException( "No marshaller for property " + marshalledProperty + " found" );
+ }
+
+ marshaller.marshall( value, propertyDescriptor, dataOutput, serializationContext );
+ }
+
+ @Override
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ Marshaller marshaller = this.marshaller;
+ if ( marshaller == null )
+ {
+ marshaller = getMarshaller();
+ }
+
+ if ( marshaller == null )
+ {
+ throw new SerializerDefinitionException( "No marshaller for property " + marshalledProperty + " found" );
+ }
+
+ return marshaller.unmarshall( propertyDescriptor, dataInput, serializationContext );
+ }
+
+ private synchronized Marshaller getMarshaller()
+ {
+ if ( marshaller == null )
+ {
+ marshaller = findMarshaller( marshalledProperty );
+ }
+ return marshaller;
+ }
+
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/BytecodeMarshallerGenerator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/BytecodeMarshallerGenerator.java
new file mode 100644
index 0000000..b47a3d3
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/BytecodeMarshallerGenerator.java
@@ -0,0 +1,902 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.exceptions.SerializerMarshallerGeneratorException;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.internal.InternalMarshallerStrategy;
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class BytecodeMarshallerGenerator
+ implements Opcodes, GeneratorConstants, MarshallerGenerator
+{
+
+ private final GeneratorClassLoader classloader = CreateClassLoader.createClassLoader( getClass().getClassLoader() );
+
+ @Override
+ public Marshaller generateMarshaller( Class<?> type, List<PropertyDescriptor> propertyDescriptors,
+ Map<Class<?>, Marshaller> marshallers,
+ ClassDescriptorAwareSerializer serializer,
+ SerializationStrategy serializationStrategy,
+ ObjectInstantiatorFactory objectInstantiatorFactory, File debugCacheDirectory )
+ {
+
+ try
+ {
+ ClassWriter cw = new ClassWriter( 0 );
+
+ // Copy properties and sort them by name
+ List<PropertyDescriptor> propertyDescriptorsCopy = new ArrayList<PropertyDescriptor>( propertyDescriptors );
+ Collections.sort( propertyDescriptorsCopy );
+
+ // Build className e.g. "SomeTypeMarshaller$$X$$Lightning"
+ String className =
+ new StringBuilder( !type.isArray() ? type.getSimpleName() : type.getComponentType().getSimpleName()
+ + "Array" ).append( "Marshaller" ).append( GENEREATED_CLASS_ID.getAndIncrement() ).append( "Lightning" ).toString();
+
+ // Build class
+ cw.visit( V1_6, ACC_PUBLIC & ACC_SUPER, className, null, SUPER_CLASS_INTERNAL_TYPE, null );
+
+ // Build marshaller fields
+ createMarshallerFields( cw, propertyDescriptorsCopy );
+
+ // Build constructor
+ createConstructor( cw, className, propertyDescriptorsCopy );
+
+ // Build Marshaller#marshall method
+ createMarshallMethod( cw, className, type, serializationStrategy, propertyDescriptorsCopy );
+
+ // Build Marshaller#unmarshall method
+ createUnmarshallMethod( cw, className, type, propertyDescriptorsCopy );
+
+ // Closing class visit
+ cw.visitEnd();
+
+ final byte[] bytecode = cw.toByteArray();
+
+ if ( debugCacheDirectory != null )
+ {
+ File file = new File( debugCacheDirectory, className + ".class" );
+ FileOutputStream out = new FileOutputStream( file );
+ out.write( bytecode );
+ out.flush();
+ out.close();
+ }
+
+ Class<? extends Marshaller> generatedClass = classloader.loadClass( bytecode );
+ Constructor<? extends Marshaller> constructor =
+ generatedClass.getConstructor( Class.class, Map.class, ClassDescriptorAwareSerializer.class,
+ ObjectInstantiatorFactory.class, List.class, MarshallerStrategy.class );
+
+ constructor.setAccessible( true );
+ return constructor.newInstance( type, marshallers, serializer, objectInstantiatorFactory,
+ propertyDescriptorsCopy, new InternalMarshallerStrategy() );
+ }
+ catch ( Exception e )
+ {
+ throw new SerializerMarshallerGeneratorException(
+ "Marshaller for type " + type + " could not be generated",
+ e );
+ }
+ }
+
+ private void createMarshallerFields( ClassWriter cw, List<PropertyDescriptor> propertyDescriptors )
+ {
+ for ( int i = 0; i < propertyDescriptors.size(); i++ )
+ {
+ PropertyDescriptor propertyDescriptor = propertyDescriptors.get( i );
+ FieldVisitor fv = null;
+
+ // Write PropertyDescriptor field
+ fv =
+ cw.visitField( ACC_FINAL & ACC_PRIVATE, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR, null, null );
+ fv.visitEnd();
+
+ if ( propertyDescriptor.getType().isArray()
+ && !propertyDescriptor.getType().getComponentType().isPrimitive() )
+ {
+ // Write ComponentType PropertyDescriptor field
+ fv =
+ cw.visitField( ACC_FINAL & ACC_PRIVATE, toFinalFieldName( "component", propertyDescriptor ),
+ CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR, null, null );
+ fv.visitEnd();
+ }
+
+ // Write Marshaller field
+ fv =
+ cw.visitField( ACC_FINAL & ACC_PRIVATE, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR, null, null );
+ fv.visitEnd();
+
+ // Write PropertyAccessor field
+ fv =
+ cw.visitField( ACC_FINAL & ACC_PRIVATE, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR, null, null );
+ fv.visitEnd();
+ }
+ }
+
+ private void createConstructor( ClassWriter cw, String className, List<PropertyDescriptor> propertyDescriptors )
+ {
+ MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "<init>", MARSHALLER_CONSTRUCTOR_SIGNATURE, null, null );
+ mv.visitCode();
+
+ // Load this
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load first parameter type (Class)
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Load second parameter type (Map)
+ mv.visitVarInsn( ALOAD, 2 );
+
+ // Load third parameter type (ClassDescriptorAwaySerializer)
+ mv.visitVarInsn( ALOAD, 3 );
+
+ // Load fourth parameter type (ObjenesisSerializer)
+ mv.visitVarInsn( ALOAD, 4 );
+
+ // Call super(Class, Map)
+ mv.visitMethodInsn( INVOKESPECIAL, SUPER_CLASS_INTERNAL_TYPE, "<init>", MARSHALLER_SUPER_CONSTRUCTOR_SIGNATURE );
+
+ // Fill fields with marshallers
+ for ( int i = 0; i < propertyDescriptors.size(); i++ )
+ {
+ PropertyDescriptor propertyDescriptor = propertyDescriptors.get( i );
+ String fieldName = toFinalFieldName( "marshaller", propertyDescriptor );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load property type
+ mv.visitVarInsn( ALOAD, 5 );
+ mv.visitIntInsn( BIPUSH, i );
+ mv.visitMethodInsn( INVOKEINTERFACE, LIST_CLASS_INTERNAL_TYPE, "get", "(I)Ljava/lang/Object;" );
+
+ // Store PropertyDescriptor
+ mv.visitTypeInsn( CHECKCAST, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE );
+ mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+
+ if ( propertyDescriptor.getType().isArray()
+ && !propertyDescriptor.getType().getComponentType().isPrimitive() )
+ {
+ Label labelNonNull = new Label();
+
+ // Get type from PropertyAccessor
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+ mv.visitMethodInsn( INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getType",
+ "()Ljava/lang/Class;" );
+
+ // Get array component type
+ mv.visitMethodInsn( INVOKEVIRTUAL, CLASS_CLASS_INTERNAL_TYPE, "getComponentType",
+ CLASS_GET_COMPONENT_TYPE );
+ mv.visitVarInsn( ASTORE, 9 );
+
+ // Generate cheating PropertyDescriptor for component type
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitTypeInsn( NEW, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE );
+ mv.visitInsn( DUP );
+ mv.visitLdcInsn( propertyDescriptor.getPropertyName() + "Element" );
+ mv.visitVarInsn( ALOAD, 9 );
+ mv.visitInsn( ACONST_NULL );
+ mv.visitMethodInsn( INVOKESPECIAL, CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "<init>",
+ CHEATINGPROPERTYDESCRIPTOR_CONSTRUCTOR );
+ mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
+ CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+
+ // Search marshaller by using interal ones
+ mv.visitVarInsn( ALOAD, 6 );
+ mv.visitVarInsn( ALOAD, 9 );
+ mv.visitInsn( ACONST_NULL );
+ mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLERSTRATEGY_CLASS_INTERNAL_TYPE, "getMarshaller",
+ MARSHALLERSTRATEGY_GET_MARSHALLER_SIGNATURE );
+ mv.visitVarInsn( ASTORE, 8 );
+ mv.visitVarInsn( ALOAD, 8 );
+
+ // Search marshaller for property type
+ mv.visitJumpInsn( IFNONNULL, labelNonNull );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
+ CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+ mv.visitMethodInsn( INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller",
+ MARSHALLER_FIND_MARSHALLER_SIGNATURE );
+ mv.visitVarInsn( ASTORE, 8 );
+
+ // Save marshaller to field
+ mv.visitLabel( labelNonNull );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitVarInsn( ALOAD, 8 );
+ mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR );
+ }
+ else
+ {
+ // Check if marshaller is defined
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+ mv.visitMethodInsn( INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "findMarshaller",
+ MARSHALLER_FIND_MARSHALLER_SIGNATURE );
+ mv.visitFieldInsn( PUTFIELD, className, fieldName, MARSHALLER_CLASS_DESCRIPTOR );
+ }
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitInsn( DUP );
+
+ // Load property accessor
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+ mv.visitMethodInsn( INVOKEINTERFACE, PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE, "getPropertyAccessor",
+ PROPERTY_DESCRIPTOR_GET_PROPERTYACCESSOR_SIGNATURE );
+
+ // Save PropertyAccessor to field
+ mv.visitFieldInsn( PUTFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR );
+ }
+
+ mv.visitInsn( RETURN );
+ mv.visitMaxs( -1, 12 );
+ mv.visitEnd();
+ }
+
+ private void createMarshallMethod( ClassWriter cw, String className, Class<?> type,
+ SerializationStrategy serializationStrategy,
+ List<PropertyDescriptor> propertyDescriptors )
+ {
+
+ MethodVisitor mv =
+ cw.visitMethod( ACC_PUBLIC, "marshall", MARSHALLER_MARSHALL_SIGNATURE, null, MARSHALLER_EXCEPTIONS );
+
+ // If element type is not reference capable or SerializationStrategy is
+ // not SizeOptimized just prevent generation of code
+ if ( serializationStrategy == SerializationStrategy.SizeOptimized && ClassUtil.isReferenceCapable( type ) )
+ {
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load value to method stack
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Load type to method stack
+ mv.visitVarInsn( ALOAD, 2 );
+
+ // Load dataOutput to method stack
+ mv.visitVarInsn( ALOAD, 3 );
+
+ // Load serializationContext to method stack
+ mv.visitVarInsn( ALOAD, 4 );
+
+ // Call super.isAlreadyMarshalled(...);
+ mv.visitMethodInsn( INVOKEVIRTUAL, SUPER_CLASS_INTERNAL_TYPE, "isAlreadyMarshalled",
+ MARSHALLER_IS_ALREADY_MARSHALLED_SIGNATURE );
+
+ // Label if value is not yet marshalled
+ Label notYetMarshalled = new Label();
+
+ // Test if already marshalled
+ mv.visitJumpInsn( IFEQ, notYetMarshalled );
+
+ // If marshalled - just return
+ mv.visitInsn( RETURN );
+
+ // Visit label - if not yet marshalled - marshall it
+ mv.visitLabel( notYetMarshalled );
+ }
+
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
+ {
+ if ( propertyDescriptor.getType().isArray()
+ && !propertyDescriptor.getType().getComponentType().isPrimitive() )
+ {
+ visitObjectArrayPropertyAccessorRead( mv, className, propertyDescriptor );
+ }
+ else
+ {
+ visitValuePropertyAccessorRead( mv, className, propertyDescriptor );
+ }
+ }
+
+ // Add Return instruction
+ mv.visitInsn( RETURN );
+
+ // End visiting
+ mv.visitMaxs( 9, 9 );
+ mv.visitEnd();
+ }
+
+ private void visitValuePropertyAccessorRead( MethodVisitor mv, String className,
+ PropertyDescriptor propertyDescriptor )
+ {
+ Class<?> propertyType = propertyDescriptor.getType();
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load property marshaller on stack
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR );
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Read PropertyAccessor from field
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR );
+
+ // Load value to method stack
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Load value by type on stack
+ visitPropertyAccessorValueRead( propertyType, mv );
+
+ // If type is primitive add some "autoboxing" magic
+ if ( propertyType.isPrimitive() )
+ {
+ visitWrapperAutoboxing( propertyType, mv );
+ }
+
+ // Load type to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+
+ // Load DataOutput to method stack
+ mv.visitVarInsn( ALOAD, 3 );
+
+ // Load SerializationContext to method stack
+ mv.visitVarInsn( ALOAD, 4 );
+
+ // Call Marshaller#marshall on properties marshaller
+ mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "marshall", MARSHALLER_MARSHALL_SIGNATURE );
+ }
+
+ private void visitObjectArrayPropertyAccessorRead( MethodVisitor mv, String className,
+ PropertyDescriptor propertyDescriptor )
+ {
+ Class<?> propertyType = propertyDescriptor.getType();
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Read PropertyAccessor from field
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR );
+ mv.visitTypeInsn( CHECKCAST, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE );
+ mv.visitVarInsn( ASTORE, 8 );
+
+ // Load property type
+ mv.visitVarInsn( ALOAD, 8 );
+ mv.visitInsn( DUP );
+ mv.visitMethodInsn( INVOKEINTERFACE, PROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "getType",
+ OBJECT_GET_CLASS_SIGNATURE );
+ mv.visitVarInsn( ASTORE, 5 );
+
+ // Load value to method stack
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Save array to stack position 6
+ visitPropertyAccessorValueRead( propertyType, mv );
+ mv.visitTypeInsn( CHECKCAST, Type.getType( propertyType ).getInternalName() );
+ mv.visitVarInsn( ASTORE, 6 );
+
+ // Save length to stream
+ mv.visitVarInsn( ALOAD, 3 );
+ mv.visitVarInsn( ALOAD, 6 );
+ mv.visitInsn( ARRAYLENGTH );
+ mv.visitMethodInsn( INVOKEINTERFACE, DATAOUTPUT_CLASS_INTERNAL_TYPE, "writeInt", "(I)V" );
+
+ // Loop over every element in array
+ Label forLoopEnd = new Label();
+ Label forLoopStart = new Label();
+ mv.visitInsn( ICONST_0 );
+ mv.visitVarInsn( ISTORE, 7 );
+ mv.visitJumpInsn( GOTO, forLoopEnd );
+ mv.visitLabel( forLoopStart );
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load property marshaller on stack
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR );
+
+ // Load PropertyAccessor to method stack
+ mv.visitVarInsn( ALOAD, 8 );
+
+ // Load array to method stack
+ mv.visitVarInsn( ALOAD, 6 );
+
+ // Load index to method stack
+ mv.visitVarInsn( ILOAD, 7 );
+
+ // Get value from array
+ mv.visitMethodInsn( INVOKEINTERFACE, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "readObject",
+ PROPERTY_ACCESSOR_ARRAY_READ_OBJECT_SIGNATURE );
+ mv.visitTypeInsn( CHECKCAST, Type.getType( propertyType.getComponentType() ).getInternalName() );
+
+ // If type is primitive add some "autoboxing" magic
+ if ( propertyType.getComponentType().isPrimitive() )
+ {
+ visitWrapperAutoboxing( propertyType.getComponentType(), mv );
+ }
+
+ // Load type to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
+ CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+
+ // Load DataOutput to method stack
+ mv.visitVarInsn( ALOAD, 3 );
+
+ // Load SerializationContext to method stack
+ mv.visitVarInsn( ALOAD, 4 );
+
+ // Call Marshaller#marshall on properties marshaller
+ mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "marshall", MARSHALLER_MARSHALL_SIGNATURE );
+
+ // Test if loop ends
+ mv.visitIincInsn( 7, 1 );
+ mv.visitLabel( forLoopEnd );
+ mv.visitVarInsn( ILOAD, 7 );
+ mv.visitVarInsn( ALOAD, 6 );
+ mv.visitInsn( ARRAYLENGTH );
+ mv.visitJumpInsn( IF_ICMPLT, forLoopStart );
+ }
+
+ private void createUnmarshallMethod( ClassWriter cw, String className, Class<?> type,
+ List<PropertyDescriptor> propertyDescriptors )
+ {
+ MethodVisitor mv =
+ cw.visitMethod( ACC_PUBLIC, "unmarshall", MARSHALLER_UNMARSHALL_SIGNATURE, null, MARSHALLER_EXCEPTIONS );
+
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
+ {
+ if ( propertyDescriptor.getType().isArray()
+ && !propertyDescriptor.getType().getComponentType().isPrimitive() )
+ {
+ visitObjectArrayPropertyAccessorWrite( mv, className, propertyDescriptor );
+ }
+ else
+ {
+ visitValuePropertyAccessorWrite( mv, className, propertyDescriptor );
+ }
+ }
+
+ // Load instance to method stack
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Add Return statement
+ visitReturn( type, mv );
+
+ // End visiting
+ mv.visitMaxs( 11, 11 );
+ mv.visitEnd();
+ }
+
+ private void visitValuePropertyAccessorWrite( MethodVisitor mv, String className,
+ PropertyDescriptor propertyDescriptor )
+ {
+ Class<?> propertyType = propertyDescriptor.getType();
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Read PropertyAccessor from field
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR );
+
+ // Store PropertyAccessor for later use
+ mv.visitVarInsn( ASTORE, 5 );
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load property marshaller to method stack
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR );
+
+ // Load this to method stack
+ mv.visitVarInsn( ALOAD, 0 );
+
+ // Load PropertyDescriptor to method stack
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "descriptor", propertyDescriptor ),
+ PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+
+ // Load DataInput to method stack
+ mv.visitVarInsn( ALOAD, 3 );
+
+ // Load SerializationContext to method stack
+ mv.visitVarInsn( ALOAD, 4 );
+
+ // Call Marshaller#unmarshall on properties marshaller
+ mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "unmarshall",
+ MARSHALLER_BASE_UNMARSHALL_SIGNATURE );
+
+ // Save value
+ mv.visitVarInsn( ASTORE, 6 );
+
+ // Load PropertyAccessor to method stack
+ mv.visitVarInsn( ALOAD, 5 );
+
+ // Load instance to method stack
+ mv.visitVarInsn( ALOAD, 1 );
+
+ // Load value to method stack
+ mv.visitVarInsn( ALOAD, 6 );
+
+ // If type is primitive add some "autoboxing" magic
+ if ( propertyType.isPrimitive() )
+ {
+ visitPrimitiveAutoboxing( propertyType, mv );
+ }
+
+ // Call PropertyAccessor#writeX
+ visitPropertyAccessorValueWrite( propertyType, mv );
+ }
+
+ private void visitObjectArrayPropertyAccessorWrite( MethodVisitor mv, String className,
+ PropertyDescriptor propertyDescriptor )
+ {
+ Class<?> propertyType = propertyDescriptor.getType();
+ Class<?> componentType = propertyType.getComponentType();
+
+ // Read size
+ mv.visitVarInsn( ALOAD, 3 );
+ mv.visitMethodInsn( INVOKEINTERFACE, DATAINPUT_CLASS_INTERNAL_TYPE, "readInt", "()I" );
+ mv.visitInsn( DUP );
+ mv.visitVarInsn( ISTORE, 5 );
+
+ // Instantiate array
+ mv.visitTypeInsn( ANEWARRAY, Type.getType( componentType ).getInternalName() );
+ mv.visitVarInsn( ASTORE, 6 );
+
+ // Read PropertyAccessor from field
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "accessor", propertyDescriptor ),
+ PROPERTYACCESSOR_CLASS_DESCRIPTOR );
+ mv.visitVarInsn( ASTORE, 9 );
+
+ // Get component type
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "component", propertyDescriptor ),
+ CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR );
+ mv.visitVarInsn( ASTORE, 8 );
+
+ mv.visitVarInsn( ALOAD, 0 );
+ mv.visitFieldInsn( GETFIELD, className, toFinalFieldName( "marshaller", propertyDescriptor ),
+ MARSHALLER_CLASS_DESCRIPTOR );
+ mv.visitVarInsn( ASTORE, 10 );
+
+ // For loop
+ Label forLoopStart = new Label();
+ Label forLoopEnd = new Label();
+ mv.visitInsn( ICONST_0 );
+ mv.visitVarInsn( ISTORE, 7 );
+ mv.visitJumpInsn( GOTO, forLoopEnd );
+ mv.visitLabel( forLoopStart );
+
+ // Write value to array
+ mv.visitVarInsn( ALOAD, 9 );
+ mv.visitVarInsn( ALOAD, 6 );
+ mv.visitVarInsn( ILOAD, 7 );
+
+ // Read value from stream to 4th stack position
+ mv.visitVarInsn( ALOAD, 10 );
+ mv.visitVarInsn( ALOAD, 8 );
+ mv.visitVarInsn( ALOAD, 3 );
+ mv.visitVarInsn( ALOAD, 4 );
+ mv.visitMethodInsn( INVOKEINTERFACE, MARSHALLER_CLASS_INTERNAL_TYPE, "unmarshall",
+ MARSHALLER_BASE_UNMARSHALL_SIGNATURE );
+
+ mv.visitMethodInsn( INVOKEINTERFACE, ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, "writeObject",
+ PROPERTY_ACCESSOR_ARRAY_WRITE_OBJECT_SIGNATURE );
+
+ // Increment counter
+ mv.visitIincInsn( 7, 1 );
+
+ // Test for loop end
+ mv.visitLabel( forLoopEnd );
+ mv.visitVarInsn( ILOAD, 7 );
+ mv.visitVarInsn( ILOAD, 5 );
+ mv.visitJumpInsn( IF_ICMPLT, forLoopStart );
+
+ // Write array to object
+ mv.visitVarInsn( ALOAD, 9 );
+ mv.visitVarInsn( ALOAD, 1 );
+ mv.visitVarInsn( ALOAD, 6 );
+ visitPropertyAccessorValueWrite( propertyType.getComponentType(), mv );
+ }
+
+ private void visitReturn( Class<?> type, MethodVisitor mv )
+ {
+ int returnOpcode = ARETURN;
+
+ if ( type == boolean.class )
+ {
+ returnOpcode = IRETURN;
+ }
+ else if ( type == byte.class )
+ {
+ returnOpcode = IRETURN;
+ }
+ else if ( type == char.class )
+ {
+ returnOpcode = IRETURN;
+ }
+ else if ( type == short.class )
+ {
+ returnOpcode = IRETURN;
+ }
+ else if ( type == int.class )
+ {
+ returnOpcode = IRETURN;
+ }
+ else if ( type == long.class )
+ {
+ returnOpcode = LRETURN;
+ }
+ else if ( type == float.class )
+ {
+ returnOpcode = FRETURN;
+ }
+ else if ( type == double.class )
+ {
+ returnOpcode = DRETURN;
+ }
+ else
+ {
+ returnOpcode = ARETURN;
+ }
+
+ mv.visitInsn( returnOpcode );
+ }
+
+ private void visitPropertyAccessorValueRead( Class<?> type, MethodVisitor mv )
+ {
+ String methodName = null;
+ String methodSignature = null;
+
+ if ( type == boolean.class )
+ {
+ methodName = "readBoolean";
+ methodSignature = PROPERTY_ACCESSOR_READ_BOOLEAN_SIGNATURE;
+ }
+ else if ( type == byte.class )
+ {
+ methodName = "readByte";
+ methodSignature = PROPERTY_ACCESSOR_READ_BYTE_SIGNATURE;
+ }
+ else if ( type == char.class )
+ {
+ methodName = "readChar";
+ methodSignature = PROPERTY_ACCESSOR_READ_CHAR_SIGNATURE;
+ }
+ else if ( type == short.class )
+ {
+ methodName = "readShort";
+ methodSignature = PROPERTY_ACCESSOR_READ_SHORT_SIGNATURE;
+ }
+ else if ( type == int.class )
+ {
+ methodName = "readInt";
+ methodSignature = PROPERTY_ACCESSOR_READ_INT_SIGNATURE;
+ }
+ else if ( type == long.class )
+ {
+ methodName = "readLong";
+ methodSignature = PROPERTY_ACCESSOR_READ_LONG_SIGNATURE;
+ }
+ else if ( type == float.class )
+ {
+ methodName = "readFloat";
+ methodSignature = PROPERTY_ACCESSOR_READ_FLOAT_SIGNATURE;
+ }
+ else if ( type == double.class )
+ {
+ methodName = "readDouble";
+ methodSignature = PROPERTY_ACCESSOR_READ_DOUBLE_SIGNATURE;
+ }
+ else
+ {
+ methodName = "readObject";
+ methodSignature = PROPERTY_ACCESSOR_READ_OBJECT_SIGNATURE;
+ }
+
+ mv.visitMethodInsn( INVOKEINTERFACE, VALUEPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, methodName, methodSignature );
+ }
+
+ private void visitPropertyAccessorValueWrite( Class<?> type, MethodVisitor mv )
+ {
+ String methodName = null;
+ String methodSignature = null;
+
+ if ( type == boolean.class )
+ {
+ methodName = "writeBoolean";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_BOOLEAN_SIGNATURE;
+ }
+ else if ( type == byte.class )
+ {
+ methodName = "writeByte";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_BYTE_SIGNATURE;
+ }
+ else if ( type == char.class )
+ {
+ methodName = "writeChar";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_CHAR_SIGNATURE;
+ }
+ else if ( type == short.class )
+ {
+ methodName = "writeShort";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_SHORT_SIGNATURE;
+ }
+ else if ( type == int.class )
+ {
+ methodName = "writeInt";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_INT_SIGNATURE;
+ }
+ else if ( type == long.class )
+ {
+ methodName = "writeLong";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_LONG_SIGNATURE;
+ }
+ else if ( type == float.class )
+ {
+ methodName = "writeFloat";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_FLOAT_SIGNATURE;
+ }
+ else if ( type == double.class )
+ {
+ methodName = "writeDouble";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_DOUBLE_SIGNATURE;
+ }
+ else
+ {
+ methodName = "writeObject";
+ methodSignature = PROPERTY_ACCESSOR_WRITE_OBJECT_SIGNATURE;
+ }
+
+ mv.visitMethodInsn( INVOKEINTERFACE, VALUEPROPERTYACCESSOR_CLASS_INTERNAL_TYPE, methodName, methodSignature );
+ }
+
+ private void visitPrimitiveAutoboxing( Class<?> type, MethodVisitor mv )
+ {
+ if ( type == boolean.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z" );
+ }
+ else if ( type == byte.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B" );
+ }
+ else if ( type == char.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C" );
+ }
+ else if ( type == short.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S" );
+ }
+ else if ( type == int.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I" );
+ }
+ else if ( type == long.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J" );
+ }
+ else if ( type == float.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F" );
+ }
+ else if ( type == double.class )
+ {
+ mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D" );
+ }
+ }
+
+ private void visitWrapperAutoboxing( Class<?> type, MethodVisitor mv )
+ {
+ if ( type == boolean.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", BOOLEAN_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == byte.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", BYTE_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == char.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", CHAR_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == short.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", SHORT_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == int.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", INT_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == long.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", LONG_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == float.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", FLOAT_VALUE_OF_SIGNATURE );
+ }
+ else if ( type == double.class )
+ {
+ mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", DOUBLE_VALUE_OF_SIGNATURE );
+ }
+ }
+
+ private String toFinalFieldName( String prefix, PropertyDescriptor propertyDescriptor )
+ {
+ return new StringBuilder( prefix.toUpperCase() ).append( "_" ).append( propertyDescriptor.getPropertyName().toUpperCase() ).append( "_LIGHTNING" ).toString();
+ }
+
+ protected void visitSystemOutPrintln( MethodVisitor mv, int stackPosition )
+ {
+ mv.visitVarInsn( ASTORE, stackPosition );
+ mv.visitFieldInsn( GETSTATIC, Type.getType( System.class ).getInternalName(), "out",
+ Type.getType( PrintStream.class ).getDescriptor() );
+ mv.visitVarInsn( ALOAD, stackPosition );
+ mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType( Object.class ).getInternalName(), "toString",
+ "()Ljava/lang/String;" );
+ mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType( PrintStream.class ).getInternalName(), "println",
+ "(Ljava/lang/String;)V" );
+ mv.visitVarInsn( ALOAD, stackPosition );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/CreateClassLoader.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/CreateClassLoader.java
new file mode 100644
index 0000000..d66f736
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/CreateClassLoader.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class CreateClassLoader
+ implements PrivilegedAction<GeneratorClassLoader>
+{
+
+ private final ClassLoader classLoader;
+
+ public CreateClassLoader( final ClassLoader classLoader )
+ {
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public GeneratorClassLoader run()
+ {
+ return new GeneratorClassLoader( classLoader );
+ }
+
+ public static final GeneratorClassLoader createClassLoader( ClassLoader classLoader )
+ {
+ return AccessController.doPrivileged( new CreateClassLoader( classLoader ) );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorClassLoader.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorClassLoader.java
new file mode 100644
index 0000000..98458ff
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorClassLoader.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+public class GeneratorClassLoader
+ extends ClassLoader
+{
+
+ public GeneratorClassLoader( final ClassLoader classLoader )
+ {
+ super( classLoader );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public <T> Class<T> loadClass( final byte[] data )
+ {
+ return (Class<T>) defineClass( null, data, 0, data.length );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorConstants.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorConstants.java
new file mode 100644
index 0000000..efc4f84
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/GeneratorConstants.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.CheatPropertyDescriptor;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.metadata.ArrayPropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.apache.directmemory.lightning.metadata.ValuePropertyAccessor;
+import org.objectweb.asm.Type;
+
+public interface GeneratorConstants
+{
+
+ static String MARSHALLER_MARSHALL_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] { Type.getType( Object.class ), Type.getType( PropertyDescriptor.class ),
+ Type.getType( DataOutput.class ), Type.getType( SerializationContext.class ) } );
+
+ static String MARSHALLER_BASE_UNMARSHALL_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Object.class ), new Type[] { Type.getType( PropertyDescriptor.class ),
+ Type.getType( DataInput.class ), Type.getType( SerializationContext.class ) } );
+
+ static String MARSHALLER_UNMARSHALL_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Object.class ),
+ new Type[] { Type.getType( Object.class ), Type.getType( PropertyDescriptor.class ),
+ Type.getType( DataInput.class ), Type.getType( SerializationContext.class ) } );
+
+ static String MARSHALLER_FIND_MARSHALLER_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Marshaller.class ),
+ new Type[] { Type.getType( PropertyDescriptor.class ) } );
+
+ static String MARSHALLER_GET_PROPERTY_ACCESSOR_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( PropertyAccessor.class ), new Type[] { Type.getType( String.class ) } );
+
+ static String MARSHALLER_IS_ALREADY_MARSHALLED_SIGNATURE =
+ Type.getMethodDescriptor( Type.BOOLEAN_TYPE,
+ new Type[] { Type.getType( Object.class ), Type.getType( Class.class ),
+ Type.getType( DataOutput.class ), Type.getType( SerializationContext.class ) } );
+
+ static String MARSHALLER_CONSTRUCTOR_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] { Type.getType( Class.class ), Type.getType( Map.class ),
+ Type.getType( ClassDescriptorAwareSerializer.class ),
+ Type.getType( ObjectInstantiatorFactory.class ), Type.getType( List.class ),
+ Type.getType( MarshallerStrategy.class ) } );
+
+ static String MARSHALLER_SUPER_CONSTRUCTOR_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] { Type.getType( Class.class ), Type.getType( Map.class ),
+ Type.getType( ClassDescriptorAwareSerializer.class ), Type.getType( ObjectInstantiatorFactory.class ) } );
+
+ static String PROPERTY_DESCRIPTOR_GET_MARSHALLER_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Marshaller.class ), new Type[0] );
+
+ static String PROPERTY_DESCRIPTOR_GET_PROPERTYACCESSOR_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( PropertyAccessor.class ), new Type[0] );
+
+ static String OBJECT_GET_CLASS_SIGNATURE = Type.getMethodDescriptor( Type.getType( Class.class ), new Type[0] );
+
+ static String CLASS_GET_COMPONENT_TYPE = Type.getMethodDescriptor( Type.getType( Class.class ), new Type[0] );
+
+ static String ARRAY_LENGTH_SIGNATURE = Type.getMethodDescriptor( Type.INT_TYPE, new Type[0] );
+
+ static String MARSHALLERSTRATEGY_GET_MARSHALLER_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Marshaller.class ),
+ new Type[] { Type.getType( java.lang.reflect.Type.class ),
+ Type.getType( MarshallerContext.class ) } );
+
+ static String CHEATINGPROPERTYDESCRIPTOR_CONSTRUCTOR =
+ Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] { Type.getType( String.class ),
+ Type.getType( Class.class ), Type.getType( Marshaller.class ) } );
+
+ static String SUPER_CLASS_INTERNAL_TYPE = Type.getType( AbstractGeneratedMarshaller.class ).getInternalName();
+
+ static String MARSHALLER_CLASS_INTERNAL_TYPE = Type.getType( Marshaller.class ).getInternalName();
+
+ static String IOEXCEPTION_CLASS_INTERNAL_TYPE = Type.getType( IOException.class ).getInternalName();
+
+ static String LIST_CLASS_INTERNAL_TYPE = Type.getType( List.class ).getInternalName();
+
+ static String PROPERTYACCESSOR_CLASS_INTERNAL_TYPE = Type.getType( PropertyAccessor.class ).getInternalName();
+
+ static String VALUEPROPERTYACCESSOR_CLASS_INTERNAL_TYPE =
+ Type.getType( ValuePropertyAccessor.class ).getInternalName();
+
+ static String ARRAYPROPERTYACCESSOR_CLASS_INTERNAL_TYPE =
+ Type.getType( ArrayPropertyAccessor.class ).getInternalName();
+
+ static String PROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE = Type.getType( PropertyDescriptor.class ).getInternalName();
+
+ static String CHEATINGPROPERTYDESCRIPTOR_CLASS_INTERNAL_TYPE =
+ Type.getType( CheatPropertyDescriptor.class ).getInternalName();
+
+ static String CLASS_CLASS_INTERNAL_TYPE = Type.getType( Class.class ).getInternalName();
+
+ static String DATAOUTPUT_CLASS_INTERNAL_TYPE = Type.getType( DataOutput.class ).getInternalName();
+
+ static String DATAINPUT_CLASS_INTERNAL_TYPE = Type.getType( DataInput.class ).getInternalName();
+
+ static String MARSHALLERSTRATEGY_CLASS_INTERNAL_TYPE = Type.getType( MarshallerStrategy.class ).getInternalName();
+
+ static String MARSHALLER_CLASS_DESCRIPTOR = Type.getType( Marshaller.class ).getDescriptor();
+
+ static String PROPERTYDESCRIPTOR_CLASS_DESCRIPTOR = Type.getType( PropertyDescriptor.class ).getDescriptor();
+
+ static String PROPERTYACCESSOR_CLASS_DESCRIPTOR = Type.getType( PropertyAccessor.class ).getDescriptor();
+
+ static String CHEATINGPROPERTYDESCRIPTOR_CLASS_DESCRIPTOR =
+ Type.getType( CheatPropertyDescriptor.class ).getDescriptor();
+
+ static String[] MARSHALLER_EXCEPTIONS = { IOEXCEPTION_CLASS_INTERNAL_TYPE };
+
+ static AtomicLong GENEREATED_CLASS_ID = new AtomicLong();
+
+ static String PROPERTY_DESCRIPTOR_FIELD_NAME = "PROPERTY_DESCRIPTORS";
+
+ static String PROPERTY_ACCESSOR_READ_BOOLEAN_SIGNATURE =
+ Type.getMethodDescriptor( Type.BOOLEAN_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_BYTE_SIGNATURE =
+ Type.getMethodDescriptor( Type.BYTE_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_CHAR_SIGNATURE =
+ Type.getMethodDescriptor( Type.CHAR_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_SHORT_SIGNATURE =
+ Type.getMethodDescriptor( Type.SHORT_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_INT_SIGNATURE =
+ Type.getMethodDescriptor( Type.INT_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_LONG_SIGNATURE =
+ Type.getMethodDescriptor( Type.LONG_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_FLOAT_SIGNATURE =
+ Type.getMethodDescriptor( Type.FLOAT_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_DOUBLE_SIGNATURE =
+ Type.getMethodDescriptor( Type.DOUBLE_TYPE, new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_READ_OBJECT_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Object.class ), new Type[] { Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_WRITE_BOOLEAN_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.BOOLEAN_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_BYTE_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.BYTE_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_CHAR_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.CHAR_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_SHORT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.SHORT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_INT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_LONG_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.LONG_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_FLOAT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] {
+ Type.getType( Object.class ),
+ Type.FLOAT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_DOUBLE_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.DOUBLE_TYPE } );
+
+ static String PROPERTY_ACCESSOR_WRITE_OBJECT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.getType( Object.class ) } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_BOOLEAN_SIGNATURE =
+ Type.getMethodDescriptor( Type.BOOLEAN_TYPE, new Type[] { Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_BYTE_SIGNATURE = Type.getMethodDescriptor( Type.BYTE_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_CHAR_SIGNATURE = Type.getMethodDescriptor( Type.CHAR_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_SHORT_SIGNATURE = Type.getMethodDescriptor( Type.SHORT_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_INT_SIGNATURE = Type.getMethodDescriptor( Type.INT_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_LONG_SIGNATURE = Type.getMethodDescriptor( Type.LONG_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_FLOAT_SIGNATURE = Type.getMethodDescriptor( Type.FLOAT_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_DOUBLE_SIGNATURE =
+ Type.getMethodDescriptor( Type.DOUBLE_TYPE, new Type[] { Type.getType( Object.class ), Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_READ_OBJECT_SIGNATURE =
+ Type.getMethodDescriptor( Type.getType( Object.class ), new Type[] { Type.getType( Object.class ),
+ Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_BOOLEAN_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] { Type.getType( Object.class ), Type.INT_TYPE,
+ Type.BOOLEAN_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_BYTE_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.BYTE_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_CHAR_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.CHAR_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_SHORT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.SHORT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_INT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.INT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_LONG_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.LONG_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_FLOAT_SIGNATURE = Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] {
+ Type.getType( Object.class ), Type.INT_TYPE, Type.FLOAT_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_DOUBLE_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] { Type.getType( Object.class ), Type.INT_TYPE,
+ Type.DOUBLE_TYPE } );
+
+ static String PROPERTY_ACCESSOR_ARRAY_WRITE_OBJECT_SIGNATURE =
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[] { Type.getType( Object.class ), Type.INT_TYPE, Type.getType( Object.class ) } );
+
+ static String BOOLEAN_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Boolean.class ),
+ new Type[] { Type.BOOLEAN_TYPE } );
+
+ static String BYTE_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Byte.class ),
+ new Type[] { Type.BYTE_TYPE } );
+
+ static String CHAR_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Character.class ),
+ new Type[] { Type.CHAR_TYPE } );
+
+ static String SHORT_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Short.class ),
+ new Type[] { Type.SHORT_TYPE } );
+
+ static String INT_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Integer.class ),
+ new Type[] { Type.INT_TYPE } );
+
+ static String LONG_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Long.class ),
+ new Type[] { Type.LONG_TYPE } );
+
+ static String FLOAT_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Float.class ),
+ new Type[] { Type.FLOAT_TYPE } );
+
+ static String DOUBLE_VALUE_OF_SIGNATURE = Type.getMethodDescriptor( Type.getType( Double.class ),
+ new Type[] { Type.DOUBLE_TYPE } );
+
+ static String ARRAY_TYPE_BOOLEAN = Type.getInternalName( boolean[].class );
+
+ static String ARRAY_TYPE_BYTE = Type.getInternalName( byte[].class );
+
+ static String ARRAY_TYPE_CHAR = Type.getInternalName( char[].class );
+
+ static String ARRAY_TYPE_SHORT = Type.getInternalName( short[].class );
+
+ static String ARRAY_TYPE_INT = Type.getInternalName( int[].class );
+
+ static String ARRAY_TYPE_LONG = Type.getInternalName( long[].class );
+
+ static String ARRAY_TYPE_FLOAT = Type.getInternalName( float[].class );
+
+ static String ARRAY_TYPE_DOUBLE = Type.getInternalName( double[].class );
+
+ static String ARRAY_TYPE_OBJECT = Type.getInternalName( Object[].class );
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/MarshallerGenerator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/MarshallerGenerator.java
new file mode 100644
index 0000000..6637c54
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/generator/MarshallerGenerator.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.generator;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public interface MarshallerGenerator
+{
+
+ Marshaller generateMarshaller( Class<?> type, List<PropertyDescriptor> propertyDescriptors,
+ Map<Class<?>, Marshaller> marshallers, ClassDescriptorAwareSerializer serializer,
+ SerializationStrategy serializationStrategy,
+ ObjectInstantiatorFactory objectInstantiatorFactory, File debugCacheDirectory );
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/NullInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/NullInstantiator.java
new file mode 100644
index 0000000..1a53fda
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/NullInstantiator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+
+/**
+ * The instantiator that always return a null instance
+ *
+ * @author Henri Tremblay
+ */
+public class NullInstantiator
+ implements ObjectInstantiator
+{
+
+ /**
+ * @return Always null
+ */
+ @Override
+ public Object newInstance()
+ {
+ return null;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisBase.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisBase.java
new file mode 100644
index 0000000..c41daa8
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisBase.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.instantiator.strategy.InstantiatorStrategy;
+
+/**
+ * Base class to extend if you want to have a class providing your own default strategy. Can also be instantiated
+ * directly.
+ *
+ * @author Henri Tremblay
+ */
+public class ObjenesisBase
+ implements ObjectInstantiatorFactory
+{
+
+ /** Strategy used by this Objenesi implementation to create classes */
+ protected final InstantiatorStrategy strategy;
+
+ /** Strategy cache. Key = Class, Value = InstantiatorStrategy */
+ protected Map<String, ObjectInstantiator> cache;
+
+ /**
+ * Constructor allowing to pick a strategy and using cache
+ *
+ * @param strategy Strategy to use
+ */
+ public ObjenesisBase( InstantiatorStrategy strategy )
+ {
+ this( strategy, true );
+ }
+
+ /**
+ * Flexible constructor allowing to pick the strategy and if caching should be used
+ *
+ * @param strategy Strategy to use
+ * @param useCache If {@link ObjectInstantiator}s should be cached
+ */
+ public ObjenesisBase( InstantiatorStrategy strategy, boolean useCache )
+ {
+ if ( strategy == null )
+ {
+ throw new IllegalArgumentException( "A strategy can't be null" );
+ }
+ this.strategy = strategy;
+ this.cache = useCache ? new HashMap<String, ObjectInstantiator>() : null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getClass().getName() + " using " + strategy.getClass().getName()
+ + ( cache == null ? " without" : " with" ) + " caching";
+ }
+
+ /**
+ * Will create a new object without any constructor being called
+ *
+ * @param clazz Class to instantiate
+ * @return New instance of clazz
+ */
+ @Override
+ public Object newInstance( Class<?> clazz )
+ {
+ return getInstantiatorOf( clazz ).newInstance();
+ }
+
+ /**
+ * Will pick the best instantiator for the provided class. If you need to create a lot of instances from the same
+ * class, it is way more efficient to create them from the same ObjectInstantiator than calling
+ * {@link #newInstance(Class)}.<br>
+ * Explicitly made this NON-THREADSAFE for performance reasons.
+ *
+ * @param clazz Class to instantiate
+ * @return Instantiator dedicated to the class
+ */
+ @Override
+ public ObjectInstantiator getInstantiatorOf( Class<?> clazz )
+ {
+ if ( cache == null )
+ {
+ return strategy.newInstantiatorOf( clazz );
+ }
+ ObjectInstantiator instantiator = cache.get( clazz.getName() );
+ if ( instantiator == null )
+ {
+ instantiator = strategy.newInstantiatorOf( clazz );
+ cache.put( clazz.getName(), instantiator );
+ }
+ return instantiator;
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisException.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisException.java
new file mode 100644
index 0000000..53c7c46
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisException.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+/**
+ * Exception thrown by Objenesis. It wraps any instantiation exceptions. Note that this exception is runtime to prevent
+ * having to catch it. It will do normal exception wrapping for JDK 1.4 and more and basic message wrapping for JDK 1.3.
+ *
+ * @author Henri Tremblay
+ */
+public class ObjenesisException
+ extends RuntimeException
+{
+
+ private static final long serialVersionUID = -2677230016262426968L;
+
+ private static final boolean jdk14 =
+ ( Double.parseDouble( System.getProperty( "java.specification.version" ) ) > 1.3 );
+
+ /**
+ * @param msg Error message
+ */
+ public ObjenesisException( String msg )
+ {
+ super( msg );
+ }
+
+ /**
+ * @param cause Wrapped exception. The message will be the one of the cause.
+ */
+ public ObjenesisException( Throwable cause )
+ {
+ super( cause == null ? null : cause.toString() );
+ if ( jdk14 )
+ {
+ initCause( cause );
+ }
+ }
+
+ /**
+ * @param msg Error message
+ * @param cause Wrapped exception
+ */
+ public ObjenesisException( String msg, Throwable cause )
+ {
+ super( msg );
+ if ( jdk14 )
+ {
+ initCause( cause );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisHelper.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisHelper.java
new file mode 100644
index 0000000..24eaae5
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisHelper.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import java.io.Serializable;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+
+/**
+ * Use Objenesis in a static way. <strong>It is strongly not recommended to use this class.</strong>
+ *
+ * @author Henri Tremblay
+ */
+public final class ObjenesisHelper
+{
+
+ private static final ObjectInstantiatorFactory OBJENESIS_STD = new ObjenesisStd();
+
+ private static final ObjectInstantiatorFactory OBJENESIS_SERIALIZER = new ObjenesisSerializer();
+
+ private ObjenesisHelper()
+ {
+ }
+
+ /**
+ * Will create a new object without any constructor being called
+ *
+ * @param clazz Class to instantiate
+ * @return New instance of clazz
+ */
+ public static Object newInstance( Class<?> clazz )
+ {
+ return OBJENESIS_STD.newInstance( clazz );
+ }
+
+ /**
+ * Will create an object just like it's done by ObjectInputStream.readObject (the default constructor of the first
+ * non serializable class will be called)
+ *
+ * @param clazz Class to instantiate
+ * @return New instance of clazz
+ */
+ public static Serializable newSerializableInstance( Class<?> clazz )
+ {
+ return (Serializable) OBJENESIS_SERIALIZER.newInstance( clazz );
+ }
+
+ /**
+ * Will pick the best instantiator for the provided class. If you need to create a lot of instances from the same
+ * class, it is way more efficient to create them from the same ObjectInstantiator than calling
+ * {@link #newInstance(Class)}.
+ *
+ * @param clazz Class to instantiate
+ * @return Instantiator dedicated to the class
+ */
+ public static ObjectInstantiator getInstantiatorOf( Class<?> clazz )
+ {
+ return OBJENESIS_STD.getInstantiatorOf( clazz );
+ }
+
+ /**
+ * Same as {@link #getInstantiatorOf(Class)} but providing an instantiator emulating ObjectInputStream.readObject
+ * behavior.
+ *
+ * @see #newSerializableInstance(Class)
+ * @param clazz Class to instantiate
+ * @return Instantiator dedicated to the class
+ */
+ public static ObjectInstantiator getSerializableObjectInstantiatorOf( Class<?> clazz )
+ {
+ return OBJENESIS_SERIALIZER.getInstantiatorOf( clazz );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisSerializer.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisSerializer.java
new file mode 100644
index 0000000..59d1e34
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisSerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import org.apache.directmemory.lightning.internal.instantiator.strategy.SerializingInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the {@link SerializingInstantiatorStrategy}.
+ *
+ * @author Henri Tremblay
+ */
+public class ObjenesisSerializer
+ extends ObjenesisBase
+{
+
+ /**
+ * Default constructor using the
+ * {@link org.apache.directmemory.lightning.internal.instantiator.strategy.SerializingInstantiatorStrategy}
+ */
+ public ObjenesisSerializer()
+ {
+ super( new SerializingInstantiatorStrategy() );
+ }
+
+ /**
+ * Instance using the
+ * {@link org.apache.directmemory.lightning.internal.instantiator.strategy.SerializingInstantiatorStrategy} with or
+ * without caching {@link org.apache.directmemory.lightning.instantiator.ObjectInstantiator}s
+ *
+ * @param useCache If {@link org.apache.directmemory.lightning.instantiator.ObjectInstantiator} s should be cached
+ */
+ public ObjenesisSerializer( boolean useCache )
+ {
+ super( new SerializingInstantiatorStrategy(), useCache );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisStd.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisStd.java
new file mode 100644
index 0000000..4803229
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/ObjenesisStd.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import org.apache.directmemory.lightning.internal.instantiator.strategy.StdInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the
+ * {@link org.apache.directmemory.lightning.internal.instantiator.strategy.StdInstantiatorStrategy} .
+ *
+ * @author Henri Tremblay
+ */
+public class ObjenesisStd
+ extends ObjenesisBase
+{
+
+ /**
+ * Default constructor using the
+ * {@link org.apache.directmemory.lightning.internal.instantiator.strategy.StdInstantiatorStrategy}
+ */
+ public ObjenesisStd()
+ {
+ super( new StdInstantiatorStrategy() );
+ }
+
+ /**
+ * Instance using the
+ * {@link org.apache.directmemory.lightning.internal.instantiator.strategy.StdInstantiatorStrategy} with or without
+ * caching {@link org.apache.directmemory.lightning.instantiator.ObjectInstantiator}s
+ *
+ * @param useCache If {@link org.apache.directmemory.lightning.instantiator.ObjectInstantiator} s should be cached
+ */
+ public ObjenesisStd( boolean useCache )
+ {
+ super( new StdInstantiatorStrategy(), useCache );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/SerializationInstantiatorHelper.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/SerializationInstantiatorHelper.java
new file mode 100644
index 0000000..0abfe24
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/SerializationInstantiatorHelper.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator;
+
+import java.io.Serializable;
+
+/**
+ * Helper for common serialization-compatible instantiation functions
+ *
+ * @author Leonardo Mesquita
+ */
+public class SerializationInstantiatorHelper
+{
+
+ /**
+ * Returns the first non-serializable superclass of a given class. According to Java Object Serialization
+ * Specification, objects read from a stream are initialized by calling an accessible no-arg constructor from the
+ * first non-serializable superclass in the object's hierarchy, allowing the state of non-serializable fields to be
+ * correctly initialized.
+ *
+ * @param type Serializable class for which the first non-serializable superclass is to be found
+ * @return The first non-serializable superclass of 'type'.
+ * @see java.io.Serializable
+ */
+ public static Class<?> getNonSerializableSuperClass( Class<?> type )
+ {
+ Class<?> result = type;
+ while ( Serializable.class.isAssignableFrom( result ) )
+ {
+ result = result.getSuperclass();
+ if ( result == null )
+ {
+ throw new Error( "Bad class hierarchy: No non-serializable parents" );
+ }
+ }
+ return result;
+
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/AccessibleInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/AccessibleInstantiator.java
new file mode 100644
index 0000000..3462c31
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/AccessibleInstantiator.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.basic;
+
+/**
+ * Instantiates a class by grabbing the no-args constructor, making it accessible and then calling
+ * Constructor.newInstance(). Although this still requires no-arg constructors, it can call non-public constructors (if
+ * the security manager allows it).
+ *
+ * @author Joe Walnes
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class AccessibleInstantiator
+ extends ConstructorInstantiator
+{
+
+ public AccessibleInstantiator( Class<?> type )
+ {
+ super( type );
+ if ( constructor != null )
+ {
+ constructor.setAccessible( true );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ConstructorInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ConstructorInstantiator.java
new file mode 100644
index 0000000..df93435
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ConstructorInstantiator.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.basic;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by grabbing the no args constructor and calling Constructor.newInstance(). This can deal with
+ * default public constructors, but that's about it.
+ *
+ * @author Joe Walnes
+ * @see ObjectInstantiator
+ */
+public class ConstructorInstantiator
+ implements ObjectInstantiator
+{
+
+ protected Constructor<?> constructor;
+
+ public ConstructorInstantiator( Class<?> type )
+ {
+ try
+ {
+ constructor = type.getDeclaredConstructor( (Class[]) null );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return constructor.newInstance( (Object[]) null );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/NewInstanceInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/NewInstanceInstantiator.java
new file mode 100644
index 0000000..d1ebb80
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/NewInstanceInstantiator.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.basic;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * The simplest instantiator - simply calls Class.newInstance(). This can deal with default public constructors, but
+ * that's about it.
+ *
+ * @author Joe Walnes
+ * @see ObjectInstantiator
+ */
+public class NewInstanceInstantiator
+ implements ObjectInstantiator
+{
+
+ private final Class<?> type;
+
+ public NewInstanceInstantiator( Class<?> type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return type.newInstance();
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectInputStreamInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectInputStreamInstantiator.java
new file mode 100644
index 0000000..d4b08cd
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectInputStreamInstantiator.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.basic;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.ObjectStreamConstants;
+import java.io.Serializable;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by using a dummy input stream that always feeds data for an empty object of the same kind. NOTE:
+ * This instantiator may not work properly if the class being instantiated defines a "readResolve" method, since it may
+ * return objects that have been returned previously (i.e., there's no guarantee that the returned object is a new one),
+ * or even objects from a completely different class.
+ *
+ * @author Leonardo Mesquita
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class ObjectInputStreamInstantiator
+ implements ObjectInstantiator
+{
+
+ private static class MockStream
+ extends InputStream
+ {
+
+ private int pointer;
+
+ private byte[] data;
+
+ private int sequence;
+
+ private static final int[] NEXT = new int[] { 1, 2, 2 };
+
+ private byte[][] buffers;
+
+ private final byte[] FIRST_DATA;
+
+ private static byte[] HEADER;
+
+ private static byte[] REPEATING_DATA;
+
+ static
+ {
+ initialize();
+ }
+
+ private static void initialize()
+ {
+ try
+ {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ DataOutputStream dout = new DataOutputStream( byteOut );
+ dout.writeShort( ObjectStreamConstants.STREAM_MAGIC );
+ dout.writeShort( ObjectStreamConstants.STREAM_VERSION );
+ HEADER = byteOut.toByteArray();
+
+ byteOut = new ByteArrayOutputStream();
+ dout = new DataOutputStream( byteOut );
+
+ dout.writeByte( ObjectStreamConstants.TC_OBJECT );
+ dout.writeByte( ObjectStreamConstants.TC_REFERENCE );
+ dout.writeInt( ObjectStreamConstants.baseWireHandle );
+ REPEATING_DATA = byteOut.toByteArray();
+ }
+ catch ( IOException e )
+ {
+ throw new Error( "IOException: " + e.getMessage() );
+ }
+
+ }
+
+ public MockStream( Class<?> clazz )
+ {
+ this.pointer = 0;
+ this.sequence = 0;
+ this.data = HEADER;
+
+ // (byte) TC_OBJECT
+ // (byte) TC_CLASSDESC
+ // (short length)
+ // (byte * className.length)
+ // (long)serialVersionUID
+ // (byte) SC_SERIALIZABLE
+ // (short)0 <fields>
+ // TC_ENDBLOCKDATA
+ // TC_NULL
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ DataOutputStream dout = new DataOutputStream( byteOut );
+ try
+ {
+ dout.writeByte( ObjectStreamConstants.TC_OBJECT );
+ dout.writeByte( ObjectStreamConstants.TC_CLASSDESC );
+ dout.writeUTF( clazz.getName() );
+ dout.writeLong( ObjectStreamClass.lookup( clazz ).getSerialVersionUID() );
+ dout.writeByte( ObjectStreamConstants.SC_SERIALIZABLE );
+ dout.writeShort( (short) 0 ); // Zero fields
+ dout.writeByte( ObjectStreamConstants.TC_ENDBLOCKDATA );
+ dout.writeByte( ObjectStreamConstants.TC_NULL );
+ }
+ catch ( IOException e )
+ {
+ throw new Error( "IOException: " + e.getMessage() );
+ }
+ this.FIRST_DATA = byteOut.toByteArray();
+ buffers = new byte[][] { HEADER, FIRST_DATA, REPEATING_DATA };
+ }
+
+ private void advanceBuffer()
+ {
+ pointer = 0;
+ sequence = NEXT[sequence];
+ data = buffers[sequence];
+ }
+
+ @Override
+ public int read()
+ throws IOException
+ {
+ int result = data[pointer++];
+ if ( pointer >= data.length )
+ {
+ advanceBuffer();
+ }
+
+ return result;
+ }
+
+ @Override
+ public int available()
+ throws IOException
+ {
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public int read( byte[] b, int off, int len )
+ throws IOException
+ {
+ int left = len;
+ int remaining = data.length - pointer;
+
+ while ( remaining <= left )
+ {
+ System.arraycopy( data, pointer, b, off, remaining );
+ off += remaining;
+ left -= remaining;
+ advanceBuffer();
+ remaining = data.length - pointer;
+ }
+ if ( left > 0 )
+ {
+ System.arraycopy( data, pointer, b, off, left );
+ pointer += left;
+ }
+
+ return len;
+ }
+ }
+
+ private ObjectInputStream inputStream;
+
+ public ObjectInputStreamInstantiator( Class<?> clazz )
+ {
+ if ( Serializable.class.isAssignableFrom( clazz ) )
+ {
+ try
+ {
+ this.inputStream = new ObjectInputStream( new MockStream( clazz ) );
+ }
+ catch ( IOException e )
+ {
+ throw new Error( "IOException: " + e.getMessage() );
+ }
+ }
+ else
+ {
+ throw new ObjenesisException( new NotSerializableException( clazz + " not serializable" ) );
+ }
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return inputStream.readObject();
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new Error( "ClassNotFoundException: " + e.getMessage() );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectStreamClassInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectStreamClassInstantiator.java
new file mode 100644
index 0000000..5ca72c8
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/basic/ObjectStreamClassInstantiator.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.basic;
+
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by using reflection to make a call to private method ObjectStreamClass.newInstance, present in
+ * many JVM implementations. This instantiator will create classes in a way compatible with serialization, calling the
+ * first non-serializable superclass' no-arg constructor.
+ *
+ * @author Leonardo Mesquita
+ * @see ObjectInstantiator
+ * @see java.io.Serializable
+ */
+public class ObjectStreamClassInstantiator
+ implements ObjectInstantiator
+{
+
+ private static Method newInstanceMethod;
+
+ private static void initialize()
+ {
+ if ( newInstanceMethod == null )
+ {
+ try
+ {
+ newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod( "newInstance", new Class[] {} );
+ newInstanceMethod.setAccessible( true );
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+ }
+
+ private final ObjectStreamClass objStreamClass;
+
+ public ObjectStreamClassInstantiator( Class<?> type )
+ {
+ initialize();
+ objStreamClass = ObjectStreamClass.lookup( type );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return newInstanceMethod.invoke( objStreamClass, new Object[] {} );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiator.java
new file mode 100644
index 0000000..bc09305
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.gcj;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to work on GCJ JVMs. This
+ * instantiator will not call any constructors.
+ *
+ * @author Leonardo Mesquita
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class GCJInstantiator
+ extends GCJInstantiatorBase
+{
+
+ public GCJInstantiator( Class<?> type )
+ {
+ super( type );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return newObjectMethod.invoke( dummyStream, new Object[] { type, Object.class } );
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( InvocationTargetException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiatorBase.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiatorBase.java
new file mode 100644
index 0000000..b4a965f
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJInstantiatorBase.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.gcj;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Base class for GCJ-based instantiators. It initializes reflection access to method ObjectInputStream.newObject, as
+ * well as creating a dummy ObjectInputStream to be used as the "this" argument for the method.
+ *
+ * @author Leonardo Mesquita
+ */
+public abstract class GCJInstantiatorBase
+ implements ObjectInstantiator
+{
+
+ protected static Method newObjectMethod = null;
+
+ protected static ObjectInputStream dummyStream;
+
+ private static class DummyStream
+ extends ObjectInputStream
+ {
+
+ public DummyStream()
+ throws IOException
+ {
+ }
+ }
+
+ private static void initialize()
+ {
+ if ( newObjectMethod == null )
+ {
+ try
+ {
+ newObjectMethod =
+ ObjectInputStream.class.getDeclaredMethod( "newObject", new Class[] { Class.class, Class.class } );
+ newObjectMethod.setAccessible( true );
+ dummyStream = new DummyStream();
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( IOException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+ }
+
+ protected final Class<?> type;
+
+ public GCJInstantiatorBase( Class<?> type )
+ {
+ this.type = type;
+ initialize();
+ }
+
+ @Override
+ public abstract Object newInstance();
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJSerializationInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJSerializationInstantiator.java
new file mode 100644
index 0000000..2875407
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/gcj/GCJSerializationInstantiator.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.gcj;
+
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+import org.apache.directmemory.lightning.internal.instantiator.SerializationInstantiatorHelper;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to work on GCJ JVMs. This
+ * instantiator will create classes in a way compatible with serialization, calling the first non-serializable
+ * superclass' no-arg constructor.
+ *
+ * @author Leonardo Mesquita
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class GCJSerializationInstantiator
+ extends GCJInstantiatorBase
+{
+
+ private Class<?> superType;
+
+ public GCJSerializationInstantiator( Class<?> type )
+ {
+ super( type );
+ this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return newObjectMethod.invoke( dummyStream, new Object[] { type, superType } );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercInstantiator.java
new file mode 100644
index 0000000..8ca5adb
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercInstantiator.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.perc;
+
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal Perc private methods. It is only supposed to work on Perc JVMs.
+ * This instantiator will not call any constructors. The code was provided by Aonix Perc support team.
+ *
+ * @author Henri Tremblay
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class PercInstantiator
+ implements ObjectInstantiator
+{
+
+ private final Method newInstanceMethod;
+
+ private final Object[] typeArgs = new Object[] { null, Boolean.FALSE };
+
+ public PercInstantiator( Class<?> type )
+ {
+
+ typeArgs[0] = type;
+
+ try
+ {
+ newInstanceMethod =
+ ObjectInputStream.class.getDeclaredMethod( "newInstance", new Class[] { Class.class, Boolean.TYPE } );
+ newInstanceMethod.setAccessible( true );
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return newInstanceMethod.invoke( null, typeArgs );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercSerializationInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercSerializationInstantiator.java
new file mode 100644
index 0000000..e695e5c
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/perc/PercSerializationInstantiator.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.perc;
+
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal Perc private methods. It is only supposed to work on Perc JVMs.
+ * This instantiator will create classes in a way compatible with serialization, calling the first non-serializable
+ * superclass' no-arg constructor.
+ * <p/>
+ * Based on code provided by Aonix but <b>doesn't work right now</b>
+ *
+ * @author Henri Tremblay
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class PercSerializationInstantiator
+ implements ObjectInstantiator
+{
+
+ private Object[] typeArgs;
+
+ private final java.lang.reflect.Method newInstanceMethod;
+
+ public PercSerializationInstantiator( Class<?> type )
+ {
+
+ // Find the first unserializable parent class
+ Class<?> unserializableType = type;
+
+ while ( Serializable.class.isAssignableFrom( unserializableType ) )
+ {
+ unserializableType = unserializableType.getSuperclass();
+ }
+
+ try
+ {
+ // Get the special Perc method to call
+ Class<?> percMethodClass = Class.forName( "COM.newmonics.PercClassLoader.Method" );
+
+ newInstanceMethod =
+ ObjectInputStream.class.getDeclaredMethod( "noArgConstruct", new Class[] { Class.class, Object.class,
+ percMethodClass } );
+ newInstanceMethod.setAccessible( true );
+
+ // Create invoke params
+ Class<?> percClassClass = Class.forName( "COM.newmonics.PercClassLoader.PercClass" );
+ Method getPercClassMethod = percClassClass.getDeclaredMethod( "getPercClass", new Class[] { Class.class } );
+ Object someObject = getPercClassMethod.invoke( null, new Object[] { unserializableType } );
+ Method findMethodMethod =
+ someObject.getClass().getDeclaredMethod( "findMethod", new Class[] { String.class } );
+ Object percMethod = findMethodMethod.invoke( someObject, new Object[] { "<init>()V" } );
+
+ typeArgs = new Object[] { unserializableType, type, percMethod };
+
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( InvocationTargetException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return newInstanceMethod.invoke( null, typeArgs );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( InvocationTargetException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/BaseInstantiatorStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/BaseInstantiatorStrategy.java
new file mode 100644
index 0000000..db3ecad
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/BaseInstantiatorStrategy.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.strategy;
+
+/**
+ * Base {@link InstantiatorStrategy} class basically containing helpful constant to sort out JVMs.
+ *
+ * @author Henri Tremblay
+ */
+public abstract class BaseInstantiatorStrategy
+ implements InstantiatorStrategy
+{
+
+ /** JVM_NAME prefix for BEA releases of JRockit */
+ protected static final String BEA_JROCKIT = "BEA";
+
+ /** JVM_NAME prefix for Oracle releases of JRockit */
+ protected static final String ORACLE_JROCKIT = "Oracle JRockit(R)";
+
+ /** JVM_NAME prefix for GCJ */
+ protected static final String GNU = "GNU libgcj";
+
+ /** JVM_NAME prefix for Sun Java HotSpot */
+ protected static final String SUN = "Java HotSpot";
+
+ /** JVM_NAME prefix for Aonix PERC */
+ protected static final String PERC = "PERC";
+
+ /** JVM version */
+ protected static final String VM_VERSION = System.getProperty( "java.runtime.version" );
+
+ /** JVM version */
+ protected static final String VM_INFO = System.getProperty( "java.vm.info" );
+
+ /** Vendor version */
+ protected static final String VENDOR_VERSION = System.getProperty( "java.vm.version" );
+
+ /** Vendor name */
+ protected static final String VENDOR = System.getProperty( "java.vm.vendor" );
+
+ /** JVM name */
+ protected static final String JVM_NAME = System.getProperty( "java.vm.name" );
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/InstantiatorStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/InstantiatorStrategy.java
new file mode 100644
index 0000000..9df7a13
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/InstantiatorStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.strategy;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+
+/**
+ * Defines a strategy to determine the best instantiator for a class.
+ *
+ * @author Henri Tremblay
+ */
+public interface InstantiatorStrategy
+{
+
+ /**
+ * Create a dedicated instantiator for the given class
+ *
+ * @param type Class that will be instantiate
+ * @return Dedicated instantiator
+ */
+ ObjectInstantiator newInstantiatorOf( Class<?> type );
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/SerializingInstantiatorStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/SerializingInstantiatorStrategy.java
new file mode 100644
index 0000000..042c999
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/SerializingInstantiatorStrategy.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.strategy;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.basic.ObjectStreamClassInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.gcj.GCJSerializationInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.perc.PercSerializationInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.sun.Sun13SerializationInstantiator;
+import org.apache.directmemory.lightning.internal.util.InternalUtil;
+
+/**
+ * Guess the best serializing instantiator for a given class. The returned instantiator will instantiate classes like
+ * the genuine java serialization framework (the constructor of the first not serializable class will be called).
+ * Currently, the selection doesn't depend on the class. It relies on the
+ * <ul>
+ * <li>JVM version</li>
+ * <li>JVM vendor</li>
+ * <li>JVM vendor version</li>
+ * </ul>
+ * However, instantiators are stateful and so dedicated to their class.
+ *
+ * @author Henri Tremblay
+ * @see ObjectInstantiator
+ */
+public class SerializingInstantiatorStrategy
+ extends BaseInstantiatorStrategy
+{
+
+ /**
+ * Return an {@link ObjectInstantiator} allowing to create instance following the java serialization framework
+ * specifications.
+ *
+ * @param type Class to instantiate
+ * @return The ObjectInstantiator for the class
+ */
+ @Override
+ public ObjectInstantiator newInstantiatorOf( Class<?> type )
+ {
+ if ( JVM_NAME.startsWith( SUN ) )
+ {
+ if ( VM_VERSION.startsWith( "1.3" ) )
+ {
+ return new Sun13SerializationInstantiator( type );
+ }
+ else if ( InternalUtil.isUnsafeAvailable() )
+ {
+ return InternalUtil.buildSunUnsafeInstantiator( type );
+ }
+ }
+ else if ( JVM_NAME.startsWith( GNU ) )
+ {
+ return new GCJSerializationInstantiator( type );
+ }
+ else if ( JVM_NAME.startsWith( PERC ) )
+ {
+ return new PercSerializationInstantiator( type );
+ }
+
+ return new ObjectStreamClassInstantiator( type );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/StdInstantiatorStrategy.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/StdInstantiatorStrategy.java
new file mode 100644
index 0000000..72f1351
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/strategy/StdInstantiatorStrategy.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.strategy;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.gcj.GCJInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.perc.PercInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.sun.Sun13Instantiator;
+import org.apache.directmemory.lightning.internal.instantiator.sun.SunReflectionFactoryInstantiator;
+import org.apache.directmemory.lightning.internal.util.InternalUtil;
+
+/**
+ * Guess the best instantiator for a given class. The instantiator will instantiate the class without calling any
+ * constructor. Currently, the selection doesn't depend on the class. It relies on the
+ * <ul>
+ * <li>JVM version</li>
+ * <li>JVM vendor</li>
+ * <li>JVM vendor version</li>
+ * </ul>
+ * However, instantiators are stateful and so dedicated to their class.
+ *
+ * @author Henri Tremblay
+ * @see ObjectInstantiator
+ */
+public class StdInstantiatorStrategy
+ extends BaseInstantiatorStrategy
+{
+
+ /**
+ * Return an {@link ObjectInstantiator} allowing to create instance without any constructor being called.
+ *
+ * @param type Class to instantiate
+ * @return The ObjectInstantiator for the class
+ */
+ @Override
+ public ObjectInstantiator newInstantiatorOf( Class<?> type )
+ {
+
+ if ( JVM_NAME.startsWith( SUN ) )
+ {
+ if ( VM_VERSION.startsWith( "1.3" ) )
+ {
+ return new Sun13Instantiator( type );
+ }
+ else if ( InternalUtil.isUnsafeAvailable() )
+ {
+ return InternalUtil.buildSunUnsafeInstantiator( type );
+ }
+ }
+ else if ( JVM_NAME.startsWith( ORACLE_JROCKIT ) )
+ {
+ if ( !VENDOR_VERSION.startsWith( "R" ) )
+ {
+ // Beginning with R25.1 sun.misc.Unsafe should work.
+ if ( InternalUtil.isUnsafeAvailable() )
+ {
+ return InternalUtil.buildSunUnsafeInstantiator( type );
+ }
+ }
+ }
+ else if ( JVM_NAME.startsWith( GNU ) )
+ {
+ return new GCJInstantiator( type );
+ }
+ else if ( JVM_NAME.startsWith( PERC ) )
+ {
+ return new PercInstantiator( type );
+ }
+
+ // Fallback instantiator, should work with:
+ // - Java Hotspot version 1.4 and higher
+ // - JRockit 1.4-R26 and higher
+ // - IBM and Hitachi JVMs
+ // ... might works for others so we just give it a try
+ return new SunReflectionFactoryInstantiator( type );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13Instantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13Instantiator.java
new file mode 100644
index 0000000..c984adc
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13Instantiator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Instantiates a class by making a call to internal Sun private methods. It is only supposed to work on Sun HotSpot 1.3
+ * JVM. This instantiator will not call any constructors.
+ *
+ * @author Leonardo Mesquita
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class Sun13Instantiator
+ extends Sun13InstantiatorBase
+{
+
+ public Sun13Instantiator( Class<?> type )
+ {
+ super( type );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return allocateNewObjectMethod.invoke( null, new Object[] { type, Object.class } );
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( InvocationTargetException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13InstantiatorBase.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13InstantiatorBase.java
new file mode 100644
index 0000000..b64f33b
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13InstantiatorBase.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+/**
+ * Base class for Sun 1.3 based instantiators. It initializes reflection access to static method
+ * ObjectInputStream.allocateNewObject.
+ *
+ * @author Leonardo Mesquita
+ */
+public abstract class Sun13InstantiatorBase
+ implements ObjectInstantiator
+{
+
+ protected static Method allocateNewObjectMethod = null;
+
+ private static void initialize()
+ {
+ if ( allocateNewObjectMethod == null )
+ {
+ try
+ {
+ allocateNewObjectMethod =
+ ObjectInputStream.class.getDeclaredMethod( "allocateNewObject", new Class[] { Class.class,
+ Class.class } );
+ allocateNewObjectMethod.setAccessible( true );
+ }
+ catch ( RuntimeException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+ }
+
+ protected final Class<?> type;
+
+ public Sun13InstantiatorBase( Class<?> type )
+ {
+ this.type = type;
+ initialize();
+ }
+
+ @Override
+ public abstract Object newInstance();
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13SerializationInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13SerializationInstantiator.java
new file mode 100644
index 0000000..904b581
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/Sun13SerializationInstantiator.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+import org.apache.directmemory.lightning.internal.instantiator.SerializationInstantiatorHelper;
+
+/**
+ * Instantiates a class by making a call to internal Sun private methods. It is only supposed to work on Sun HotSpot 1.3
+ * JVM. This instantiator will create classes in a way compatible with serialization, calling the first non-serializable
+ * superclass' no-arg constructor.
+ *
+ * @author Leonardo Mesquita
+ * @see org.apache.directmemory.lightning.instantiator.ObjectInstantiator
+ */
+public class Sun13SerializationInstantiator
+ extends Sun13InstantiatorBase
+{
+
+ private final Class<?> superType;
+
+ public Sun13SerializationInstantiator( Class<?> type )
+ {
+ super( type );
+ this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return allocateNewObjectMethod.invoke( null, new Object[] { type, superType } );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactoryInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactoryInstantiator.java
new file mode 100644
index 0000000..b88082d
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactoryInstantiator.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+
+import sun.reflect.ReflectionFactory;
+
+/**
+ * Instantiates an object, WITHOUT calling it's constructor, using internal sun.reflect.ReflectionFactory - a class only
+ * available on JDK's that use Sun's 1.4 (or later) Java implementation. This is the best way to instantiate an object
+ * without any side effects caused by the constructor - however it is not available on every platform.
+ *
+ * @author Joe Walnes
+ * @see ObjectInstantiator
+ */
+@SuppressWarnings( "restriction" )
+public class SunReflectionFactoryInstantiator
+ implements ObjectInstantiator
+{
+
+ private final Constructor<?> mungedConstructor;
+
+ public SunReflectionFactoryInstantiator( Class<?> type )
+ {
+
+ ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
+ Constructor<?> javaLangObjectConstructor;
+
+ try
+ {
+ javaLangObjectConstructor = Object.class.getConstructor( (Class[]) null );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ throw new Error( "Cannot find constructor for java.lang.Object!" );
+ }
+ mungedConstructor = reflectionFactory.newConstructorForSerialization( type, javaLangObjectConstructor );
+ mungedConstructor.setAccessible( true );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return mungedConstructor.newInstance( (Object[]) null );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactorySerializationInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
new file mode 100644
index 0000000..e9be184
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import java.io.NotSerializableException;
+import java.lang.reflect.Constructor;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.instantiator.ObjenesisException;
+import org.apache.directmemory.lightning.internal.instantiator.SerializationInstantiatorHelper;
+
+import sun.reflect.ReflectionFactory;
+
+/**
+ * Instantiates an object using internal sun.reflect.ReflectionFactory - a class only available on JDK's that use Sun's
+ * 1.4 (or later) Java implementation. This instantiator will create classes in a way compatible with serialization,
+ * calling the first non-serializable superclass' no-arg constructor. This is the best way to instantiate an object
+ * without any side effects caused by the constructor - however it is not available on every platform.
+ *
+ * @author Leonardo Mesquita
+ * @see ObjectInstantiator
+ */
+@SuppressWarnings( "restriction" )
+public class SunReflectionFactorySerializationInstantiator
+ implements ObjectInstantiator
+{
+
+ private final Constructor<?> mungedConstructor;
+
+ public SunReflectionFactorySerializationInstantiator( Class<?> type )
+ {
+
+ Class<?> nonSerializableAncestor = SerializationInstantiatorHelper.getNonSerializableSuperClass( type );
+ ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
+ Constructor<?> nonSerializableAncestorConstructor;
+ try
+ {
+ nonSerializableAncestorConstructor = nonSerializableAncestor.getConstructor( (Class[]) null );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ /**
+ * @todo (Henri) I think we should throw a NotSerializableException just to put the same message a
+ * ObjectInputStream. Otherwise, the user won't know if the null returned if a "Not serializable", a
+ * "No default constructor on ancestor" or a "Exception in constructor"
+ */
+ throw new ObjenesisException( new NotSerializableException( type
+ + " has no suitable superclass constructor" ) );
+ }
+
+ mungedConstructor = reflectionFactory.newConstructorForSerialization( type, nonSerializableAncestorConstructor );
+ mungedConstructor.setAccessible( true );
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ return mungedConstructor.newInstance( (Object[]) null );
+ }
+ catch ( Exception e )
+ {
+ throw new ObjenesisException( e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunUnsafeAllocateInstanceInstantiator.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunUnsafeAllocateInstanceInstantiator.java
new file mode 100644
index 0000000..21bbd4a
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/instantiator/sun/SunUnsafeAllocateInstanceInstantiator.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.instantiator.sun;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.util.UnsafeUtil;
+
+@SuppressWarnings( "restriction" )
+public class SunUnsafeAllocateInstanceInstantiator
+ implements ObjectInstantiator
+{
+
+ private static final sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe();
+
+ protected final Class<?> type;
+
+ public SunUnsafeAllocateInstanceInstantiator( Class<?> type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public Object newInstance()
+ {
+ try
+ {
+ if ( UNSAFE != null )
+ return UNSAFE.allocateInstance( type );
+ }
+ catch ( Exception e )
+ {
+ // ignore and return null
+ }
+
+ return null;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferInputStream.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferInputStream.java
new file mode 100644
index 0000000..7cc3e78
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferInputStream.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class BufferInputStream
+ extends InputStream
+{
+
+ private final ByteBuffer byteBuffer;
+
+ public BufferInputStream( ByteBuffer byteBuffer )
+ {
+ this.byteBuffer = byteBuffer;
+ }
+
+ @Override
+ public synchronized int read()
+ throws IOException
+ {
+ if ( !byteBuffer.hasRemaining() )
+ {
+ return -1;
+ }
+ return byteBuffer.get();
+ }
+
+ @Override
+ public synchronized int read( byte[] bytes, int off, int len )
+ throws IOException
+ {
+ len = Math.min( len, byteBuffer.remaining() );
+ byteBuffer.get( bytes, off, len );
+ return len;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferOutputStream.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferOutputStream.java
new file mode 100644
index 0000000..8c21645
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/BufferOutputStream.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class BufferOutputStream
+ extends OutputStream
+{
+
+ private final ByteBuffer byteBuffer;
+
+ public BufferOutputStream( ByteBuffer byteBuffer )
+ {
+ this.byteBuffer = byteBuffer;
+ }
+
+ @Override
+ public synchronized void write( int b )
+ throws IOException
+ {
+ byteBuffer.put( (byte) b );
+ }
+
+ @Override
+ public synchronized void write( byte[] bytes, int off, int len )
+ throws IOException
+ {
+ byteBuffer.put( bytes, off, len );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/ReaderInputStream.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/ReaderInputStream.java
new file mode 100644
index 0000000..f8431fc
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/ReaderInputStream.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+public class ReaderInputStream
+ extends InputStream
+{
+
+ /** Source Reader */
+ private Reader in;
+
+ private String encoding = System.getProperty( "file.encoding" );
+
+ private byte[] slack;
+
+ private int begin;
+
+ /**
+ * Construct a <CODE>ReaderInputStream</CODE> for the specified <CODE>Reader</CODE>.
+ *
+ * @param reader <CODE>Reader</CODE>. Must not be <code>null</code>.
+ */
+ public ReaderInputStream( Reader reader )
+ {
+ in = reader;
+ }
+
+ /**
+ * Construct a <CODE>ReaderInputStream</CODE> for the specified <CODE>Reader</CODE>, with the specified encoding.
+ *
+ * @param reader non-null <CODE>Reader</CODE>.
+ * @param encoding non-null <CODE>String</CODE> encoding.
+ */
+ public ReaderInputStream( Reader reader, String encoding )
+ {
+ this( reader );
+ if ( encoding == null )
+ {
+ throw new IllegalArgumentException( "encoding must not be null" );
+ }
+ else
+ {
+ this.encoding = encoding;
+ }
+ }
+
+ /**
+ * Reads from the <CODE>Reader</CODE>, returning the same value.
+ *
+ * @return the value of the next character in the <CODE>Reader</CODE>.
+ * @exception IOException if the original <code>Reader</code> fails to be read
+ */
+ @Override
+ public synchronized int read()
+ throws IOException
+ {
+ if ( in == null )
+ {
+ throw new IOException( "Stream Closed" );
+ }
+
+ byte result;
+ if ( slack != null && begin < slack.length )
+ {
+ result = slack[begin];
+ if ( ++begin == slack.length )
+ {
+ slack = null;
+ }
+ }
+ else
+ {
+ byte[] buf = new byte[1];
+ if ( read( buf, 0, 1 ) <= 0 )
+ {
+ result = -1;
+ }
+ result = buf[0];
+ }
+
+ if ( result < -1 )
+ {
+ result += 256;
+ }
+
+ return result;
+ }
+
+ /**
+ * Reads from the <code>Reader</code> into a byte array
+ *
+ * @param b the byte array to read into
+ * @param off the offset in the byte array
+ * @param len the length in the byte array to fill
+ * @return the actual number read into the byte array, -1 at the end of the stream
+ * @exception IOException if an error occurs
+ */
+ @Override
+ public synchronized int read( byte[] b, int off, int len )
+ throws IOException
+ {
+ if ( in == null )
+ {
+ throw new IOException( "Stream Closed" );
+ }
+
+ while ( slack == null )
+ {
+ char[] buf = new char[len]; // might read too much
+ int n = in.read( buf );
+ if ( n == -1 )
+ {
+ return -1;
+ }
+ if ( n > 0 )
+ {
+ slack = new String( buf, 0, n ).getBytes( encoding );
+ begin = 0;
+ }
+ }
+
+ if ( len > slack.length - begin )
+ {
+ len = slack.length - begin;
+ }
+
+ System.arraycopy( slack, begin, b, off, len );
+
+ if ( ( begin += len ) >= slack.length )
+ {
+ slack = null;
+ }
+
+ return len;
+ }
+
+ /**
+ * Marks the read limit of the StringReader.
+ *
+ * @param limit the maximum limit of bytes that can be read before the mark position becomes invalid
+ */
+ @Override
+ public synchronized void mark( final int limit )
+ {
+ try
+ {
+ in.mark( limit );
+ }
+ catch ( IOException ioe )
+ {
+ throw new RuntimeException( ioe.getMessage() );
+ }
+ }
+
+ /**
+ * @return the current number of bytes ready for reading
+ * @exception IOException if an error occurs
+ */
+ @Override
+ public synchronized int available()
+ throws IOException
+ {
+ if ( in == null )
+ {
+ throw new IOException( "Stream Closed" );
+ }
+ if ( slack != null )
+ {
+ return slack.length - begin;
+ }
+ if ( in.ready() )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ /**
+ * @return false - mark is not supported
+ */
+ @Override
+ public boolean markSupported()
+ {
+ return false; // would be imprecise
+ }
+
+ /**
+ * Resets the StringReader.
+ *
+ * @exception IOException if the StringReader fails to be reset
+ */
+ @Override
+ public synchronized void reset()
+ throws IOException
+ {
+ if ( in == null )
+ {
+ throw new IOException( "Stream Closed" );
+ }
+ slack = null;
+ in.reset();
+ }
+
+ /**
+ * Closes the Stringreader.
+ *
+ * @exception IOException if the original StringReader fails to be closed
+ */
+ @Override
+ public synchronized void close()
+ throws IOException
+ {
+ if ( in != null )
+ {
+ in.close();
+ slack = null;
+ in = null;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/WriterOutputStream.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/WriterOutputStream.java
new file mode 100644
index 0000000..2120bb9
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/io/WriterOutputStream.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/* ------------------------------------------------------------ */
+/**
+ * Wrap a Writer as an OutputStream. When all you have is a Writer and only an OutputStream will do. Try not to use this
+ * as it indicates that your design is a dogs breakfast (JSP made me write it).
+ *
+ * @author Greg Wilkins (gregw) - Mort Bay Consulting Pty. Ltd.
+ */
+public class WriterOutputStream
+ extends OutputStream
+{
+
+ protected Writer _writer;
+
+ protected String _encoding;
+
+ private byte[] _buf = new byte[1];
+
+ /* ------------------------------------------------------------ */
+ public WriterOutputStream( Writer writer, String encoding )
+ {
+ _writer = writer;
+ _encoding = encoding;
+ }
+
+ /* ------------------------------------------------------------ */
+ public WriterOutputStream( Writer writer )
+ {
+ _writer = writer;
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void close()
+ throws IOException
+ {
+ _writer.close();
+ _writer = null;
+ _encoding = null;
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void flush()
+ throws IOException
+ {
+ _writer.flush();
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void write( byte[] b )
+ throws IOException
+ {
+ if ( _encoding == null )
+ _writer.write( new String( b ) );
+ else
+ _writer.write( new String( b, _encoding ) );
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void write( byte[] b, int off, int len )
+ throws IOException
+ {
+ if ( _encoding == null )
+ _writer.write( new String( b, off, len ) );
+ else
+ _writer.write( new String( b, off, len, _encoding ) );
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public synchronized void write( int b )
+ throws IOException
+ {
+ _buf[0] = (byte) b;
+ write( _buf );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshaller.java
new file mode 100644
index 0000000..7a4acc6
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshaller.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.charset.Charset;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class BigDecimalMarshaller
+ extends AbstractMarshaller
+{
+
+ private static final Charset CHARSET = Charset.forName( "ASCII" );
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return BigDecimal.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ String representation = ( (BigDecimal) value ).toString();
+ byte[] data = representation.getBytes( CHARSET );
+ dataOutput.writeInt( data.length );
+ dataOutput.write( data );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int length = dataInput.readInt();
+ byte[] data = new byte[length];
+ dataInput.readFully( data );
+
+ return (V) new BigDecimal( new String( data, CHARSET ) );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshaller.java
new file mode 100644
index 0000000..f71f21f
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshaller.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class BigIntegerMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return BigInteger.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ byte[] data = ( (BigInteger) value ).toByteArray();
+ dataOutput.writeInt( data.length );
+ dataOutput.write( data );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int length = dataInput.readInt();
+ byte[] data = new byte[length];
+ dataInput.readFully( data );
+
+ return (V) new BigInteger( data );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanArrayMarshaller.java
new file mode 100644
index 0000000..ea696bd
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class BooleanArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return boolean[].class == type || Boolean[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( boolean[].class == propertyDescriptor.getType() )
+ {
+ boolean[] array = (boolean[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( boolean arrayValue : array )
+ {
+ dataOutput.writeBoolean( arrayValue );
+ }
+ }
+ else
+ {
+ Boolean[] array = (Boolean[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( boolean arrayValue : array )
+ {
+ dataOutput.writeBoolean( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( boolean[].class == propertyDescriptor.getType() )
+ {
+ boolean[] array = new boolean[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readBoolean();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Boolean[] array = new Boolean[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readBoolean();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshaller.java
new file mode 100644
index 0000000..061ac0f
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class BooleanMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return boolean.class == type || Boolean.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Boolean.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeBoolean( (Boolean) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Boolean.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Boolean.valueOf( dataInput.readBoolean() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteArrayMarshaller.java
new file mode 100644
index 0000000..a3e5c8a
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ByteArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return byte[].class == type || Byte[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( byte[].class == propertyDescriptor.getType() )
+ {
+ byte[] array = (byte[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( byte arrayValue : array )
+ {
+ dataOutput.writeByte( arrayValue );
+ }
+ }
+ else
+ {
+ Byte[] array = (Byte[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( byte arrayValue : array )
+ {
+ dataOutput.writeByte( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( byte[].class == propertyDescriptor.getType() )
+ {
+ byte[] array = new byte[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readByte();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Byte[] array = new Byte[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readByte();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshaller.java
new file mode 100644
index 0000000..0e112cf
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ByteMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return byte.class == type || Byte.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Byte.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeByte( (Byte) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Byte.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Byte.valueOf( dataInput.readByte() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterArrayMarshaller.java
new file mode 100644
index 0000000..bb19e74
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class CharacterArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return char[].class == type || Character[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( char[].class == propertyDescriptor.getType() )
+ {
+ char[] array = (char[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( char arrayValue : array )
+ {
+ dataOutput.writeChar( arrayValue );
+ }
+ }
+ else
+ {
+ Character[] array = (Character[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( char arrayValue : array )
+ {
+ dataOutput.writeChar( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( char[].class == propertyDescriptor.getType() )
+ {
+ char[] array = new char[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readChar();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Character[] array = new Character[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readChar();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshaller.java
new file mode 100644
index 0000000..337bdff
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class CharacterMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return char.class == type || Character.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Character.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeChar( (Character) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Character.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Character.valueOf( dataInput.readChar() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleArrayMarshaller.java
new file mode 100644
index 0000000..7acdaec
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class DoubleArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return double[].class == type || Double[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( double[].class == propertyDescriptor.getType() )
+ {
+ double[] array = (double[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( double arrayValue : array )
+ {
+ dataOutput.writeDouble( arrayValue );
+ }
+ }
+ else
+ {
+ Double[] array = (Double[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( double arrayValue : array )
+ {
+ dataOutput.writeDouble( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( double[].class == propertyDescriptor.getType() )
+ {
+ double[] array = new double[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readDouble();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Double[] array = new Double[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readDouble();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshaller.java
new file mode 100644
index 0000000..a668f70
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class DoubleMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return double.class == type || Double.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Double.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeDouble( (Double) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Double.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Double.valueOf( dataInput.readDouble() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/EnumMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/EnumMarshaller.java
new file mode 100644
index 0000000..907dc79
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/EnumMarshaller.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class EnumMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Enum.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ dataOutput.writeLong( serializationContext.getClassDefinitionContainer().getClassDefinitionByType( propertyDescriptor.getType() ).getId() );
+ dataOutput.writeInt( ( (Enum<?>) value ).ordinal() );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ long typeId = dataInput.readLong();
+ Class<?> propertyType = serializationContext.getClassDefinitionContainer().getTypeById( typeId );
+
+ int ordinal = dataInput.readInt();
+ Enum<?>[] values = ( (Class<Enum<?>>) propertyType ).getEnumConstants();
+ for ( Enum<?> value : values )
+ {
+ if ( value.ordinal() == ordinal )
+ {
+ return (V) value;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ExternalizableMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ExternalizableMarshaller.java
new file mode 100644
index 0000000..cb59667
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ExternalizableMarshaller.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractObjectMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ExternalizableMarshaller
+ extends AbstractObjectMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Externalizable.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ ( (Externalizable) value ).writeExternal( (ObjectOutput) dataOutput );
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ try
+ {
+ ( (Externalizable) value ).readExternal( (ObjectInput) dataInput );
+ return value;
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new IOException( "Error while deserialization", e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatArrayMarshaller.java
new file mode 100644
index 0000000..826345d
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class FloatArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return float[].class == type || Float[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( float[].class == propertyDescriptor.getType() )
+ {
+ float[] array = (float[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( float arrayValue : array )
+ {
+ dataOutput.writeFloat( arrayValue );
+ }
+ }
+ else
+ {
+ Float[] array = (Float[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( float arrayValue : array )
+ {
+ dataOutput.writeFloat( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( float[].class == propertyDescriptor.getType() )
+ {
+ float[] array = new float[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readFloat();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Float[] array = new Float[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readFloat();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshaller.java
new file mode 100644
index 0000000..0004096
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class FloatMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return float.class == type || Float.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Float.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeFloat( (Float) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Float.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Float.valueOf( dataInput.readFloat() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerArrayMarshaller.java
new file mode 100644
index 0000000..17d0cd7
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class IntegerArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return int[].class == type || Integer[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( int[].class == propertyDescriptor.getType() )
+ {
+ int[] array = (int[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( int arrayValue : array )
+ {
+ dataOutput.writeInt( arrayValue );
+ }
+ }
+ else
+ {
+ Integer[] array = (Integer[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( int arrayValue : array )
+ {
+ dataOutput.writeInt( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( int[].class == propertyDescriptor.getType() )
+ {
+ int[] array = new int[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readInt();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Integer[] array = new Integer[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readInt();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshaller.java
new file mode 100644
index 0000000..1975e9d
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class IntegerMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return int.class == type || Integer.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Integer.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeInt( (Integer) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Integer.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Integer.valueOf( dataInput.readInt() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshaller.java
new file mode 100644
index 0000000..ff5a9c4
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshaller.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.exceptions.SerializerExecutionException;
+import org.apache.directmemory.lightning.internal.CheatPropertyDescriptor;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ListMarshaller
+ extends AbstractMarshaller
+ implements TypeBindableMarshaller
+{
+
+ private final Type listType;
+
+ private Marshaller listTypeMarshaller;
+
+ public ListMarshaller()
+ {
+ this( null );
+ }
+
+ private ListMarshaller( Type listType )
+ {
+ this.listType = listType;
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return List.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( writePossibleNull( value, dataOutput ) )
+ {
+ List<?> list = (List<?>) value;
+ dataOutput.writeInt( list.size() );
+
+ Marshaller marshaller = null;
+ ClassDefinition classDefinition = null;
+ PropertyDescriptor pd = null;
+ if ( listType != null )
+ {
+ ensureMarshallerInitialized( serializationContext );
+ marshaller = listTypeMarshaller;
+ Class<?> baseType = TypeUtil.getBaseType( listType );
+ classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
+ pd = new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List", baseType, marshaller );
+ }
+
+ for ( Object entry : list )
+ {
+ if ( writePossibleNull( entry, dataOutput ) )
+ {
+ if ( listType == null )
+ {
+ marshaller = serializationContext.findMarshaller( entry.getClass() );
+ classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getClass() );
+ pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List",
+ entry.getClass(), marshaller );
+ }
+
+ if ( classDefinition == null )
+ {
+ throw new SerializerExecutionException( "No ClassDefinition found for type " + entry.getClass() );
+ }
+
+ dataOutput.writeLong( classDefinition.getId() );
+ marshaller.marshall( entry, pd, dataOutput, serializationContext );
+ }
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ List list = new ArrayList( size );
+ if ( size > 0 )
+ {
+ for ( int i = 0; i < size; i++ )
+ {
+ if ( isNull( dataInput ) )
+ {
+ list.add( null );
+ }
+ else
+ {
+ long classId = dataInput.readLong();
+ ClassDefinition classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionById( classId );
+
+ Marshaller marshaller;
+ if ( listType != null )
+ {
+ ensureMarshallerInitialized( serializationContext );
+ marshaller = listTypeMarshaller;
+ }
+ else
+ {
+ marshaller = serializationContext.findMarshaller( classDefinition.getType() );
+ }
+
+ PropertyDescriptor pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List",
+ classDefinition.getType(), marshaller );
+ list.add( marshaller.unmarshall( pd, dataInput, serializationContext ) );
+ }
+ }
+ }
+
+ return (V) list;
+ }
+
+ @Override
+ public Marshaller bindType( Type... bindingTypes )
+ {
+ if ( bindingTypes == null )
+ {
+ return new ListMarshaller();
+ }
+
+ if ( bindingTypes.length != 1 )
+ {
+ throw new SerializerExecutionException( "List type binding has no single generic: "
+ + Arrays.toString( bindingTypes ) );
+ }
+
+ Type listType = bindingTypes[0];
+ return new ListMarshaller( listType );
+ }
+
+ private void ensureMarshallerInitialized( SerializationContext serializationContext )
+ {
+ if ( listTypeMarshaller != null )
+ return;
+
+ listTypeMarshaller = serializationContext.findMarshaller( listType );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongArrayMarshaller.java
new file mode 100644
index 0000000..8594aaf
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class LongArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return long[].class == type || Long[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( long[].class == propertyDescriptor.getType() )
+ {
+ long[] array = (long[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( long arrayValue : array )
+ {
+ dataOutput.writeLong( arrayValue );
+ }
+ }
+ else
+ {
+ Long[] array = (Long[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( long arrayValue : array )
+ {
+ dataOutput.writeLong( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( long[].class == propertyDescriptor.getType() )
+ {
+ long[] array = new long[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readLong();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Long[] array = new Long[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readLong();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshaller.java
new file mode 100644
index 0000000..cf53a49
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class LongMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return long.class == type || Long.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Long.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeLong( (Long) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Long.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Long.valueOf( dataInput.readLong() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshaller.java
new file mode 100644
index 0000000..8d6c2a7
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshaller.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.exceptions.SerializerExecutionException;
+import org.apache.directmemory.lightning.internal.CheatPropertyDescriptor;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class MapMarshaller
+ extends AbstractMarshaller
+ implements TypeBindableMarshaller
+{
+
+ private final Type mapKeyType;
+
+ private final Type mapValueType;
+
+ private Marshaller mapKeyTypeMarshaller;
+
+ private Marshaller mapValueTypeMarshaller;
+
+ public MapMarshaller()
+ {
+ this( null, null );
+ }
+
+ private MapMarshaller( Type mapKeyType, Type mapValueType )
+ {
+ this.mapKeyType = mapKeyType;
+ this.mapValueType = mapValueType;
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Map.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( writePossibleNull( value, dataOutput ) )
+ {
+ Map<?, ?> map = (Map<?, ?>) value;
+ dataOutput.writeInt( map.size() );
+
+ Marshaller keyMarshaller = null;
+ ClassDefinition keyClassDefinition = null;
+ PropertyDescriptor keyPd = null;
+ Marshaller valueMarshaller = null;
+ ClassDefinition valueClassDefinition = null;
+ PropertyDescriptor valuePd = null;
+ if ( mapKeyType != null )
+ {
+ ensureMarshallersInitialized( serializationContext );
+ keyMarshaller = mapKeyTypeMarshaller;
+ Class<?> baseType = TypeUtil.getBaseType( mapKeyType );
+ keyClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
+ keyPd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Key", baseType, keyMarshaller );
+
+ valueMarshaller = mapValueTypeMarshaller;
+ baseType = TypeUtil.getBaseType( mapValueType );
+ valueClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
+ valuePd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Value", baseType,
+ valueMarshaller );
+ }
+
+ for ( Entry<?, ?> entry : map.entrySet() )
+ {
+ if ( mapKeyType == null )
+ {
+ keyMarshaller =
+ entry.getKey() != null ? serializationContext.findMarshaller( entry.getKey().getClass() )
+ : null;
+ keyClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getKey().getClass() );
+ keyPd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Key",
+ entry.getKey().getClass(), keyMarshaller );
+
+ if ( entry.getValue() != null )
+ {
+ valueMarshaller =
+ entry.getValue() != null ? serializationContext.findMarshaller( entry.getValue().getClass() )
+ : null;
+ valueClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getValue().getClass() );
+ valuePd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Value",
+ entry.getValue().getClass(), valueMarshaller );
+ }
+ }
+
+ if ( writePossibleNull( entry.getKey(), dataOutput ) )
+ {
+ dataOutput.writeLong( keyClassDefinition.getId() );
+ keyMarshaller.marshall( entry.getKey(), keyPd, dataOutput, serializationContext );
+ }
+
+ if ( writePossibleNull( entry.getValue(), dataOutput ) )
+ {
+ dataOutput.writeLong( valueClassDefinition.getId() );
+ valueMarshaller.marshall( entry.getValue(), valuePd, dataOutput, serializationContext );
+ }
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ Map map = new LinkedHashMap( size );
+ if ( size > 0 )
+ {
+ for ( int i = 0; i < size; i++ )
+ {
+ Object key = null;
+ if ( !isNull( dataInput ) )
+ {
+ long keyClassId = dataInput.readLong();
+ ClassDefinition keyClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionById( keyClassId );
+
+ Marshaller keyMarshaller;
+ if ( mapKeyType != null )
+ {
+ ensureMarshallersInitialized( serializationContext );
+ keyMarshaller = mapKeyTypeMarshaller;
+ }
+ else
+ {
+ keyMarshaller = serializationContext.findMarshaller( keyClassDefinition.getType() );
+ }
+
+ PropertyDescriptor pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Key",
+ keyClassDefinition.getType(), keyMarshaller );
+ key = keyMarshaller.unmarshall( pd, dataInput, serializationContext );
+ }
+
+ Object value = null;
+ if ( !isNull( dataInput ) )
+ {
+ long valueClassId = dataInput.readLong();
+ ClassDefinition valueClassDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionById( valueClassId );
+
+ Marshaller valueMarshaller;
+ if ( mapKeyType != null )
+ {
+ ensureMarshallersInitialized( serializationContext );
+ valueMarshaller = mapValueTypeMarshaller;
+ }
+ else
+ {
+ valueMarshaller = serializationContext.findMarshaller( valueClassDefinition.getType() );
+ }
+
+ PropertyDescriptor pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Value",
+ valueClassDefinition.getType(), valueMarshaller );
+ value = valueMarshaller.unmarshall( pd, dataInput, serializationContext );
+ }
+
+ map.put( key, value );
+ }
+ }
+
+ return (V) map;
+ }
+
+ @Override
+ public Marshaller bindType( Type... bindingTypes )
+ {
+ if ( bindingTypes == null )
+ {
+ return new MapMarshaller();
+ }
+
+ if ( bindingTypes.length != 2 )
+ {
+ throw new SerializerExecutionException( "Map type binding has no double generic: "
+ + Arrays.toString( bindingTypes ) );
+ }
+
+ Class<?> mapKeyType = (Class<?>) bindingTypes[0];
+ Class<?> mapValueType = (Class<?>) bindingTypes[1];
+ return new MapMarshaller( mapKeyType, mapValueType );
+ }
+
+ private void ensureMarshallersInitialized( SerializationContext serializationContext )
+ {
+ if ( mapKeyTypeMarshaller != null && mapValueTypeMarshaller != null )
+ return;
+
+ mapKeyTypeMarshaller = serializationContext.findMarshaller( mapKeyType );
+ mapValueTypeMarshaller = serializationContext.findMarshaller( mapValueType );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SerializableMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SerializableMarshaller.java
new file mode 100644
index 0000000..41f4205
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SerializableMarshaller.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractObjectMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class SerializableMarshaller
+ extends AbstractObjectMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Serializable.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ ObjectOutputStream stream = new ObjectOutputStream( (OutputStream) dataOutput );
+ stream.writeObject( value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ ObjectInputStream stream = new ObjectInputStream( (InputStream) dataInput );
+ try
+ {
+ return (V) stream.readObject();
+ }
+ catch ( ClassNotFoundException e )
+ {
+ throw new IOException( "Error while deserialization", e );
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshaller.java
new file mode 100644
index 0000000..8341514
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshaller.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.TypeBindableMarshaller;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.exceptions.SerializerExecutionException;
+import org.apache.directmemory.lightning.internal.CheatPropertyDescriptor;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class SetMarshaller
+ extends AbstractMarshaller
+ implements TypeBindableMarshaller
+{
+
+ private final Type setType;
+
+ private Marshaller setTypeMarshaller;
+
+ public SetMarshaller()
+ {
+ this( null );
+ }
+
+ private SetMarshaller( Type setType )
+ {
+ this.setType = setType;
+ }
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Set.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( writePossibleNull( value, dataOutput ) )
+ {
+ Set<?> set = (Set<?>) value;
+ dataOutput.writeInt( set.size() );
+
+ Marshaller marshaller = null;
+ ClassDefinition classDefinition = null;
+ PropertyDescriptor pd = null;
+ if ( setType != null )
+ {
+ ensureMarshallerInitialized( serializationContext );
+ marshaller = setTypeMarshaller;
+ Class<?> baseType = TypeUtil.getBaseType( setType );
+ classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
+ pd = new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set", baseType, marshaller );
+ }
+
+ for ( Object entry : set )
+ {
+ if ( writePossibleNull( entry, dataOutput ) )
+ {
+ if ( setType == null )
+ {
+ marshaller = serializationContext.findMarshaller( entry.getClass() );
+ classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getClass() );
+ pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set",
+ entry.getClass(), marshaller );
+ }
+
+ dataOutput.writeLong( classDefinition.getId() );
+ marshaller.marshall( entry, pd, dataOutput, serializationContext );
+ }
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ Set set = new HashSet( size );
+ if ( size > 0 )
+ {
+ for ( int i = 0; i < size; i++ )
+ {
+ if ( isNull( dataInput ) )
+ {
+ set.add( null );
+ }
+ else
+ {
+ long classId = dataInput.readLong();
+ ClassDefinition classDefinition =
+ serializationContext.getClassDefinitionContainer().getClassDefinitionById( classId );
+
+ Marshaller marshaller;
+ if ( setType != null )
+ {
+ ensureMarshallerInitialized( serializationContext );
+ marshaller = setTypeMarshaller;
+ }
+ else
+ {
+ marshaller = serializationContext.findMarshaller( classDefinition.getType() );
+ }
+
+ PropertyDescriptor pd =
+ new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set",
+ classDefinition.getType(), marshaller );
+ set.add( marshaller.unmarshall( pd, dataInput, serializationContext ) );
+ }
+ }
+ }
+
+ return (V) set;
+ }
+
+ @Override
+ public Marshaller bindType( Type... bindingTypes )
+ {
+ if ( bindingTypes == null )
+ {
+ return new SetMarshaller();
+ }
+
+ if ( bindingTypes.length != 1 )
+ {
+ throw new SerializerExecutionException( "Set type binding has no single generic: "
+ + Arrays.toString( bindingTypes ) );
+ }
+
+ Type setType = bindingTypes[0];
+ return new SetMarshaller( setType );
+ }
+
+ private void ensureMarshallerInitialized( SerializationContext serializationContext )
+ {
+ if ( setTypeMarshaller != null )
+ return;
+
+ setTypeMarshaller = serializationContext.findMarshaller( setType );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortArrayMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortArrayMarshaller.java
new file mode 100644
index 0000000..4eaacc4
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortArrayMarshaller.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ShortArrayMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return short[].class == type || Short[].class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ if ( short[].class == propertyDescriptor.getType() )
+ {
+ short[] array = (short[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( short arrayValue : array )
+ {
+ dataOutput.writeShort( arrayValue );
+ }
+ }
+ else
+ {
+ Short[] array = (Short[]) value;
+ dataOutput.writeInt( array.length );
+
+ for ( short arrayValue : array )
+ {
+ dataOutput.writeShort( arrayValue );
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ int size = dataInput.readInt();
+ if ( short[].class == propertyDescriptor.getType() )
+ {
+ short[] array = new short[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readShort();
+ }
+
+ return (V) array;
+ }
+ else
+ {
+ Short[] array = new Short[size];
+ for ( int i = 0; i < size; i++ )
+ {
+ array[i] = dataInput.readShort();
+ }
+
+ return (V) array;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshaller.java
new file mode 100644
index 0000000..590f543
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class ShortMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return short.class == type || Short.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( Short.class == propertyDescriptor.getType() )
+ {
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+ }
+
+ dataOutput.writeShort( (Short) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( Short.class == propertyDescriptor.getType() )
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+ }
+
+ return (V) Short.valueOf( dataInput.readShort() );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StreamedMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StreamedMarshaller.java
new file mode 100644
index 0000000..67a28fa
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StreamedMarshaller.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.Streamed;
+import org.apache.directmemory.lightning.base.AbstractObjectMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class StreamedMarshaller
+ extends AbstractObjectMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return Streamed.class.isAssignableFrom( type );
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ ( (Streamed) value ).writeTo( dataOutput );
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ ( (Streamed) value ).readFrom( dataInput );
+ return value;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StringMarshaller.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StringMarshaller.java
new file mode 100644
index 0000000..ba8ecb0
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/marshaller/StringMarshaller.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.base.AbstractMarshaller;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class StringMarshaller
+ extends AbstractMarshaller
+{
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return String.class == type;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ if ( !writePossibleNull( value, dataOutput ) )
+ {
+ return;
+ }
+
+ dataOutput.writeUTF( (String) value );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <V> V unmarshall( PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ if ( isNull( dataInput ) )
+ {
+ return null;
+ }
+
+ return (V) dataInput.readUTF();
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/BeanUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/BeanUtil.java
new file mode 100644
index 0000000..7846545
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/BeanUtil.java
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.exceptions.SerializerDefinitionException;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.PropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.objectweb.asm.Type;
+
+public final class BeanUtil
+{
+
+ private BeanUtil()
+ {
+ }
+
+ public static Set<Field> findPropertiesByClass( Class<?> type, Class<? extends Annotation> attributeAnnotation )
+ {
+ Set<Field> properties = new HashSet<Field>();
+ properties.addAll( findPropertiesByInstanceFields( type, attributeAnnotation ) );
+ properties.addAll( findPropertiesByMethods( type, type, attributeAnnotation ) );
+ properties.addAll( findPropertiesByInterfaces( type, attributeAnnotation ) );
+
+ if ( type.getSuperclass() != null && type.getSuperclass() != Object.class )
+ {
+ properties.addAll( findPropertiesByClass( type.getSuperclass(), attributeAnnotation ) );
+ }
+
+ return properties;
+ }
+
+ public static Set<Field> findPropertiesByInstanceFields( Class<?> type,
+ Class<? extends Annotation> attributeAnnotation )
+ {
+ Set<Field> attributes = new HashSet<Field>();
+ for ( Field field : type.getDeclaredFields() )
+ {
+ if ( field.isAnnotationPresent( attributeAnnotation ) )
+ {
+ attributes.add( field );
+ }
+ }
+
+ return attributes;
+ }
+
+ public static Set<Field> findPropertiesByMethods( Class<?> type, Class<?> searchType,
+ Class<? extends Annotation> attributeAnnotation )
+ {
+ Set<Field> attributes = new HashSet<Field>();
+ for ( Method method : searchType.getDeclaredMethods() )
+ {
+ if ( method.isAnnotationPresent( attributeAnnotation ) )
+ {
+ String propertyName = BeanUtil.buildPropertyName( method );
+ Field field = BeanUtil.getFieldByPropertyName( propertyName, type );
+ if ( field == null )
+ {
+ if ( attributeAnnotation == Attribute.class )
+ {
+ Attribute attribute = method.getAnnotation( Attribute.class );
+ field = BeanUtil.getFieldByPropertyName( attribute.property(), type );
+ }
+
+ if ( field == null )
+ {
+ throw new SerializerDefinitionException( "No property for method " + method + " was found" );
+ }
+ }
+
+ attributes.add( field );
+ }
+ }
+
+ return attributes;
+ }
+
+ public static Set<Field> findPropertiesByInterfaces( Class<?> type, Class<? extends Annotation> attributeAnnotation )
+ {
+ Set<Field> attributes = new HashSet<Field>();
+
+ for ( Class<?> interfaze : type.getInterfaces() )
+ {
+ // Add all annotated methods in interface
+ attributes.addAll( findInterfaceProperties0( type, interfaze, attributeAnnotation ) );
+ }
+
+ return attributes;
+ }
+
+ private static Set<Field> findInterfaceProperties0( Class<?> type, Class<?> interfaze,
+ Class<? extends Annotation> attributeAnnotation )
+ {
+ Set<Field> attributes = new HashSet<Field>();
+
+ // Add all annotated methods in interface
+ attributes.addAll( findPropertiesByMethods( type, interfaze, attributeAnnotation ) );
+
+ // Look up super-interface
+ if ( interfaze.getSuperclass() != null )
+ {
+ attributes.addAll( findInterfaceProperties0( type, interfaze.getSuperclass(), attributeAnnotation ) );
+ }
+
+ return attributes;
+ }
+
+ public static Field getFieldByPropertyName( String propertyName, Class<?> type )
+ {
+ try
+ {
+ return type.getDeclaredField( propertyName );
+ }
+ catch ( NoSuchFieldException e )
+ {
+ if ( type.getSuperclass() != null && type.getSuperclass() != Object.class )
+ {
+ return getFieldByPropertyName( propertyName, type.getSuperclass() );
+ }
+ return null;
+ }
+ }
+
+ public static Method findSetterMethod( Method method )
+ {
+ if ( method.getName().startsWith( "set" ) )
+ {
+ return method;
+ }
+
+ String propertyName = StringUtil.toUpperCamelCase( extractPropertyName( method.getName() ) );
+
+ Class<?> type = method.getReturnType();
+ Class<?> clazz = method.getDeclaringClass();
+ String setterName = "set" + propertyName;
+
+ try
+ {
+ return clazz.getDeclaredMethod( setterName, type );
+ }
+ catch ( Exception e )
+ {
+ // Seems there's no setter, so ignore all exceptions
+ return null;
+ }
+ }
+
+ public static Method findArraySetterMethod( Method method )
+ {
+ if ( method.getName().startsWith( "set" ) )
+ {
+ return method;
+ }
+
+ String propertyName = StringUtil.toUpperCamelCase( extractPropertyName( method.getName() ) );
+
+ Class<?> type = method.getReturnType();
+ Class<?> clazz = method.getDeclaringClass();
+ String setterName = "set" + propertyName;
+
+ try
+ {
+ return clazz.getDeclaredMethod( setterName, type, int.class );
+ }
+ catch ( Exception e )
+ {
+ // Seems there's no setter, so ignore all exceptions
+ return null;
+ }
+ }
+
+ public static Method findGetterMethod( Method method )
+ {
+ if ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) )
+ {
+ return method;
+ }
+
+ String propertyName = StringUtil.toUpperCamelCase( extractPropertyName( method.getName() ) );
+
+ Class<?> type = method.getParameterTypes()[0];
+ Class<?> clazz = method.getDeclaringClass();
+ String getterObjectName = "get" + propertyName;
+ String getterBooleanName = "is" + propertyName;
+
+ try
+ {
+ return clazz.getDeclaredMethod( getterObjectName, type );
+ }
+ catch ( Exception e )
+ {
+ if ( type == boolean.class )
+ {
+ try
+ {
+ return clazz.getDeclaredMethod( getterBooleanName, type );
+ }
+ catch ( Exception ex )
+ {
+ // Intentionally left blank - just fall through
+ }
+ }
+
+ // Seems there's no setter, so ignore all exceptions
+ return null;
+ }
+ }
+
+ public static Method findArrayGetterMethod( Method method )
+ {
+ if ( method.getName().startsWith( "get" ) || method.getName().startsWith( "is" ) )
+ {
+ return method;
+ }
+
+ String propertyName = StringUtil.toUpperCamelCase( extractPropertyName( method.getName() ) );
+
+ Class<?> type = method.getParameterTypes()[0];
+ Class<?> clazz = method.getDeclaringClass();
+ String getterObjectName = "get" + propertyName;
+ String getterBooleanName = "is" + propertyName;
+
+ try
+ {
+ return clazz.getDeclaredMethod( getterObjectName, type );
+ }
+ catch ( Exception e )
+ {
+ if ( type == boolean.class )
+ {
+ try
+ {
+ return clazz.getDeclaredMethod( getterBooleanName, type, int.class );
+ }
+ catch ( Exception ex )
+ {
+ // Intentionally left blank - just fall through
+ }
+ }
+
+ // Seems there's no setter, so ignore all exceptions
+ return null;
+ }
+ }
+
+ public static String buildPropertyName( Method method )
+ {
+ return buildPropertyName( method.getName() );
+ }
+
+ public static String buildPropertyName( String methodName )
+ {
+ return StringUtil.toLowerCamelCase( extractPropertyName( methodName ) );
+ }
+
+ public static String buildInternalSignature( Iterable<PropertyDescriptor> propertyDescriptors )
+ {
+ StringBuilder internalSignature = new StringBuilder();
+ for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
+ {
+ internalSignature.append( propertyDescriptor.getInternalSignature() );
+ }
+ return internalSignature.toString();
+ }
+
+ public static <T> String buildInternalSignature( String propertyName, PropertyAccessor propertyAccessor )
+ {
+ String type = Type.getDescriptor( propertyAccessor.getType() );
+ return new StringBuilder( "{" ).append( propertyName ).append( "}" ).append( type ).toString();
+ }
+
+ private static String extractPropertyName( String methodName )
+ {
+ if ( methodName.toUpperCase().startsWith( "GET" ) || methodName.toUpperCase().startsWith( "IS" )
+ || methodName.toUpperCase().startsWith( "SET" ) )
+ {
+
+ char[] characters = methodName.toCharArray();
+ for ( int i = 1; i < characters.length; i++ )
+ {
+ if ( Character.isUpperCase( characters[i] ) )
+ {
+ return StringUtil.toLowerCamelCase( methodName.substring( i ) );
+ }
+ }
+ }
+ return StringUtil.toLowerCamelCase( methodName );
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/ClassUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/ClassUtil.java
new file mode 100644
index 0000000..268460c
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/ClassUtil.java
@@ -0,0 +1,509 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public final class ClassUtil
+{
+
+ public static final ClassDefinition[] CLASS_DESCRIPTORS = new ClassDefinition[] {
+ new JavaBuildInTypeClassDefinition( boolean.class, 1 ), new JavaBuildInTypeClassDefinition( Boolean.class, 2 ),
+ new JavaBuildInTypeClassDefinition( byte.class, 3 ), new JavaBuildInTypeClassDefinition( Byte.class, 4 ),
+ new JavaBuildInTypeClassDefinition( char.class, 5 ), new JavaBuildInTypeClassDefinition( Character.class, 6 ),
+ new JavaBuildInTypeClassDefinition( double.class, 7 ), new JavaBuildInTypeClassDefinition( Double.class, 8 ),
+ new JavaBuildInTypeClassDefinition( float.class, 9 ), new JavaBuildInTypeClassDefinition( Float.class, 10 ),
+ new JavaBuildInTypeClassDefinition( int.class, 11 ), new JavaBuildInTypeClassDefinition( Integer.class, 12 ),
+ new JavaBuildInTypeClassDefinition( long.class, 13 ), new JavaBuildInTypeClassDefinition( Long.class, 14 ),
+ new JavaBuildInTypeClassDefinition( short.class, 15 ), new JavaBuildInTypeClassDefinition( Short.class, 16 ),
+ new JavaBuildInTypeClassDefinition( String.class, 17 ), new JavaBuildInTypeClassDefinition( List.class, 18 ),
+ new JavaBuildInTypeClassDefinition( Set.class, 19 ), new JavaBuildInTypeClassDefinition( Map.class, 20 ),
+ new JavaBuildInTypeClassDefinition( BigInteger.class, 21 ),
+ new JavaBuildInTypeClassDefinition( BigDecimal.class, 22 ) };
+
+ private static final Map<Class<?>, Long> SERIAL_VERSION_UID_CACHE = new ConcurrentHashMap<Class<?>, Long>();
+
+ private ClassUtil()
+ {
+ }
+
+ public static boolean isReferenceCapable( Class<?> type )
+ {
+ return !type.isPrimitive() && Boolean.class != type && Byte.class != type && Short.class != type
+ && Integer.class != type && Long.class != type && Float.class != type && Double.class != type;
+ }
+
+ public static Class<?> loadClass( String canonicalName )
+ throws ClassNotFoundException
+ {
+ return loadClass( canonicalName, ClassUtil.class.getClassLoader() );
+ }
+
+ public static Class<?> loadClass( String canonicalName, ClassLoader classLoader )
+ throws ClassNotFoundException
+ {
+ Class<?> type = null;
+ try
+ {
+ type = classLoader.loadClass( canonicalName );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ // Intentionally left blank
+ }
+
+ if ( type == null )
+ {
+ try
+ {
+ type = Class.forName( canonicalName );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ // Intentionally left blank
+ }
+ }
+
+ if ( type == null )
+ {
+ try
+ {
+ ClassLoader tcl = Thread.currentThread().getContextClassLoader();
+ type = tcl.loadClass( canonicalName );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ // Intentionally left blank
+ }
+ }
+
+ if ( type == null )
+ {
+ try
+ {
+ ClassLoader ccl = ClassUtil.class.getClassLoader();
+ type = ccl.loadClass( canonicalName );
+ }
+ catch ( ClassNotFoundException e )
+ {
+ // Intentionally left blank
+ }
+ }
+
+ if ( type != null )
+ {
+ return type;
+ }
+
+ throw new ClassNotFoundException( "Class " + canonicalName + " not found on classpath" );
+ }
+
+ public static long calculateSerialVersionUID( Class<?> clazz )
+ {
+ Long serialVersionUID = SERIAL_VERSION_UID_CACHE.get( clazz );
+ if ( serialVersionUID != null )
+ {
+ return serialVersionUID;
+ }
+
+ if ( Serializable.class.isAssignableFrom( clazz ) )
+ {
+ serialVersionUID = ObjectStreamClass.lookup( clazz ).getSerialVersionUID();
+ SERIAL_VERSION_UID_CACHE.put( clazz, serialVersionUID );
+ return serialVersionUID;
+ }
+
+ serialVersionUID = getSerialVersionUIDFromField( clazz );
+ if ( serialVersionUID != null )
+ {
+ SERIAL_VERSION_UID_CACHE.put( clazz, serialVersionUID );
+ return serialVersionUID;
+ }
+
+ try
+ {
+ ClassReader reader = new ClassReader( Type.getInternalName( clazz ).replace( "/", "." ) );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream( baos );
+
+ SerialVersionClassVisitor classVisitor = new SerialVersionClassVisitor();
+ reader.accept( classVisitor, 0 );
+
+ // Classname
+ out.writeUTF( toJavaName( classVisitor.name ) );
+
+ // Modifiers
+ out.writeInt( clazz.getModifiers()
+ & ( Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT ) );
+
+ // Interfaces
+ Collections.sort( classVisitor.interfaces );
+ for ( int i = 0; i < classVisitor.interfaces.size(); i++ )
+ {
+ out.writeUTF( toJavaName( classVisitor.interfaces.get( i ) ) );
+ }
+
+ // Fields
+ Field[] fields = clazz.getDeclaredFields();
+ Arrays.sort( fields, new Comparator<Field>()
+ {
+
+ @Override
+ public int compare( Field o1, Field o2 )
+ {
+ return o1.getName().compareTo( o2.getName() );
+ }
+ } );
+
+ for ( Field field : fields )
+ {
+ int mods = field.getModifiers();
+ if ( ( ( mods & Modifier.PRIVATE ) == 0 || ( mods & ( Modifier.STATIC | Modifier.TRANSIENT ) ) == 0 ) )
+ {
+ out.writeUTF( field.getName() );
+ out.writeInt( mods );
+ out.writeUTF( Type.getDescriptor( field.getType() ) );
+ }
+ }
+
+ // Static Initializer
+ if ( classVisitor.staticInitializerFound )
+ {
+ out.writeUTF( "<clinit>" );
+ out.writeInt( Modifier.STATIC );
+ out.writeUTF( "()V" );
+ }
+
+ // Constructors
+ Constructor<?>[] constructors = clazz.getDeclaredConstructors();
+ Arrays.sort( constructors, new Comparator<Constructor<?>>()
+ {
+
+ @Override
+ public int compare( Constructor<?> o1, Constructor<?> o2 )
+ {
+ return Type.getConstructorDescriptor( o1 ).compareTo( Type.getConstructorDescriptor( o2 ) );
+ }
+ } );
+
+ for ( int i = 0; i < constructors.length; i++ )
+ {
+ Constructor<?> constructor = constructors[i];
+ int mods = constructor.getModifiers();
+ if ( ( mods & Modifier.PRIVATE ) == 0 )
+ {
+ out.writeUTF( "<init>" );
+ out.writeInt( mods );
+ out.writeUTF( toJavaName( Type.getConstructorDescriptor( constructor ) ) );
+ }
+ }
+
+ // Methods
+ Method[] methods = clazz.getDeclaredMethods();
+ Arrays.sort( methods, new Comparator<Method>()
+ {
+
+ @Override
+ public int compare( Method o1, Method o2 )
+ {
+ return Type.getMethodDescriptor( o1 ).compareTo( Type.getMethodDescriptor( o2 ) );
+ }
+ } );
+
+ for ( int i = 0; i < methods.length; i++ )
+ {
+ Method method = methods[i];
+ int mods = method.getModifiers();
+ if ( ( mods & Modifier.PRIVATE ) == 0 )
+ {
+ out.writeUTF( "<init>" );
+ out.writeInt( mods );
+ out.writeUTF( toJavaName( Type.getMethodDescriptor( method ) ) );
+ }
+ }
+
+ // Final calculation
+ out.flush();
+ MessageDigest digest = MessageDigest.getInstance( "SHA" );
+ byte[] checksum = digest.digest( baos.toByteArray() );
+
+ long hash = 0;
+ for ( int i = Math.min( checksum.length, 8 ) - 1; i >= 0; i-- )
+ {
+ hash = ( hash << 8 ) | ( checksum[i] & 0xFF );
+ }
+
+ SERIAL_VERSION_UID_CACHE.put( clazz, hash );
+ return hash;
+ }
+ catch ( IOException e )
+ {
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ }
+
+ return -1L;
+ }
+
+ public static byte[] getClassBytes( Class<?> clazz )
+ {
+ try
+ {
+ ClassLoader classLoader = clazz.getClassLoader();
+ if ( classLoader == null )
+ {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ }
+
+ String internalName = Type.getInternalName( clazz );
+ InputStream stream = classLoader.getResourceAsStream( internalName + ".class" );
+ byte[] data = new byte[stream.available()];
+ stream.read( data );
+ stream.close();
+ return data;
+ }
+ catch ( IOException e )
+ {
+ throw new RuntimeException( "Class bytes could not be read", e );
+ }
+ }
+
+ private static String toJavaName( String classname )
+ {
+ return classname.replace( "/", "." );
+ }
+
+ private static Long getSerialVersionUIDFromField( Class<?> clazz )
+ {
+ try
+ {
+ Field f = clazz.getDeclaredField( "serialVersionUID" );
+ int mask = Modifier.STATIC | Modifier.FINAL;
+ if ( ( f.getModifiers() & mask ) == mask )
+ {
+ f.setAccessible( true );
+ return Long.valueOf( f.getLong( null ) );
+ }
+ }
+ catch ( Exception ex )
+ {
+ }
+ return null;
+ }
+
+ private static class JavaBuildInTypeClassDefinition
+ implements ClassDefinition
+ {
+
+ private final long id;
+
+ private final Class<?> type;
+
+ private final String canonicalName;
+
+ private final byte[] checksum = new byte[20];
+
+ private final long serialVersionUID = -1L;
+
+ JavaBuildInTypeClassDefinition( Class<?> type, long id )
+ {
+ this.id = id;
+ this.type = type;
+ this.canonicalName = type.getCanonicalName();
+ }
+
+ @Override
+ public String getCanonicalName()
+ {
+ return canonicalName;
+ }
+
+ @Override
+ public Class<?> getType()
+ {
+ return type;
+ }
+
+ @Override
+ public byte[] getChecksum()
+ {
+ return checksum;
+ }
+
+ @Override
+ public long getId()
+ {
+ return id;
+ }
+
+ @Override
+ public long getSerialVersionUID()
+ {
+ return serialVersionUID;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( canonicalName == null ) ? 0 : canonicalName.hashCode() );
+ result = prime * result + Arrays.hashCode( checksum );
+ result = prime * result + (int) ( id ^ ( id >>> 32 ) );
+ result = prime * result + (int) ( serialVersionUID ^ ( serialVersionUID >>> 32 ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ JavaBuildInTypeClassDefinition other = (JavaBuildInTypeClassDefinition) obj;
+ if ( canonicalName == null )
+ {
+ if ( other.canonicalName != null )
+ return false;
+ }
+ else if ( !canonicalName.equals( other.canonicalName ) )
+ return false;
+ if ( !Arrays.equals( checksum, other.checksum ) )
+ return false;
+ if ( id != other.id )
+ return false;
+ if ( serialVersionUID != other.serialVersionUID )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "JavaBuildInTypeClassDefinition [id=" + id + ", type=" + type + ", canonicalName=" + canonicalName
+ + ", checksum=" + Arrays.toString( checksum ) + ", serialVersionUID=" + serialVersionUID + "]";
+ }
+ }
+
+ private static class SerialVersionClassVisitor
+ extends ClassVisitor
+ {
+
+ public SerialVersionClassVisitor()
+ {
+ super( Opcodes.ASM4 );
+ }
+
+ private List<String> interfaces = new ArrayList<String>();
+
+ private boolean staticInitializerFound = false;
+
+ private String name;
+
+ @Override
+ public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
+ {
+ this.name = name;
+ this.interfaces = Arrays.asList( interfaces );
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
+ {
+ return null;
+ }
+
+ @Override
+ public void visitAttribute( Attribute attr )
+ {
+ }
+
+ @Override
+ public void visitEnd()
+ {
+ }
+
+ @Override
+ public FieldVisitor visitField( int access, String name, String desc, String signature, Object value )
+ {
+ return null;
+ }
+
+ @Override
+ public void visitInnerClass( String name, String outerName, String innerName, int access )
+ {
+ }
+
+ @Override
+ public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions )
+ {
+ if ( "<clinit>".equals( name ) && ( access & Opcodes.ACC_STATIC ) != 0 )
+ {
+ staticInitializerFound = true;
+ }
+ return null;
+ }
+
+ @Override
+ public void visitOuterClass( String owner, String name, String desc )
+ {
+ }
+
+ @Override
+ public void visitSource( String source, String debug )
+ {
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/Crc64Util.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/Crc64Util.java
new file mode 100644
index 0000000..e836764
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/Crc64Util.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+/**
+ * Crc64 checksum computation. This classes basic content was copied from original position:
+ * http://intact.googlecode.com/ It was changed to use byte data instead of strings
+ *
+ * @author The European Bioinformatics Institute, and others.
+ * @author Uniparc
+ * @version $Id$
+ */
+public final class Crc64Util
+{
+
+ private static long _crc64Array[] = new long[256];
+
+ /**
+ * Initialization of _crc64Array.
+ */
+ static
+ {
+
+ for ( int i = 0; i <= 255; ++i )
+ {
+ long k = i;
+ for ( int j = 0; j < 8; ++j )
+ {
+ if ( ( k & 1 ) != 0 )
+ {
+ k = ( k >>> 1 ) ^ 0xd800000000000000l;
+ }
+ else
+ {
+ k = k >>> 1;
+ }
+ }
+ _crc64Array[i] = k;
+ }
+ }
+
+ private Crc64Util()
+ {
+ }
+
+ /**
+ * Returns a hex string representation of the checksum
+ *
+ * @param checksum
+ * @return
+ */
+ public static String toString( long checksum )
+ {
+ String crc64String = Long.toHexString( checksum ).toUpperCase();
+ StringBuffer crc64 = new StringBuffer( "0000000000000000" );
+ crc64.replace( crc64.length() - crc64String.length(), crc64.length(), crc64String );
+
+ return crc64.toString();
+ }
+
+ /**
+ * Calculated the checksum of the given data array as a long value.
+ *
+ * @param data the data to checksum
+ * @return the calculated checksum
+ */
+ public static long checksum( byte[] data )
+ {
+ long crc64Number = 0;
+ for ( int i = 0; i < data.length; ++i )
+ {
+ int symbol = data[i];
+ long a = ( crc64Number >>> 8 );
+ long b = ( crc64Number ^ symbol ) & 0xff;
+ crc64Number = a ^ _crc64Array[(int) b];
+ }
+
+ return crc64Number;
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/InternalUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/InternalUtil.java
new file mode 100644
index 0000000..10cf017
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/InternalUtil.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.lang.reflect.Constructor;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiator;
+import org.apache.directmemory.lightning.internal.beans.PropertyAccessorFactory;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public final class InternalUtil
+{
+
+ public static final Charset CHARSET = Charset.forName( "UTF-8" );
+
+ public static final boolean UNSAFE_AVAILABLE;
+
+ static
+ {
+ boolean unsafeAvailable = false;
+ try
+ {
+ Class.forName( "sun.misc.Unsafe" );
+ unsafeAvailable = true;
+ }
+ catch ( Exception e )
+ {
+ // Intentionally left blank
+ }
+
+ UNSAFE_AVAILABLE = unsafeAvailable;
+ }
+
+ private InternalUtil()
+ {
+ }
+
+ public static byte[] getChecksum( byte[] data, Logger logger )
+ {
+ try
+ {
+ MessageDigest digest = MessageDigest.getInstance( "SHA-1" );
+ digest.update( data, 0, data.length );
+ return digest.digest();
+ }
+ catch ( Exception e )
+ {
+ throw new RuntimeException( "Could not build checksum of data" );
+ }
+ }
+
+ public static byte[] getChecksum( Collection<PropertyDescriptor> propertyDescriptors, Logger logger )
+ {
+ final StringBuilder builder = new StringBuilder();
+
+ // Clone and sort list of PropertyDescriptors
+ List<PropertyDescriptor> temp = new ArrayList<PropertyDescriptor>( propertyDescriptors );
+ Collections.sort( temp );
+
+ for ( PropertyDescriptor propertyDescriptor : temp )
+ {
+ logger.trace( "Adding property " + propertyDescriptor.getName() + " to checksum" );
+ builder.append( propertyDescriptor.getInternalSignature() );
+ }
+
+ return getChecksum( builder.toString().getBytes( CHARSET ), logger );
+ }
+
+ public static boolean isUnsafeAvailable()
+ {
+ return UNSAFE_AVAILABLE;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public static ObjectInstantiator buildSunUnsafeInstantiator( Class<?> type )
+ {
+ try
+ {
+ Class<? extends ObjectInstantiator> clazz =
+ (Class<? extends ObjectInstantiator>) ClassUtil.loadClass( "org.apache.directmemory.lightning.internal.instantiator.sun.SunUnsafeAllocateInstanceInstantiator" );
+
+ Constructor<? extends ObjectInstantiator> constructor = clazz.getDeclaredConstructor( Class.class );
+ return constructor.newInstance( type );
+ }
+ catch ( Exception e )
+ {
+ return null;
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public static PropertyAccessorFactory buildSunUnsafePropertyAccessor()
+ {
+ try
+ {
+ Class<? extends PropertyAccessorFactory> clazz =
+ (Class<? extends PropertyAccessorFactory>) ClassUtil.loadClass( "org.apache.directmemory.lightning.internal.beans.SunUnsafePropertyAccessorFactory" );
+
+ Constructor<? extends PropertyAccessorFactory> constructor = clazz.getDeclaredConstructor();
+ constructor.setAccessible( true );
+ return constructor.newInstance();
+ }
+ catch ( Exception e )
+ {
+ return null;
+ }
+ }
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/StringUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/StringUtil.java
new file mode 100644
index 0000000..142862a
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/StringUtil.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+public final class StringUtil
+{
+
+ private StringUtil()
+ {
+ }
+
+ public static String toLowerCamelCase( String value )
+ {
+ if ( value == null )
+ return null;
+
+ if ( value.length() == 0 )
+ return value;
+
+ return toCamelCase( value );
+ }
+
+ public static String toUpperCamelCase( String value )
+ {
+ String lowerCamelCase = toLowerCamelCase( value );
+ return String.valueOf( Character.toUpperCase( lowerCamelCase.toCharArray()[0] ) )
+ + lowerCamelCase.substring( 1 );
+ }
+
+ private static String toCamelCase( String value )
+ {
+ StringBuilder camelCase = new StringBuilder();
+ char[] characters = value.toCharArray();
+
+ for ( int i = 0; i < characters.length; i++ )
+ {
+ i = ignoreWhitespace( characters, i );
+ if ( i == -1 )
+ break;
+
+ if ( camelCase.length() == 0 )
+ camelCase.append( Character.toLowerCase( characters[i] ) );
+ else
+ camelCase.append( Character.toUpperCase( characters[i] ) );
+
+ int nextWhitespace = nextWhitespace( characters, i );
+ if ( nextWhitespace == -1 )
+ nextWhitespace = characters.length;
+
+ camelCase.append( value.substring( i + 1, nextWhitespace ) );
+ i = nextWhitespace;
+ }
+
+ return camelCase.toString();
+ }
+
+ private static int ignoreWhitespace( char[] characters, int offset )
+ {
+ for ( int i = offset; i < characters.length; i++ )
+ {
+ char c = characters[i];
+ if ( !Character.isWhitespace( c ) && '-' != c && '_' != c )
+ return i;
+ }
+ return -1;
+ }
+
+ private static int nextWhitespace( char[] characters, int offset )
+ {
+ for ( int i = offset + 1; i < characters.length; i++ )
+ {
+ char c = characters[i];
+ if ( Character.isWhitespace( c ) || '-' == c || '_' == c )
+ return i;
+ }
+ return -1;
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/TypeUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/TypeUtil.java
new file mode 100644
index 0000000..2d9434d
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/TypeUtil.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+public final class TypeUtil
+{
+
+ private TypeUtil()
+ {
+ }
+
+ public static Class<?> getBaseType( Type type )
+ {
+ if ( type instanceof Class )
+ {
+ return (Class<?>) type;
+ }
+
+ if ( type instanceof ParameterizedType )
+ {
+ return (Class<?>) ( (ParameterizedType) type ).getRawType();
+ }
+
+ throw new IllegalStateException( "The requested type is an generic array or wildcard which is not supported" );
+ }
+
+ public static Type[] getTypeArgument( Type type )
+ {
+ if ( type instanceof Class )
+ {
+ return null;
+ }
+
+ if ( type instanceof ParameterizedType )
+ {
+ return ( (ParameterizedType) type ).getActualTypeArguments();
+ }
+
+ throw new IllegalStateException( "The requested type is an generic array or wildcard which is not supported" );
+ }
+
+}
diff --git a/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/UnsafeUtil.java b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/UnsafeUtil.java
new file mode 100644
index 0000000..53fc238
--- /dev/null
+++ b/lightning-core/src/main/java/org/apache/directmemory/lightning/internal/util/UnsafeUtil.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.lang.reflect.Field;
+
+@SuppressWarnings( "restriction" )
+public final class UnsafeUtil
+{
+
+ private static final sun.misc.Unsafe UNSAFE;
+
+ static
+ {
+ sun.misc.Unsafe unsafe;
+ try
+ {
+ Field unsafeField = sun.misc.Unsafe.class.getDeclaredField( "theUnsafe" );
+ unsafeField.setAccessible( true );
+ unsafe = (sun.misc.Unsafe) unsafeField.get( null );
+ }
+ catch ( Exception e )
+ {
+ unsafe = null;
+ }
+
+ UNSAFE = unsafe;
+ }
+
+ private UnsafeUtil()
+ {
+ }
+
+ public static sun.misc.Unsafe getUnsafe()
+ {
+ return UNSAFE;
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/Benchmark.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/Benchmark.java
new file mode 100644
index 0000000..cc8a0cf
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/Benchmark.java
@@ -0,0 +1,526 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractObjectMarshaller;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore
+public class Benchmark
+{
+
+ private static final int WARMUP_ROUNDS = 100000;
+
+ private static final int BENCHMARK_ROUNDS = 800000;
+
+ @Test
+ public void benchmarkLightningSerialization()
+ throws Exception
+ {
+ long buildStartTime = System.nanoTime();
+ Serializer serializer =
+ Lightning.newBuilder().debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new BenchmarkSerializerDefinition() ).build();
+ long nanos = TimeUnit.NANOSECONDS.toMillis( System.nanoTime() - buildStartTime );
+ System.out.println( "Lightning Serializer build time: " + nanos + " ms" );
+
+ long size = 0;
+ for ( int i = 0; i < WARMUP_ROUNDS; i++ )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ Foo foo = buildRandomFoo();
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+ size = baos.toByteArray().length;
+ }
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+
+ long time = 0;
+ for ( int i = 0; i < BENCHMARK_ROUNDS; i++ )
+ {
+ Foo foo = buildRandomFoo();
+
+ long startTime = System.nanoTime();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( foo );
+
+ time += System.nanoTime() - startTime;
+ assertNotNull( baos.toByteArray() );
+ }
+
+ double avg = time / (double) BENCHMARK_ROUNDS;
+ System.out.println( "Lightning Serialization Avg: " + String.format( "%5.2f", avg ) + " ns, runs: "
+ + BENCHMARK_ROUNDS + ", size: " + size + " bytes" );
+
+ System.runFinalization();
+ System.gc();
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+ }
+
+ @Test
+ public void benchmarkLightningDeserialization()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().serializerDefinitions( new BenchmarkSerializerDefinition() ).build();
+
+ long size = 0;
+ for ( int i = 0; i < WARMUP_ROUNDS; i++ )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ Foo foo = buildRandomFoo();
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+ size = baos.toByteArray().length;
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+
+ long time = 0;
+ for ( int i = 0; i < BENCHMARK_ROUNDS; i++ )
+ {
+ Foo foo = buildRandomFoo();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( foo );
+
+ long startTime = System.nanoTime();
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ time += System.nanoTime() - startTime;
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ double avg = time / (double) BENCHMARK_ROUNDS;
+ System.out.println( "Lightning Deserialization Avg: " + String.format( "%5.2f", avg ) + " ns, runs: "
+ + BENCHMARK_ROUNDS + ", size: " + size + " bytes" );
+
+ System.runFinalization();
+ System.gc();
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+ }
+
+ @Test
+ public void benchmarkJavaSerialization()
+ throws Exception
+ {
+ long size = 0;
+ for ( int i = 0; i < WARMUP_ROUNDS; i++ )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+ Foo foo = buildRandomFoo();
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+ size = baos.toByteArray().length;
+ }
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+
+ long time = 0;
+ for ( int i = 0; i < BENCHMARK_ROUNDS; i++ )
+ {
+ Foo foo = buildRandomFoo();
+
+ long startTime = System.nanoTime();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+ out.writeObject( foo );
+
+ time += System.nanoTime() - startTime;
+ assertNotNull( baos.toByteArray() );
+ }
+
+ double avg = time / (double) BENCHMARK_ROUNDS;
+ System.out.println( "Java Serialization Avg: " + String.format( "%5.2f", avg ) + " ns, runs: "
+ + BENCHMARK_ROUNDS + ", size: " + size + " bytes" );
+
+ System.runFinalization();
+ System.gc();
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+ }
+
+ @Test
+ public void benchmarkJavaDeserialization()
+ throws Exception
+ {
+ long size = 0;
+ for ( int i = 0; i < WARMUP_ROUNDS; i++ )
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+ Foo foo = buildRandomFoo();
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+ size = baos.toByteArray().length;
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ ObjectInputStream in = new ObjectInputStream( bais );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+
+ long time = 0;
+ for ( int i = 0; i < BENCHMARK_ROUNDS; i++ )
+ {
+ Foo foo = buildRandomFoo();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+ out.writeObject( foo );
+
+ long startTime = System.nanoTime();
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ ObjectInputStream in = new ObjectInputStream( bais );
+ Object value = in.readObject();
+
+ time += System.nanoTime() - startTime;
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ double avg = time / (double) BENCHMARK_ROUNDS;
+ System.out.println( "Java Deserialization Avg: " + String.format( "%5.2f", avg ) + " ns, runs: "
+ + BENCHMARK_ROUNDS + ", size: " + size + " bytes" );
+
+ System.runFinalization();
+ System.gc();
+
+ try
+ {
+ Thread.sleep( 5000 );
+ }
+ catch ( Exception e )
+ {
+ }
+ }
+
+ private static final Random RANDOM = new Random( System.nanoTime() );
+
+ private static final String[] STRING_VALUES = { "HGHO", "jldu", "oösd", "JKGH", "HGFG", "JLHL", "GJJK", "JKGH" };
+
+ private static Foo buildRandomFoo()
+ {
+ Foo foo = new Foo();
+ foo.enumValue = RANDOM.nextInt( 100 ) < 50 ? Bar.Value1 : Bar.Value2;
+ foo.someOther = RANDOM.nextInt();
+ foo.value = RANDOM.nextInt( 100 ) < 50 ? null : RANDOM.nextInt();
+ foo.first = STRING_VALUES[RANDOM.nextInt( STRING_VALUES.length )];
+ foo.second = STRING_VALUES[RANDOM.nextInt( STRING_VALUES.length )];
+
+ return foo;
+ }
+
+ public static class BenchmarkSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+ }
+ }
+
+ @SuppressWarnings( "serial" )
+ public static class Foo
+ implements Serializable
+ {
+
+ private String first;
+
+ private String second;
+
+ private Integer value;
+
+ private int someOther;
+
+ @Attribute
+ private Bar enumValue;
+
+ @Attribute
+ public String getFirst()
+ {
+ return first;
+ }
+
+ public void setFirst( String first )
+ {
+ this.first = first;
+ }
+
+ @Attribute
+ public String getSecond()
+ {
+ return second;
+ }
+
+ public void setSecond( String second )
+ {
+ this.second = second;
+ }
+
+ @Attribute
+ public Integer getValue()
+ {
+ return value;
+ }
+
+ public void setValue( Integer value )
+ {
+ this.value = value;
+ }
+
+ @Attribute
+ // Implicitly required
+ public int getSomeOther()
+ {
+ return someOther;
+ }
+
+ public void setSomeOther( int someOther )
+ {
+ this.someOther = someOther;
+ }
+
+ public Bar getEnumValue()
+ {
+ return enumValue;
+ }
+
+ public void setEnumValue( Bar enumValue )
+ {
+ this.enumValue = enumValue;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Foo [hash=@" + hashCode() + ", first=" + first + ", second=" + second + ", value=" + value
+ + ", someOther=" + someOther + ", enumValue=" + enumValue + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( enumValue == null ) ? 0 : enumValue.hashCode() );
+ result = prime * result + ( ( first == null ) ? 0 : first.hashCode() );
+ result = prime * result + ( ( second == null ) ? 0 : second.hashCode() );
+ result = prime * result + someOther;
+ result = prime * result + ( ( value == null ) ? 0 : value.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Foo other = (Foo) obj;
+ if ( enumValue != other.enumValue )
+ return false;
+ if ( first == null )
+ {
+ if ( other.first != null )
+ return false;
+ }
+ else if ( !first.equals( other.first ) )
+ return false;
+ if ( second == null )
+ {
+ if ( other.second != null )
+ return false;
+ }
+ else if ( !second.equals( other.second ) )
+ return false;
+ if ( someOther != other.someOther )
+ return false;
+ if ( value == null )
+ {
+ if ( other.value != null )
+ return false;
+ }
+ else if ( !value.equals( other.value ) )
+ return false;
+ return true;
+ }
+ }
+
+ public static enum Bar
+ {
+ Value1, Value2
+ }
+
+ public static class BarMarshaller
+ extends AbstractObjectMarshaller
+ {
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return type == Bar.class;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ return null;
+ }
+ }
+
+ public static class SomeSpecialIntegerMarshaller
+ extends AbstractObjectMarshaller
+ {
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return type == Integer.class;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ return value;
+ }
+
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/ClassDefinitionContainerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/ClassDefinitionContainerTestCase.java
new file mode 100644
index 0000000..1ff51d3
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/ClassDefinitionContainerTestCase.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.directmemory.lightning.ClassComparisonStrategy;
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.exceptions.ClassDefinitionInconsistentException;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.junit.Test;
+
+public class ClassDefinitionContainerTestCase
+{
+
+ @Test
+ public void testLightningChecksum()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+ }
+
+ @Test( expected = ClassDefinitionInconsistentException.class )
+ public void testLightningChecksumFailing()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer = Lightning.newBuilder().logger( new DebugLogger() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+ }
+
+ @Test
+ public void testSerialVersionUID()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).classComparisonStrategy( ClassComparisonStrategy.SerialVersionUID ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+ }
+
+ @Test( expected = ClassDefinitionInconsistentException.class )
+ public void testSerialVersionUIDFailing()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).classComparisonStrategy( ClassComparisonStrategy.SerialVersionUID ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer = Lightning.newBuilder().logger( new DebugLogger() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+ }
+
+ @Test
+ public void testClassDefinitionContainerTransportLightningChecksum()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+
+ out.writeObject( container );
+ byte[] data = baos.toByteArray();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( data );
+ ObjectInputStream in = new ObjectInputStream( bais );
+
+ ClassDefinitionContainer remoteContainer = (ClassDefinitionContainer) in.readObject();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( remoteContainer );
+ }
+
+ @Test
+ public void testClassDefinitionContainerTransportSerialVersionUID()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).classComparisonStrategy( ClassComparisonStrategy.SerialVersionUID ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream( baos );
+
+ out.writeObject( container );
+ byte[] data = baos.toByteArray();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( data );
+ ObjectInputStream in = new ObjectInputStream( bais );
+
+ ClassDefinitionContainer remoteContainer = (ClassDefinitionContainer) in.readObject();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).classComparisonStrategy( ClassComparisonStrategy.SerialVersionUID ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( remoteContainer );
+ }
+
+ public static class SerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+ serialize( Bar.class ).attributes();
+ }
+ }
+
+ public static class Foo
+ {
+
+ @Attribute
+ private int id;
+
+ @Attribute
+ private String name;
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId( int id )
+ {
+ this.id = id;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+ }
+
+ public static class Bar
+ {
+
+ @Attribute
+ private int id;
+
+ @Attribute
+ private String name;
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId( int id )
+ {
+ this.id = id;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/ComplexClassHierarchyTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/ComplexClassHierarchyTestCase.java
new file mode 100644
index 0000000..9943c40
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/ComplexClassHierarchyTestCase.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.junit.Test;
+
+public class ComplexClassHierarchyTestCase
+{
+
+ @Test
+ public void testSimpleObject()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ foo.setName( "SomeName" );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ @Test
+ public void testSomeMoreComplexObjectWithOneDefinition()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ foo.setName( "SomeName" );
+
+ Complex complex = new Complex();
+ complex.setFoo( foo );
+ complex.setBar( Bar.SomeOtherValue );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( complex );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( complex, value );
+ }
+
+ @Test
+ public void testSomeMoreComplexObjectWithTwoDefinition()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new ParentSerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new ParentSerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ foo.setName( "SomeName" );
+
+ Complex complex = new Complex();
+ complex.setFoo( foo );
+ complex.setBar( Bar.SomeOtherValue );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( complex );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( complex, value );
+ }
+
+ public static class SerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+ serialize( Complex.class ).attributes();
+ }
+ }
+
+ public static class ParentSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+
+ install( new ChildSerializerDefinition() );
+ }
+ }
+
+ public static class ChildSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Complex.class ).attributes();
+ }
+ }
+
+ public static class Foo
+ {
+
+ @Attribute
+ private int id;
+
+ @Attribute
+ private String name;
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId( int id )
+ {
+ this.id = id;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName( String name )
+ {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Foo other = (Foo) obj;
+ if ( id != other.id )
+ return false;
+ if ( name == null )
+ {
+ if ( other.name != null )
+ return false;
+ }
+ else if ( !name.equals( other.name ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Foo [id=" + id + ", name=" + name + "]";
+ }
+ }
+
+ public static class Complex
+ {
+
+ @Attribute
+ private Foo foo;
+
+ @Attribute
+ private Bar bar;
+
+ public Foo getFoo()
+ {
+ return foo;
+ }
+
+ public void setFoo( Foo foo )
+ {
+ this.foo = foo;
+ }
+
+ public Bar getBar()
+ {
+ return bar;
+ }
+
+ public void setBar( Bar bar )
+ {
+ this.bar = bar;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( bar == null ) ? 0 : bar.hashCode() );
+ result = prime * result + ( ( foo == null ) ? 0 : foo.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Complex other = (Complex) obj;
+ if ( bar != other.bar )
+ return false;
+ if ( foo == null )
+ {
+ if ( other.foo != null )
+ return false;
+ }
+ else if ( !foo.equals( other.foo ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Complex [foo=" + foo + ", bar=" + bar + "]";
+ }
+ }
+
+ public static enum Bar
+ {
+ SomeValue, SomeOtherValue, SomeTotallyDifferentValue
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/GenericTypedTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/GenericTypedTestCase.java
new file mode 100644
index 0000000..b5e0e8f
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/GenericTypedTestCase.java
@@ -0,0 +1,458 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.util.List;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.logging.LogLevel;
+import org.apache.directmemory.lightning.logging.LoggerAdapter;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.junit.Test;
+
+public class GenericTypedTestCase
+{
+
+ @Test
+ public void testSimpleObject()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ // foo.setName("SomeName");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( foo );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( foo, value );
+ }
+
+ @Test
+ public void testSomeMoreComplexObjectWithOneDefinition()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new SerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ // foo.setName("SomeName");
+
+ Complex complex = new Complex();
+ complex.setFoo( foo );
+ complex.setBar( Bar.SomeOtherValue );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( complex );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( complex, value );
+ }
+
+ @Test
+ public void testSomeMoreComplexObjectWithTwoDefinition()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new ParentSerializerDefinition() ).build();
+
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new ParentSerializerDefinition() ).build();
+
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.setId( 10000 );
+ // foo.setName("SomeName");
+
+ Complex complex = new Complex();
+ complex.setFoo( foo );
+ complex.setBar( Bar.SomeOtherValue );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( complex );
+
+ assertNotNull( baos );
+ assertNotNull( out );
+ assertNotNull( baos.toByteArray() );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ assertNotNull( value );
+ assertEquals( complex, value );
+ }
+
+ public static class SerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+ serialize( Complex.class ).attributes();
+ }
+ }
+
+ public static class ParentSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+
+ install( new ChildSerializerDefinition() );
+ }
+ }
+
+ public static class ChildSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Complex.class ).attributes();
+ }
+ }
+
+ public static class Foo
+ {
+
+ @Attribute
+ private int id;
+
+ @Attribute
+ private List<String> names;
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId( int id )
+ {
+ this.id = id;
+ }
+
+ public List<String> getNames()
+ {
+ return names;
+ }
+
+ public void setNames( List<String> names )
+ {
+ this.names = names;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ // result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Foo other = (Foo) obj;
+ if ( id != other.id )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Foo [id=" + id + ", names=" + names + "]";
+ }
+ }
+
+ public static class Complex
+ {
+
+ @Attribute
+ private Foo foo;
+
+ @Attribute
+ private Bar bar;
+
+ public Foo getFoo()
+ {
+ return foo;
+ }
+
+ public void setFoo( Foo foo )
+ {
+ this.foo = foo;
+ }
+
+ public Bar getBar()
+ {
+ return bar;
+ }
+
+ public void setBar( Bar bar )
+ {
+ this.bar = bar;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( bar == null ) ? 0 : bar.hashCode() );
+ result = prime * result + ( ( foo == null ) ? 0 : foo.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Complex other = (Complex) obj;
+ if ( bar != other.bar )
+ return false;
+ if ( foo == null )
+ {
+ if ( other.foo != null )
+ return false;
+ }
+ else if ( !foo.equals( other.foo ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Complex [foo=" + foo + ", bar=" + bar + "]";
+ }
+ }
+
+ public static enum Bar
+ {
+ SomeValue, SomeOtherValue, SomeTotallyDifferentValue
+ }
+
+ public static class DebugLogger
+ extends LoggerAdapter
+ {
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ log( LogLevel.Trace, message, null );
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ log( LogLevel.Trace, message, throwable );
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ log( LogLevel.Debug, message, null );
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ log( LogLevel.Debug, message, throwable );
+ }
+
+ @Override
+ public void info( String message )
+ {
+ log( LogLevel.Info, message, null );
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ log( LogLevel.Info, message, throwable );
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ log( LogLevel.Warn, message, null );
+ }
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ log( LogLevel.Warn, message, throwable );
+ }
+
+ @Override
+ public void error( String message )
+ {
+ log( LogLevel.Error, message, null );
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ log( LogLevel.Error, message, throwable );
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ log( LogLevel.Fatal, message, null );
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ log( LogLevel.Fatal, message, throwable );
+ }
+
+ private void log( LogLevel logLevel, String message, Throwable throwable )
+ {
+ PrintStream stream;
+ if ( throwable != null )
+ {
+ stream = System.err;
+ }
+ else
+ {
+ stream = System.out;
+ }
+
+ stream.println( getName() + " - " + logLevel.name() + ": " + message );
+ if ( throwable != null )
+ {
+ throwable.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/PropertyFinderTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/PropertyFinderTestCase.java
new file mode 100644
index 0000000..9bf3188
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/PropertyFinderTestCase.java
@@ -0,0 +1,626 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.junit.Test;
+
+public class PropertyFinderTestCase
+{
+
+ @Test
+ public void testCustomDefinedPropertyFind1()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Standard.class ).attributes( attribute( "value1" ) );
+ serialize( Standard.class ).attributes( attribute( "value2" ) );
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Standard.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 2, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Standard standard = new Standard();
+ standard.setValue1( "Foo" );
+ standard.setValue2( 321 );
+ out.writeObject( standard );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Standard result = (Standard) in.readObject();
+
+ assertEquals( standard, result );
+ }
+
+ @Test
+ public void testCustomDefinedPropertyFind2()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Standard.class ).attributes( attribute( "value1" ), attribute( "value2" ) );
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Standard.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 2, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Standard standard = new Standard();
+ standard.setValue1( "Foo" );
+ standard.setValue2( 321 );
+ out.writeObject( standard );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Standard result = (Standard) in.readObject();
+
+ assertEquals( standard, result );
+ }
+
+ @Test
+ public void testStandardPropertyFind()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Standard.class ).attributes();
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Standard.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 2, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Standard standard = new Standard();
+ standard.setValue1( "Foo" );
+ standard.setValue2( 321 );
+ out.writeObject( standard );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Standard result = (Standard) in.readObject();
+
+ assertEquals( standard, result );
+ }
+
+ @Test
+ public void testStandardPropertyFindUsingExclude()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Standard.class ).attributes().exclude( "value1" );
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Standard.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 1, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Standard standard = new Standard();
+ standard.setValue1( "Foo" );
+ standard.setValue2( 321 );
+ out.writeObject( standard );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Standard result = (Standard) in.readObject();
+
+ assertNull( "value1 must not be set", result.getValue1() );
+ assertEquals( standard.getValue2(), result.getValue2() );
+ }
+
+ @Test
+ public void testStandardPropertyFindUsingExcludes()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Inherted.class ).attributes().excludes( "value1", "value2" );
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Inherted.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 2, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Inherted inherted = new Inherted();
+ inherted.setValue1( "Foo" );
+ inherted.setValue2( 321 );
+ inherted.setValue3( "Bar" );
+ inherted.setValue4( 123L );
+ out.writeObject( inherted );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Inherted result = (Inherted) in.readObject();
+
+ assertNull( "value1 must not be set", result.getValue1() );
+ assertEquals( result.getValue2(), 0 );
+ assertEquals( inherted.getValue3(), result.getValue3() );
+ assertEquals( inherted.getValue4(), result.getValue4() );
+ }
+
+ @Test
+ public void testInheritancePropertyFind()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Inherted.class ).attributes();
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Inherted.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 4, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Inherted inherted = new Inherted();
+ inherted.setValue1( "Foo" );
+ inherted.setValue2( 321 );
+ inherted.setValue3( "Bar" );
+ inherted.setValue4( 123 );
+ out.writeObject( inherted );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Standard result = (Standard) in.readObject();
+
+ assertEquals( inherted, result );
+ }
+
+ @Test
+ public void testCompositionPropertyFind()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( Composed.class ).attributes();
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( Composed.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 3, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ Composed composed = new Composed( "Foo", 123, "Bar" );
+ out.writeObject( composed );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ Composed result = (Composed) in.readObject();
+
+ assertEquals( composed, result );
+ }
+
+ @Test
+ public void testComposedInheritancePropertyFind()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( ComposedInherted.class ).attributes();
+ }
+ } );
+
+ ClassDescriptorAwareSerializer awareSerializer = (ClassDescriptorAwareSerializer) serializer;
+ ClassDescriptor classDescriptor = awareSerializer.findClassDescriptor( ComposedInherted.class );
+
+ assertNotNull( classDescriptor );
+ assertEquals( 3, classDescriptor.getPropertyDescriptors().size() );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ ComposedInherted composedInherted = new ComposedInherted();
+ composedInherted.setValue1( "Foo" );
+ composedInherted.setValue2( 321 );
+ composedInherted.setValue3( "Bar" );
+ out.writeObject( composedInherted );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ ComposedInherted result = (ComposedInherted) in.readObject();
+
+ assertEquals( composedInherted, result );
+ }
+
+ public static class Standard
+ {
+
+ @Attribute
+ private String value1;
+
+ @Attribute
+ private int value2;
+
+ public String getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( String value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public int getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( int value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + value2;
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Standard other = (Standard) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Standard [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class Inherted
+ extends Standard
+ {
+
+ @Attribute
+ private String value3;
+
+ @Attribute
+ private long value4;
+
+ public String getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( String value3 )
+ {
+ this.value3 = value3;
+ }
+
+ public long getValue4()
+ {
+ return value4;
+ }
+
+ public void setValue4( long value4 )
+ {
+ this.value4 = value4;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ result = prime * result + (int) ( value4 ^ ( value4 >>> 32 ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( !super.equals( obj ) )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Inherted other = (Inherted) obj;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ if ( value4 != other.value4 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Inherted [value3=" + value3 + ", value4=" + value4 + "]";
+ }
+ }
+
+ public static class ComposedInherted
+ extends Standard
+ implements Foo, Bar
+ {
+
+ private String value3;
+
+ public void setValue3( String value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public String getValue3()
+ {
+ return value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( !super.equals( obj ) )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ComposedInherted other = (ComposedInherted) obj;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ComposedInherted [value3=" + value3 + "]";
+ }
+ }
+
+ public static interface Foo
+ {
+
+ @Attribute
+ String getValue1();
+
+ @Attribute
+ int getValue2();
+ }
+
+ public static interface Bar
+ {
+
+ @Attribute
+ String getValue3();
+ }
+
+ public static class Composed
+ implements Foo, Bar
+ {
+
+ private final String value1;
+
+ private final int value2;
+
+ private final String value3;
+
+ public Composed( String value1, int value2, String value3 )
+ {
+ this.value1 = value1;
+ this.value2 = value2;
+ this.value3 = value3;
+ }
+
+ @Override
+ public String getValue3()
+ {
+ return value3;
+ }
+
+ @Override
+ public String getValue1()
+ {
+ return value1;
+ }
+
+ @Override
+ public int getValue2()
+ {
+ return value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + value2;
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ Composed other = (Composed) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Composed [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/WhatShouldItLookLike.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/WhatShouldItLookLike.java
new file mode 100644
index 0000000..0707020
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/WhatShouldItLookLike.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.MarshallerContext;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractObjectMarshaller;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.configuration.TypeIntrospector;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class WhatShouldItLookLike
+{
+
+ public static void main( String[] args )
+ {
+ Serializer serializer2 =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new ExampleSerializerDefinition() ).build();
+
+ ClassDefinitionContainer container2 = serializer2.getClassDefinitionContainer();
+
+ Serializer remoteSerializer2 =
+ Lightning.newBuilder().logger( new DebugLogger() ).serializerDefinitions( new ExampleSerializerDefinition() ).build();
+
+ remoteSerializer2.setClassDefinitionContainer( container2 );
+
+ Serializer serializer = Lightning.createSerializer( new ExampleSerializerDefinition() );
+ ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ Serializer remoteSerializer = Lightning.createSerializer( new ExampleSerializerDefinition() );
+ remoteSerializer.setClassDefinitionContainer( container );
+
+ Foo foo = new Foo();
+ foo.enumValue = Bar.Value2;
+ foo.first = "first";
+ foo.second = "second";
+ foo.someOther = 123;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+ out.writeObject( foo );
+ System.out.println( foo );
+
+ byte[] data = baos.toByteArray();
+ System.out.println( Arrays.toString( data ) );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( data );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+ Object value = in.readObject();
+ System.out.println( value );
+ }
+
+ public static class ExampleSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ protected void configure()
+ {
+ // Define serializable class using custom implementation of
+ // Marshaller
+ serialize( Bar.class ).using( new BarMarshaller() );
+ serialize( Bar.class ).using( BarMarshaller.class );
+
+ // Define serializable class using annotated members / methods (by
+ // usage of Lightning's @org.apache.directmemory.lightning.metadata.Attribute
+ // annotation)
+ serialize( Foo.class ).attributes();
+ serialize( Foo.class ).attributes().exclude( "value" );
+ serialize( Foo.class ).attributes().exclude( "value1" ).exclude( "value2" );
+ serialize( Foo.class ).attributes().excludes( "value1", "value2" );
+
+ // Define serializable class using annotated members / methods (by
+ // usage of custom annotation)
+ serialize( Foo.class ).attributes( Attribute.class );
+ serialize( Foo.class ).attributes( Attribute.class ).exclude( "value" );
+ serialize( Foo.class ).attributes( Attribute.class ).exclude( "value1" ).exclude( "value2" );
+ serialize( Foo.class ).attributes( Attribute.class ).excludes( "value1", "value2" );
+
+ // Define serializable class using custom definition of attributes
+ serialize( Foo.class ).attributes( attribute( "value" ),
+ attribute( "value" ).using( SomeSpecialIntegerMarshaller.class ),
+ attribute( "value" ).using( new SomeSpecialIntegerMarshaller() ) );
+
+ // Define serializable class using a different implementation of
+ // PropertyFinderStrategy
+ serialize( Foo.class ).using( new FooTypeIntrospector() );
+ serialize( Foo.class ).using( FooTypeIntrospector.class );
+
+ // Install child definition
+ install( new SomeChildSerializerDefinition() );
+ }
+ }
+
+ public static class SomeChildSerializerDefinition
+ extends AbstractSerializerDefinition
+ {
+
+ @Override
+ public void configure()
+ {
+ describesAttributes( Attribute.class );
+
+ serialize( Foo.class ).attributes();
+ }
+ }
+
+ public static class FooTypeIntrospector
+ implements TypeIntrospector
+ {
+
+ @Override
+ public List<PropertyDescriptor> introspect( Type type, MarshallerStrategy marshallerStrategy,
+ MarshallerContext marshallerContext,
+ PropertyDescriptorFactory propertyDescriptorFactory )
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }
+
+ public static class Foo
+ {
+
+ private String first;
+
+ private String second;
+
+ private Integer value;
+
+ private int someOther;
+
+ @Attribute
+ private Bar enumValue;
+
+ @Attribute( required = true )
+ public String getFirst()
+ {
+ return first;
+ }
+
+ public void setFirst( String first )
+ {
+ this.first = first;
+ }
+
+ @Attribute
+ public String getSecond()
+ {
+ return second;
+ }
+
+ public void setSecond( String second )
+ {
+ this.second = second;
+ }
+
+ @Attribute
+ public Integer getValue()
+ {
+ return value;
+ }
+
+ public void setValue( Integer value )
+ {
+ this.value = value;
+ }
+
+ @Attribute
+ // Implicitly required
+ public int getSomeOther()
+ {
+ return someOther;
+ }
+
+ public void setSomeOther( int someOther )
+ {
+ this.someOther = someOther;
+ }
+
+ public Bar getEnumValue()
+ {
+ return enumValue;
+ }
+
+ public void setEnumValue( Bar enumValue )
+ {
+ this.enumValue = enumValue;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Foo [hash=@" + hashCode() + ", first=" + first + ", second=" + second + ", value=" + value
+ + ", someOther=" + someOther + ", enumValue=" + enumValue + "]";
+ }
+ }
+
+ public static enum Bar
+ {
+ Value1, Value2
+ }
+
+ @Retention( RetentionPolicy.RUNTIME )
+ public static @interface Attribute
+ {
+
+ boolean required() default false;
+ }
+
+ public static class BarMarshaller
+ extends AbstractObjectMarshaller
+ {
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return type == Bar.class;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ return null;
+ }
+ }
+
+ public static class SomeSpecialIntegerMarshaller
+ extends AbstractObjectMarshaller
+ {
+
+ @Override
+ public boolean acceptType( Class<?> type )
+ {
+ return type == Integer.class;
+ }
+
+ @Override
+ public void marshall( Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+ }
+
+ @Override
+ public <V> V unmarshall( V value, PropertyDescriptor propertyDescriptor, DataInput dataInput,
+ SerializationContext serializationContext )
+ throws IOException
+ {
+
+ return value;
+ }
+
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/ClassDefinitionContainerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/ClassDefinitionContainerTestCase.java
new file mode 100644
index 0000000..ccc8e89
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/ClassDefinitionContainerTestCase.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.internal.InternalClassDefinition;
+import org.apache.directmemory.lightning.internal.InternalClassDefinitionContainer;
+import org.apache.directmemory.lightning.logging.LoggerAdapter;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.junit.Test;
+import org.objectweb.asm.ClassVisitor;
+
+public class ClassDefinitionContainerTestCase
+{
+
+ private static final Class<?>[] CLASSES = { ClassVisitor.class };
+
+ @Test
+ public void testClassDefinitionContainer()
+ throws Exception
+ {
+ final Set<ClassDefinition> classDefinitions = new HashSet<ClassDefinition>();
+
+ for ( Class<?> clazz : CLASSES )
+ {
+ PropertyDescriptor label = null;
+ classDefinitions.add( new InternalClassDefinition( clazz, Collections.<PropertyDescriptor> emptyList(),
+ new LoggerAdapter() ) );
+ }
+
+ ClassDefinitionContainer classDefinitionContainer = new InternalClassDefinitionContainer( classDefinitions );
+
+ for ( ClassDefinition classDefinition : classDefinitionContainer.getClassDefinitions() )
+ {
+ Class<?> clazz = null;
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorTestCase.java
new file mode 100644
index 0000000..85eb452
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/ReflectionPropertyAccessorTestCase.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import org.apache.directmemory.lightning.internal.beans.ReflectionPropertyAccessorFactory;
+import org.apache.directmemory.lightning.metadata.ArrayPropertyAccessor;
+import org.junit.Test;
+
+public class ReflectionPropertyAccessorTestCase
+{
+
+ @Test
+ public void testUnsafeBooleanArray()
+ throws Exception
+ {
+ class BooleanArrayTest
+ {
+
+ private boolean[] array = new boolean[10];
+ }
+
+ Field field = BooleanArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, BooleanArrayTest.class );
+
+ BooleanArrayTest test = new BooleanArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i % 2 == 0 ? true : false;
+ }
+
+ BooleanArrayTest result = new BooleanArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ boolean value = propertyAccessor.readBoolean( test.array, i );
+ propertyAccessor.writeBoolean( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeByteArray()
+ throws Exception
+ {
+ class ByteArrayTest
+ {
+
+ private byte[] array = new byte[10];
+ }
+
+ Field field = ByteArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, ByteArrayTest.class );
+
+ ByteArrayTest test = new ByteArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (byte) ( i + 1 );
+ }
+
+ ByteArrayTest result = new ByteArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ byte value = propertyAccessor.readByte( test.array, i );
+ propertyAccessor.writeByte( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeShortArray()
+ throws Exception
+ {
+ class ShortArrayTest
+ {
+
+ private short[] array = new short[10];
+ }
+
+ Field field = ShortArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, ShortArrayTest.class );
+
+ ShortArrayTest test = new ShortArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (short) ( i + 1 );
+ }
+
+ ShortArrayTest result = new ShortArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ short value = propertyAccessor.readShort( test.array, i );
+ propertyAccessor.writeShort( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeIntArray()
+ throws Exception
+ {
+ class IntArrayTest
+ {
+
+ private int[] array = new int[10];
+ }
+
+ Field field = IntArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, IntArrayTest.class );
+
+ IntArrayTest test = new IntArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1;
+ }
+
+ IntArrayTest result = new IntArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ int value = propertyAccessor.readInt( test.array, i );
+ propertyAccessor.writeInt( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeLongArray()
+ throws Exception
+ {
+ class LongArrayTest
+ {
+
+ private long[] array = new long[10];
+ }
+
+ Field field = LongArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, LongArrayTest.class );
+
+ LongArrayTest test = new LongArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1;
+ }
+
+ LongArrayTest result = new LongArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ long value = propertyAccessor.readLong( test.array, i );
+ propertyAccessor.writeLong( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeFloatArray()
+ throws Exception
+ {
+ class FloatArrayTest
+ {
+
+ private float[] array = new float[10];
+ }
+
+ Field field = FloatArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, FloatArrayTest.class );
+
+ FloatArrayTest test = new FloatArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (float) ( i + 1. );
+ }
+
+ FloatArrayTest result = new FloatArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ float value = propertyAccessor.readFloat( test.array, i );
+ propertyAccessor.writeFloat( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeDoubleArray()
+ throws Exception
+ {
+ class DoubleArrayTest
+ {
+
+ private double[] array = new double[10];
+ }
+
+ Field field = DoubleArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, DoubleArrayTest.class );
+
+ DoubleArrayTest test = new DoubleArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1.;
+ }
+
+ DoubleArrayTest result = new DoubleArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ double value = propertyAccessor.readDouble( test.array, i );
+ propertyAccessor.writeDouble( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeObjectArray()
+ throws Exception
+ {
+ class ObjectArrayTest
+ {
+
+ private String[] array = new String[10];
+ }
+
+ Field field = ObjectArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new ReflectionPropertyAccessorFactory().fieldAccess( field, ObjectArrayTest.class );
+
+ ObjectArrayTest test = new ObjectArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = "Hello" + i;
+ }
+
+ ObjectArrayTest result = new ObjectArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ Object value = propertyAccessor.readObject( test.array, i );
+ propertyAccessor.writeObject( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/UnsafePropertyAccessorTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/UnsafePropertyAccessorTestCase.java
new file mode 100644
index 0000000..10e0ff9
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/beans/UnsafePropertyAccessorTestCase.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.beans;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import org.apache.directmemory.lightning.internal.beans.SunUnsafePropertyAccessorFactory;
+import org.apache.directmemory.lightning.metadata.ArrayPropertyAccessor;
+import org.junit.Test;
+
+public class UnsafePropertyAccessorTestCase
+{
+
+ @Test
+ public void testUnsafeBooleanArray()
+ throws Exception
+ {
+ class BooleanArrayTest
+ {
+
+ private boolean[] array = new boolean[10];
+ }
+
+ Field field = BooleanArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, BooleanArrayTest.class );
+
+ BooleanArrayTest test = new BooleanArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i % 2 == 0 ? true : false;
+ }
+
+ BooleanArrayTest result = new BooleanArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ boolean value = propertyAccessor.readBoolean( test.array, i );
+ propertyAccessor.writeBoolean( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeByteArray()
+ throws Exception
+ {
+ class ByteArrayTest
+ {
+
+ private byte[] array = new byte[10];
+ }
+
+ Field field = ByteArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, ByteArrayTest.class );
+
+ ByteArrayTest test = new ByteArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (byte) ( i + 1 );
+ }
+
+ ByteArrayTest result = new ByteArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ byte value = propertyAccessor.readByte( test.array, i );
+ propertyAccessor.writeByte( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeShortArray()
+ throws Exception
+ {
+ class ShortArrayTest
+ {
+
+ private short[] array = new short[10];
+ }
+
+ Field field = ShortArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, ShortArrayTest.class );
+
+ ShortArrayTest test = new ShortArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (short) ( i + 1 );
+ }
+
+ ShortArrayTest result = new ShortArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ short value = propertyAccessor.readShort( test.array, i );
+ propertyAccessor.writeShort( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeIntArray()
+ throws Exception
+ {
+ class IntArrayTest
+ {
+
+ private int[] array = new int[10];
+ }
+
+ Field field = IntArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, IntArrayTest.class );
+
+ IntArrayTest test = new IntArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1;
+ }
+
+ IntArrayTest result = new IntArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ int value = propertyAccessor.readInt( test.array, i );
+ propertyAccessor.writeInt( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeLongArray()
+ throws Exception
+ {
+ class LongArrayTest
+ {
+
+ private long[] array = new long[10];
+ }
+
+ Field field = LongArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, LongArrayTest.class );
+
+ LongArrayTest test = new LongArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1;
+ }
+
+ LongArrayTest result = new LongArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ long value = propertyAccessor.readLong( test.array, i );
+ propertyAccessor.writeLong( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeFloatArray()
+ throws Exception
+ {
+ class FloatArrayTest
+ {
+
+ private float[] array = new float[10];
+ }
+
+ Field field = FloatArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, FloatArrayTest.class );
+
+ FloatArrayTest test = new FloatArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = (float) ( i + 1. );
+ }
+
+ FloatArrayTest result = new FloatArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ float value = propertyAccessor.readFloat( test.array, i );
+ propertyAccessor.writeFloat( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeDoubleArray()
+ throws Exception
+ {
+ class DoubleArrayTest
+ {
+
+ private double[] array = new double[10];
+ }
+
+ Field field = DoubleArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, DoubleArrayTest.class );
+
+ DoubleArrayTest test = new DoubleArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = i + 1.;
+ }
+
+ DoubleArrayTest result = new DoubleArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ double value = propertyAccessor.readDouble( test.array, i );
+ propertyAccessor.writeDouble( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+
+ @Test
+ public void testUnsafeObjectArray()
+ throws Exception
+ {
+ class ObjectArrayTest
+ {
+
+ private String[] array = new String[10];
+ }
+
+ Field field = ObjectArrayTest.class.getDeclaredField( "array" );
+ ArrayPropertyAccessor propertyAccessor =
+ (ArrayPropertyAccessor) new SunUnsafePropertyAccessorFactory().fieldAccess( field, ObjectArrayTest.class );
+
+ ObjectArrayTest test = new ObjectArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ test.array[i] = "Hello" + i;
+ }
+
+ ObjectArrayTest result = new ObjectArrayTest();
+ for ( int i = 0; i < 10; i++ )
+ {
+ Object value = propertyAccessor.readObject( test.array, i );
+ propertyAccessor.writeObject( result.array, i, value );
+ }
+
+ Arrays.equals( test.array, result.array );
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ArrayMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ArrayMarshallerTestCase.java
new file mode 100644
index 0000000..92136b3
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ArrayMarshallerTestCase.java
@@ -0,0 +1,929 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Random;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.io.SerializerInputStream;
+import org.apache.directmemory.lightning.io.SerializerOutputStream;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class ArrayMarshallerTestCase
+{
+
+ private static final Random RANDOM = new Random( -System.nanoTime() );
+
+ @Test
+ public void testBooleanArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ BooleanArray.class ).attributes();
+ }
+ } ).build();
+
+ BooleanArray test = new BooleanArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (boolean[]) array )[index] = RANDOM.nextBoolean();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ BooleanArray result = (BooleanArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testByteArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( ByteArray.class ).attributes();
+ }
+ } );
+
+ ByteArray test = new ByteArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (byte[]) array )[index] = (byte) ( RANDOM.nextInt( 256 ) - 127 );
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ ByteArray result = (ByteArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testCharArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( CharArray.class ).attributes();
+ }
+ } );
+
+ CharArray test = new CharArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (char[]) array )[index] = (char) ( RANDOM.nextInt( 256 ) - 127 );
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ CharArray result = (CharArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testShortArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( ShortArray.class ).attributes();
+ }
+ } );
+
+ ShortArray test = new ShortArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (short[]) array )[index] = (short) ( RANDOM.nextInt( 256 ) - 127 );
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ ShortArray result = (ShortArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testIntArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( IntArray.class ).attributes();
+ }
+ } );
+
+ IntArray test = new IntArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (int[]) array )[index] = RANDOM.nextInt();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ IntArray result = (IntArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testLongArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( LongArray.class ).attributes();
+ }
+ } );
+
+ LongArray test = new LongArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (long[]) array )[index] = RANDOM.nextLong();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ LongArray result = (LongArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testFloatArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( FloatArray.class ).attributes();
+ }
+ } );
+
+ FloatArray test = new FloatArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (float[]) array )[index] = RANDOM.nextFloat();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ FloatArray result = (FloatArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testDoubleArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( DoubleArray.class ).attributes();
+ }
+ } );
+
+ DoubleArray test = new DoubleArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (double[]) array )[index] = RANDOM.nextDouble();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ DoubleArray result = (DoubleArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testObjectArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer = Lightning.createSerializer( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize( ObjectArray.class ).attributes();
+ }
+ } );
+
+ ObjectArray test = new ObjectArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (Object[]) array )[index] = "Hello-" + RANDOM.nextInt();
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ ObjectArray result = (ObjectArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ @Test
+ public void testDeepObjectArrayMarshalling()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ DeepObjectArray.class ).attributes();
+ }
+ } ).build();
+
+ DeepObjectArray test = new DeepObjectArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (ObjectArray[]) array )[index] = new ObjectArray();
+ fillArray( new Predicate()
+ {
+
+ @Override
+ public void execute( Object array, int index )
+ {
+ ( (Object[]) array )[index] = "Hello-" + RANDOM.nextInt();
+ }
+ }, ( (ObjectArray[]) array )[index].array );
+ }
+ }, test.array );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SerializerOutputStream out = new SerializerOutputStream( baos, serializer );
+
+ out.writeObject( test );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ SerializerInputStream in = new SerializerInputStream( bais, serializer );
+
+ DeepObjectArray result = (DeepObjectArray) in.readObject();
+
+ assertNotNull( result );
+ assertEquals( test, result );
+ }
+
+ private static void fillArray( Predicate predicate, Object array )
+ {
+ for ( int i = 0; i < 10; i++ )
+ {
+ predicate.execute( array, i );
+ }
+ }
+
+ private static interface Predicate
+ {
+
+ void execute( Object array, int index );
+ }
+
+ public static class BooleanArray
+ {
+
+ @Attribute
+ private boolean[] array = new boolean[10];
+
+ public boolean[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( boolean[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ BooleanArray other = (BooleanArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BooleanArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class ByteArray
+ {
+
+ @Attribute
+ private byte[] array = new byte[10];
+
+ public byte[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( byte[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ByteArray other = (ByteArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ByteArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class CharArray
+ {
+
+ @Attribute
+ private char[] array = new char[10];
+
+ public char[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( char[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ CharArray other = (CharArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "CharArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class ShortArray
+ {
+
+ @Attribute
+ private short[] array = new short[10];
+
+ public short[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( short[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ShortArray other = (ShortArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ShortArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class IntArray
+ {
+
+ @Attribute
+ private int[] array = new int[10];
+
+ public int[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( int[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ IntArray other = (IntArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "IntArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class LongArray
+ {
+
+ @Attribute
+ private long[] array = new long[10];
+
+ public long[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( long[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ LongArray other = (LongArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "LongArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class FloatArray
+ {
+
+ @Attribute
+ private float[] array = new float[10];
+
+ public float[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( float[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ FloatArray other = (FloatArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "FloatArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class DoubleArray
+ {
+
+ @Attribute
+ private double[] array = new double[10];
+
+ public double[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( double[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ DoubleArray other = (DoubleArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "DoubleArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class ObjectArray
+ {
+
+ @Attribute
+ private String[] array = new String[10];
+
+ public String[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( String[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ObjectArray other = (ObjectArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ObjectArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+
+ public static class DeepObjectArray
+ {
+
+ @Attribute
+ private ObjectArray[] array = new ObjectArray[10];
+
+ public ObjectArray[] getArray()
+ {
+ return array;
+ }
+
+ public void setArray( ObjectArray[] array )
+ {
+ this.array = array;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode( array );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ DeepObjectArray other = (DeepObjectArray) obj;
+ if ( !Arrays.equals( array, other.array ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "DeepObjectArray [array=" + Arrays.toString( array ) + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshallerTestCase.java
new file mode 100644
index 0000000..1ddef48
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigDecimalMarshallerTestCase.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.Random;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class BigDecimalMarshallerTestCase
+{
+
+ @Test
+ public void testBigInteger()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ BigDecimalHolder.class ).attributes();
+ }
+ } ).build();
+
+ Random random = new Random( -System.nanoTime() );
+
+ BigDecimalHolder value = new BigDecimalHolder();
+ value.setValue1( BigDecimal.valueOf( random.nextLong() ).multiply( BigDecimal.valueOf( random.nextLong() ) ) );
+ value.setValue2( null );
+ value.setValue3( BigDecimal.valueOf( random.nextLong() ).subtract( BigDecimal.valueOf( random.nextLong() ) ) );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new BigDecimalHolder();
+ value.setValue1( BigDecimal.valueOf( random.nextLong() ).min( BigDecimal.valueOf( random.nextLong() ) ) );
+ value.setValue2( BigDecimal.valueOf( random.nextLong() ).divideToIntegralValue( BigDecimal.valueOf( random.nextLong() ) ) );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new BigDecimalHolder();
+ value.setValue1( null );
+ value.setValue2( BigDecimal.valueOf( random.nextLong() ).max( BigDecimal.valueOf( random.nextLong() ) ) );
+ value.setValue3( BigDecimal.valueOf( random.nextLong() ).add( BigDecimal.valueOf( random.nextLong() ) ) );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class BigDecimalHolder
+ {
+
+ @Attribute
+ private BigDecimal value1;
+
+ @Attribute
+ private BigDecimal value2;
+
+ @Attribute
+ private BigDecimal value3;
+
+ public BigDecimal getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( BigDecimal value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public BigDecimal getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( BigDecimal value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public BigDecimal getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( BigDecimal value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ BigDecimalHolder other = (BigDecimalHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BigIntegerHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshallerTestCase.java
new file mode 100644
index 0000000..540666a
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BigIntegerMarshallerTestCase.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class BigIntegerMarshallerTestCase
+{
+
+ @Test
+ public void testBigInteger()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ BigIntegerHolder.class ).attributes();
+ }
+ } ).build();
+
+ Random random = new Random( -System.nanoTime() );
+
+ BigIntegerHolder value = new BigIntegerHolder();
+ value.setValue1( BigInteger.valueOf( random.nextLong() ).multiply( BigInteger.valueOf( random.nextLong() ) ) );
+ value.setValue2( null );
+ value.setValue3( BigInteger.valueOf( random.nextLong() ).subtract( BigInteger.valueOf( random.nextLong() ) ) );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new BigIntegerHolder();
+ value.setValue1( BigInteger.valueOf( random.nextLong() ).or( BigInteger.valueOf( random.nextLong() ) ) );
+ value.setValue2( BigInteger.valueOf( random.nextLong() ).divide( BigInteger.valueOf( random.nextLong() ) ) );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new BigIntegerHolder();
+ value.setValue1( null );
+ value.setValue2( BigInteger.valueOf( random.nextLong() ).and( BigInteger.valueOf( random.nextLong() ) ) );
+ value.setValue3( BigInteger.valueOf( random.nextLong() ).add( BigInteger.valueOf( random.nextLong() ) ) );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class BigIntegerHolder
+ {
+
+ @Attribute
+ private BigInteger value1;
+
+ @Attribute
+ private BigInteger value2;
+
+ @Attribute
+ private BigInteger value3;
+
+ public BigInteger getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( BigInteger value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public BigInteger getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( BigInteger value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public BigInteger getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( BigInteger value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ BigIntegerHolder other = (BigIntegerHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BigIntegerHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshallerTestCase.java
new file mode 100644
index 0000000..c7d15ac
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/BooleanMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class BooleanMarshallerTestCase
+{
+
+ @Test
+ public void testBooleanPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( true );
+ value.setValue2( false );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( false );
+ value.setValue2( true );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testBooleanWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( true );
+ value.setValue2( null );
+ value.setValue3( false );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( false );
+ value.setValue2( true );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( true );
+ value.setValue3( false );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private boolean value1;
+
+ @Attribute
+ private boolean value2;
+
+ public boolean isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( boolean value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public boolean isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( boolean value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( value1 ? 1231 : 1237 );
+ result = prime * result + ( value2 ? 1231 : 1237 );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Boolean value1;
+
+ @Attribute
+ private Boolean value2;
+
+ @Attribute
+ private Boolean value3;
+
+ public Boolean getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Boolean value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Boolean getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Boolean value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Boolean getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Boolean value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshallerTestCase.java
new file mode 100644
index 0000000..a564941
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ByteMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class ByteMarshallerTestCase
+{
+
+ @Test
+ public void testBytePrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( (byte) 0 );
+ value.setValue2( Byte.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( (byte) -10 );
+ value.setValue2( (byte) 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testByteWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Byte.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( (byte) 34 );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( (byte) 0 );
+ value.setValue2( Byte.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( (byte) -1 );
+ value.setValue3( Byte.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private byte value1;
+
+ @Attribute
+ private byte value2;
+
+ public byte isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( byte value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public byte isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( byte value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + value1;
+ result = prime * result + value2;
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Byte value1;
+
+ @Attribute
+ private Byte value2;
+
+ @Attribute
+ private Byte value3;
+
+ public Byte getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Byte value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Byte getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Byte value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Byte getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Byte value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshallerTestCase.java
new file mode 100644
index 0000000..309d56e
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/CharacterMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class CharacterMarshallerTestCase
+{
+
+ @Test
+ public void testCharacterPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( (char) 0 );
+ value.setValue2( Character.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( (char) -10 );
+ value.setValue2( (char) 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testCharacterWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Character.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( (char) 34 );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( (char) 0 );
+ value.setValue2( Character.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( (char) -1 );
+ value.setValue3( Character.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private char value1;
+
+ @Attribute
+ private char value2;
+
+ public char isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( char value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public char isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( char value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + value1;
+ result = prime * result + value2;
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Character value1;
+
+ @Attribute
+ private Character value2;
+
+ @Attribute
+ private Character value3;
+
+ public Character getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Character value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Character getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Character value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Character getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Character value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshallerTestCase.java
new file mode 100644
index 0000000..d20b09c
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/DoubleMarshallerTestCase.java
@@ -0,0 +1,299 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class DoubleMarshallerTestCase
+{
+
+ @Test
+ public void testDoublePrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( 0 );
+ value.setValue2( Double.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( -10 );
+ value.setValue2( 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testDoubleWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Double.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( 34D );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( 0D );
+ value.setValue2( Double.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( -1D );
+ value.setValue3( Double.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private double value1;
+
+ @Attribute
+ private double value2;
+
+ public double isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( double value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public double isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( double value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ long temp;
+ temp = Double.doubleToLongBits( value1 );
+ result = prime * result + (int) ( temp ^ ( temp >>> 32 ) );
+ temp = Double.doubleToLongBits( value2 );
+ result = prime * result + (int) ( temp ^ ( temp >>> 32 ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( Double.doubleToLongBits( value1 ) != Double.doubleToLongBits( other.value1 ) )
+ return false;
+ if ( Double.doubleToLongBits( value2 ) != Double.doubleToLongBits( other.value2 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Double value1;
+
+ @Attribute
+ private Double value2;
+
+ @Attribute
+ private Double value3;
+
+ public Double getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Double value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Double getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Double value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Double getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Double value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshallerTestCase.java
new file mode 100644
index 0000000..9ea3ea2
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/FloatMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class FloatMarshallerTestCase
+{
+
+ @Test
+ public void testFloatPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( 0 );
+ value.setValue2( Float.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( -10 );
+ value.setValue2( 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testFloatWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Float.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( 34F );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( 0F );
+ value.setValue2( Float.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( -1F );
+ value.setValue3( Float.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private float value1;
+
+ @Attribute
+ private float value2;
+
+ public float isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( float value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public float isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( float value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Float.floatToIntBits( value1 );
+ result = prime * result + Float.floatToIntBits( value2 );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( Float.floatToIntBits( value1 ) != Float.floatToIntBits( other.value1 ) )
+ return false;
+ if ( Float.floatToIntBits( value2 ) != Float.floatToIntBits( other.value2 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Float value1;
+
+ @Attribute
+ private Float value2;
+
+ @Attribute
+ private Float value3;
+
+ public Float getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Float value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Float getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Float value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Float getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Float value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshallerTestCase.java
new file mode 100644
index 0000000..cbeb815
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/IntegerMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class IntegerMarshallerTestCase
+{
+
+ @Test
+ public void testIntegerPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( 0 );
+ value.setValue2( Integer.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( (short) -10 );
+ value.setValue2( (short) 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testIntegerWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Integer.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( 34 );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( 0 );
+ value.setValue2( Integer.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( -1 );
+ value.setValue3( Integer.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private int value1;
+
+ @Attribute
+ private int value2;
+
+ public int isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( int value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public int isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( int value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + value1;
+ result = prime * result + value2;
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Integer value1;
+
+ @Attribute
+ private Integer value2;
+
+ @Attribute
+ private Integer value3;
+
+ public Integer getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Integer value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Integer getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Integer value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Integer getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Integer value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshallerTestCase.java
new file mode 100644
index 0000000..f9f8672
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ListMarshallerTestCase.java
@@ -0,0 +1,314 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class ListMarshallerTestCase
+{
+
+ @Test
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public void testNoGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ NoGenericTypeList.class ).attributes();
+ }
+ } ).build();
+
+ List list = new ArrayList();
+ list.add( "Foo" );
+ list.add( 20 );
+ list.add( null );
+ list.add( BigInteger.TEN );
+
+ NoGenericTypeList value = new NoGenericTypeList();
+ value.setList( list );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testSimpleGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ SimpleGenericTypeList.class ).attributes();
+ }
+ } ).build();
+
+ List<String> list = new ArrayList<String>();
+ list.add( "Foo" );
+ list.add( "Bar" );
+ list.add( null );
+ list.add( "Rhabarbar" );
+
+ SimpleGenericTypeList value = new SimpleGenericTypeList();
+ value.setList( list );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testComplexGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ ComplexGenericTypeList.class ).attributes();
+ }
+ } ).build();
+
+ List<List<String>> list = new ArrayList<List<String>>();
+
+ List<String> list1 = new ArrayList<String>();
+ list1.add( "Foo" );
+ list1.add( "Bar" );
+ list1.add( null );
+ list1.add( "Rhabarbar" );
+
+ List<String> list2 = new ArrayList<String>();
+ list2.add( null );
+ list2.add( "Rhabarbar" );
+ list2.add( "Foo" );
+ list2.add( "Bar" );
+
+ list.add( list1 );
+ list.add( list2 );
+
+ ComplexGenericTypeList value = new ComplexGenericTypeList();
+ value.setList( list );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ public static class NoGenericTypeList
+ {
+
+ @Attribute
+ private List list;
+
+ public List getList()
+ {
+ return list;
+ }
+
+ public void setList( List list )
+ {
+ this.list = list;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( list == null ) ? 0 : list.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ NoGenericTypeList other = (NoGenericTypeList) obj;
+ if ( list == null )
+ {
+ if ( other.list != null )
+ return false;
+ }
+ else if ( !list.equals( other.list ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "NoGenericTypeList [list=" + list + "]";
+ }
+ }
+
+ public static class SimpleGenericTypeList
+ {
+
+ @Attribute
+ private List<String> list;
+
+ public List<String> getList()
+ {
+ return list;
+ }
+
+ public void setList( List<String> list )
+ {
+ this.list = list;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( list == null ) ? 0 : list.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ SimpleGenericTypeList other = (SimpleGenericTypeList) obj;
+ if ( list == null )
+ {
+ if ( other.list != null )
+ return false;
+ }
+ else if ( !list.equals( other.list ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "SimpleGenericTypeList [list=" + list + "]";
+ }
+ }
+
+ public static class ComplexGenericTypeList
+ {
+
+ @Attribute
+ private List<List<String>> list;
+
+ public List<List<String>> getList()
+ {
+ return list;
+ }
+
+ public void setList( List<List<String>> list )
+ {
+ this.list = list;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( list == null ) ? 0 : list.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ComplexGenericTypeList other = (ComplexGenericTypeList) obj;
+ if ( list == null )
+ {
+ if ( other.list != null )
+ return false;
+ }
+ else if ( !list.equals( other.list ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ComplexGenericTypeList [list=" + list + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshallerTestCase.java
new file mode 100644
index 0000000..be33b3c
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/LongMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class LongMarshallerTestCase
+{
+
+ @Test
+ public void testLongPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( 0 );
+ value.setValue2( Long.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( -10 );
+ value.setValue2( 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testLongWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Long.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( 34L );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( 0L );
+ value.setValue2( Long.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( -1L );
+ value.setValue3( Long.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private long value1;
+
+ @Attribute
+ private long value2;
+
+ public long isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( long value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public long isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( long value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) ( value1 ^ ( value1 >>> 32 ) );
+ result = prime * result + (int) ( value2 ^ ( value2 >>> 32 ) );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Long value1;
+
+ @Attribute
+ private Long value2;
+
+ @Attribute
+ private Long value3;
+
+ public Long getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Long value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Long getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Long value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Long getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Long value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshallerTestCase.java
new file mode 100644
index 0000000..da3b546
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/MapMarshallerTestCase.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class MapMarshallerTestCase
+{
+
+ @Test
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public void testNoGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ NoGenericTypeMap.class ).attributes();
+ }
+ } ).build();
+
+ Map map = new HashMap();
+ map.put( "Foo", 20 );
+ map.put( 21, "foo" );
+ map.put( "bar", null );
+ map.put( 44, BigInteger.TEN );
+
+ NoGenericTypeMap value = new NoGenericTypeMap();
+ value.setMap( map );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testSimpleGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ SimpleGenericTypeMap.class ).attributes();
+ }
+ } ).build();
+
+ Map<String, Integer> map = new HashMap<String, Integer>();
+ map.put( "Foo", 21 );
+ map.put( "Bar", Integer.MAX_VALUE );
+ map.put( "Rhabarbar", null );
+
+ SimpleGenericTypeMap value = new SimpleGenericTypeMap();
+ value.setMap( map );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testComplexGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ ComplexGenericTypeSet.class ).attributes();
+ }
+ } ).build();
+
+ Set<Set<String>> set = new HashSet<Set<String>>();
+
+ Set<String> set1 = new HashSet<String>();
+ set1.add( "Foo" );
+ set1.add( "Bar" );
+ set1.add( null );
+ set1.add( "Rhabarbar" );
+
+ Set<String> set2 = new HashSet<String>();
+ set2.add( null );
+ set2.add( "Rhabarbar" );
+ set2.add( "Foo" );
+ set2.add( "Bar" );
+
+ set.add( set1 );
+ set.add( set2 );
+
+ ComplexGenericTypeSet value = new ComplexGenericTypeSet();
+ value.setSet( set );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ public static class NoGenericTypeMap
+ {
+
+ @Attribute
+ private Map map;
+
+ public Map getmap()
+ {
+ return map;
+ }
+
+ public void setMap( Map map )
+ {
+ this.map = map;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( map == null ) ? 0 : map.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ NoGenericTypeMap other = (NoGenericTypeMap) obj;
+ if ( map == null )
+ {
+ if ( other.map != null )
+ return false;
+ }
+ else if ( !map.equals( other.map ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "NoGenericTypeMap [map=" + map + "]";
+ }
+ }
+
+ public static class SimpleGenericTypeMap
+ {
+
+ @Attribute
+ private Map<String, Integer> map;
+
+ public Map<String, Integer> getMap()
+ {
+ return map;
+ }
+
+ public void setMap( Map<String, Integer> map )
+ {
+ this.map = map;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( map == null ) ? 0 : map.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ SimpleGenericTypeMap other = (SimpleGenericTypeMap) obj;
+ if ( map == null )
+ {
+ if ( other.map != null )
+ return false;
+ }
+ else if ( !map.equals( other.map ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "SimpleGenericTypeMap [map=" + map + "]";
+ }
+ }
+
+ public static class ComplexGenericTypeSet
+ {
+
+ @Attribute
+ private Set<Set<String>> set;
+
+ public Set<Set<String>> getSet()
+ {
+ return set;
+ }
+
+ public void setSet( Set<Set<String>> set )
+ {
+ this.set = set;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( set == null ) ? 0 : set.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ComplexGenericTypeSet other = (ComplexGenericTypeSet) obj;
+ if ( set == null )
+ {
+ if ( other.set != null )
+ return false;
+ }
+ else if ( !set.equals( other.set ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ComplexGenericTypeSet [set=" + set + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshallerTestCase.java
new file mode 100644
index 0000000..aa24909
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/SetMarshallerTestCase.java
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class SetMarshallerTestCase
+{
+
+ @Test
+ @SuppressWarnings( { "rawtypes", "unchecked" } )
+ public void testNoGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ NoGenericTypeSet.class ).attributes();
+ }
+ } ).build();
+
+ Set set = new HashSet();
+ set.add( "Foo" );
+ set.add( 20 );
+ set.add( null );
+ set.add( BigInteger.TEN );
+
+ NoGenericTypeSet value = new NoGenericTypeSet();
+ value.setSet( set );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testSimpleGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ SimpleGenericTypeSet.class ).attributes();
+ }
+ } ).build();
+
+ Set<String> set = new HashSet<String>();
+ set.add( "Foo" );
+ set.add( "Bar" );
+ set.add( null );
+ set.add( "Rhabarbar" );
+
+ SimpleGenericTypeSet value = new SimpleGenericTypeSet();
+ value.setSet( set );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testComplexGenericTypeList()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ ComplexGenericTypeSet.class ).attributes();
+ }
+ } ).build();
+
+ Set<Set<String>> set = new HashSet<Set<String>>();
+
+ Set<String> set1 = new HashSet<String>();
+ set1.add( "Foo" );
+ set1.add( "Bar" );
+ set1.add( null );
+ set1.add( "Rhabarbar" );
+
+ Set<String> set2 = new HashSet<String>();
+ set2.add( null );
+ set2.add( "Rhabarbar" );
+ set2.add( "Foo" );
+ set2.add( "Bar" );
+
+ set.add( set1 );
+ set.add( set2 );
+
+ ComplexGenericTypeSet value = new ComplexGenericTypeSet();
+ value.setSet( set );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ public static class NoGenericTypeSet
+ {
+
+ @Attribute
+ private Set set;
+
+ public Set getSet()
+ {
+ return set;
+ }
+
+ public void setSet( Set set )
+ {
+ this.set = set;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( set == null ) ? 0 : set.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ NoGenericTypeSet other = (NoGenericTypeSet) obj;
+ if ( set == null )
+ {
+ if ( other.set != null )
+ return false;
+ }
+ else if ( !set.equals( other.set ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "NoGenericTypeSet [set=" + set + "]";
+ }
+ }
+
+ public static class SimpleGenericTypeSet
+ {
+
+ @Attribute
+ private Set<String> set;
+
+ public Set<String> getSet()
+ {
+ return set;
+ }
+
+ public void setSet( Set<String> set )
+ {
+ this.set = set;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( set == null ) ? 0 : set.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ SimpleGenericTypeSet other = (SimpleGenericTypeSet) obj;
+ if ( set == null )
+ {
+ if ( other.set != null )
+ return false;
+ }
+ else if ( !set.equals( other.set ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "SimpleGenericTypeSet [set=" + set + "]";
+ }
+ }
+
+ public static class ComplexGenericTypeSet
+ {
+
+ @Attribute
+ private Set<Set<String>> set;
+
+ public Set<Set<String>> getSet()
+ {
+ return set;
+ }
+
+ public void setSet( Set<Set<String>> set )
+ {
+ this.set = set;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( set == null ) ? 0 : set.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ ComplexGenericTypeSet other = (ComplexGenericTypeSet) obj;
+ if ( set == null )
+ {
+ if ( other.set != null )
+ return false;
+ }
+ else if ( !set.equals( other.set ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ComplexGenericTypeSet [set=" + set + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshallerTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshallerTestCase.java
new file mode 100644
index 0000000..e15fd9a
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/marshaller/ShortMarshallerTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.marshaller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.internal.util.DebugLogger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.junit.Test;
+
+public class ShortMarshallerTestCase
+{
+
+ @Test
+ public void testShortPrimitive()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ PrimitiveHolder.class ).attributes();
+ }
+ } ).build();
+
+ PrimitiveHolder value = new PrimitiveHolder();
+ value.setValue1( (short) 0 );
+ value.setValue2( Short.MAX_VALUE );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new PrimitiveHolder();
+ value.setValue1( (short) -10 );
+ value.setValue2( (short) 20 );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ @Test
+ public void testShortWrapper()
+ throws Exception
+ {
+ Serializer serializer =
+ Lightning.newBuilder().logger( new DebugLogger() ).debugCacheDirectory( new File( "target" ) ).serializerDefinitions( new AbstractSerializerDefinition()
+ {
+
+ @Override
+ protected void configure()
+ {
+ serialize(
+ WrapperHolder.class ).attributes();
+ }
+ } ).build();
+
+ WrapperHolder value = new WrapperHolder();
+ value.setValue1( Short.MAX_VALUE );
+ value.setValue2( null );
+ value.setValue3( (short) 34 );
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+ Object result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( (short) 0 );
+ value.setValue2( Short.MIN_VALUE );
+ value.setValue3( null );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+
+ value = new WrapperHolder();
+ value.setValue1( null );
+ value.setValue2( (short) -1 );
+ value.setValue3( Short.MAX_VALUE );
+
+ baos = new ByteArrayOutputStream();
+ serializer.serialize( value, baos );
+
+ bais = new ByteArrayInputStream( baos.toByteArray() );
+ result = serializer.deserialize( bais );
+
+ assertNotNull( result );
+ assertEquals( value, result );
+ }
+
+ public static class PrimitiveHolder
+ {
+
+ @Attribute
+ private short value1;
+
+ @Attribute
+ private short value2;
+
+ public short isValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( short value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public short isValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( short value2 )
+ {
+ this.value2 = value2;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + value1;
+ result = prime * result + value2;
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ PrimitiveHolder other = (PrimitiveHolder) obj;
+ if ( value1 != other.value1 )
+ return false;
+ if ( value2 != other.value2 )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "PrimitiveHolder [value1=" + value1 + ", value2=" + value2 + "]";
+ }
+ }
+
+ public static class WrapperHolder
+ {
+
+ @Attribute
+ private Short value1;
+
+ @Attribute
+ private Short value2;
+
+ @Attribute
+ private Short value3;
+
+ public Short getValue1()
+ {
+ return value1;
+ }
+
+ public void setValue1( Short value1 )
+ {
+ this.value1 = value1;
+ }
+
+ public Short getValue2()
+ {
+ return value2;
+ }
+
+ public void setValue2( Short value2 )
+ {
+ this.value2 = value2;
+ }
+
+ public Short getValue3()
+ {
+ return value3;
+ }
+
+ public void setValue3( Short value3 )
+ {
+ this.value3 = value3;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ( ( value1 == null ) ? 0 : value1.hashCode() );
+ result = prime * result + ( ( value2 == null ) ? 0 : value2.hashCode() );
+ result = prime * result + ( ( value3 == null ) ? 0 : value3.hashCode() );
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ WrapperHolder other = (WrapperHolder) obj;
+ if ( value1 == null )
+ {
+ if ( other.value1 != null )
+ return false;
+ }
+ else if ( !value1.equals( other.value1 ) )
+ return false;
+ if ( value2 == null )
+ {
+ if ( other.value2 != null )
+ return false;
+ }
+ else if ( !value2.equals( other.value2 ) )
+ return false;
+ if ( value3 == null )
+ {
+ if ( other.value3 != null )
+ return false;
+ }
+ else if ( !value3.equals( other.value3 ) )
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "WrapperHolder [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/BeanUtilTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/BeanUtilTestCase.java
new file mode 100644
index 0000000..b755332
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/BeanUtilTestCase.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.directmemory.lightning.internal.util.BeanUtil;
+import org.junit.Test;
+
+public class BeanUtilTestCase
+{
+
+ @Test
+ public void testPropertyNameCreation()
+ throws Exception
+ {
+ String methodName = "isDefined";
+ String result = BeanUtil.buildPropertyName( methodName );
+ assertEquals( "defined", result );
+
+ methodName = "getDefined";
+ result = BeanUtil.buildPropertyName( methodName );
+ assertEquals( "defined", result );
+
+ methodName = "setDefined";
+ result = BeanUtil.buildPropertyName( methodName );
+ assertEquals( "defined", result );
+
+ methodName = "doneDefined";
+ result = BeanUtil.buildPropertyName( methodName );
+ assertEquals( "doneDefined", result );
+ }
+
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/DebugLogger.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/DebugLogger.java
new file mode 100644
index 0000000..16c6e8e
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/DebugLogger.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import java.io.PrintStream;
+
+import org.apache.directmemory.lightning.logging.LogLevel;
+import org.apache.directmemory.lightning.logging.LoggerAdapter;
+
+public class DebugLogger
+ extends LoggerAdapter
+{
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return true;
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ log( LogLevel.Trace, message, null );
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ log( LogLevel.Trace, message, throwable );
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ log( LogLevel.Debug, message, null );
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ log( LogLevel.Debug, message, throwable );
+ }
+
+ @Override
+ public void info( String message )
+ {
+ log( LogLevel.Info, message, null );
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ log( LogLevel.Info, message, throwable );
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ log( LogLevel.Warn, message, null );
+ }
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ log( LogLevel.Warn, message, throwable );
+ }
+
+ @Override
+ public void error( String message )
+ {
+ log( LogLevel.Error, message, null );
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ log( LogLevel.Error, message, throwable );
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ log( LogLevel.Fatal, message, null );
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ log( LogLevel.Fatal, message, throwable );
+ }
+
+ private void log( LogLevel logLevel, String message, Throwable throwable )
+ {
+ PrintStream stream;
+ if ( throwable != null )
+ {
+ stream = System.err;
+ }
+ else
+ {
+ stream = System.out;
+ }
+
+ stream.println( getName() + " - " + logLevel.name() + ": " + message );
+ if ( throwable != null )
+ {
+ throwable.printStackTrace();
+ }
+ }
+}
diff --git a/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/StringUtilTestCase.java b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/StringUtilTestCase.java
new file mode 100644
index 0000000..7cfe90d
--- /dev/null
+++ b/lightning-core/src/test/java/org/apache/directmemory/lightning/internal/util/StringUtilTestCase.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.internal.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.directmemory.lightning.internal.util.StringUtil;
+import org.junit.Test;
+
+public class StringUtilTestCase
+{
+
+ @Test
+ public void testLowerCamelCase()
+ throws Exception
+ {
+ String value = "That is impossible";
+ String result = StringUtil.toLowerCamelCase( value );
+ assertEquals( "thatIsImpossible", result );
+
+ value = "that is impossible";
+ result = StringUtil.toLowerCamelCase( value );
+ assertEquals( "thatIsImpossible", result );
+
+ value = "that is impossible";
+ result = StringUtil.toLowerCamelCase( value );
+ assertEquals( "thatIsImpossible", result );
+
+ value = "that-is impossible";
+ result = StringUtil.toLowerCamelCase( value );
+ assertEquals( "thatIsImpossible", result );
+
+ value = "that_is impossible";
+ result = StringUtil.toLowerCamelCase( value );
+ assertEquals( "thatIsImpossible", result );
+ }
+
+ @Test
+ public void testUpperCamelCase()
+ throws Exception
+ {
+ String value = "That is impossible";
+ String result = StringUtil.toUpperCamelCase( value );
+ assertEquals( "ThatIsImpossible", result );
+
+ value = "that is impossible";
+ result = StringUtil.toUpperCamelCase( value );
+ assertEquals( "ThatIsImpossible", result );
+
+ value = "that is impossible";
+ result = StringUtil.toUpperCamelCase( value );
+ assertEquals( "ThatIsImpossible", result );
+
+ value = "that-is impossible";
+ result = StringUtil.toUpperCamelCase( value );
+ assertEquals( "ThatIsImpossible", result );
+
+ value = "that_is impossible";
+ result = StringUtil.toUpperCamelCase( value );
+ assertEquals( "ThatIsImpossible", result );
+ }
+
+}
diff --git a/lightning-integration/lightning-integration-jgroups/pom.xml b/lightning-integration/lightning-integration-jgroups/pom.xml
new file mode 100644
index 0000000..a35912d
--- /dev/null
+++ b/lightning-integration/lightning-integration-jgroups/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-integration-jgroups</artifactId>
+ <name>Lightning: JGroups Integration</name>
+
+ <parent>
+ <artifactId>lightning-integration</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-api</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jgroups</groupId>
+ <artifactId>jgroups</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningClusterException.java b/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningClusterException.java
new file mode 100644
index 0000000..7b1986a
--- /dev/null
+++ b/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningClusterException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.jgroups;
+
+@SuppressWarnings( "serial" )
+public class LightningClusterException
+ extends RuntimeException
+{
+
+ public LightningClusterException()
+ {
+ super();
+ }
+
+ public LightningClusterException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public LightningClusterException( String message )
+ {
+ super( message );
+ }
+
+ public LightningClusterException( Throwable cause )
+ {
+ super( cause );
+ }
+}
diff --git a/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningJGroupsMembershipListener.java b/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningJGroupsMembershipListener.java
new file mode 100644
index 0000000..aa13605
--- /dev/null
+++ b/lightning-integration/lightning-integration-jgroups/src/main/java/org/apache/directmemory/lightning/jgroups/LightningJGroupsMembershipListener.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.jgroups;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.exceptions.ClassDefinitionInconsistentException;
+import org.apache.directmemory.lightning.metadata.ClassDefinitionContainer;
+import org.jgroups.Address;
+import org.jgroups.JChannel;
+import org.jgroups.MergeView;
+import org.jgroups.Message;
+import org.jgroups.ReceiverAdapter;
+import org.jgroups.View;
+import org.jgroups.util.Util;
+
+public class LightningJGroupsMembershipListener
+ extends ReceiverAdapter
+{
+
+ private final List<Address> lastMembersView = new ArrayList<Address>();
+
+ private final ExecutorService executorService;
+
+ private final Serializer serializer;
+
+ private final JChannel channel;
+
+ public LightningJGroupsMembershipListener( JChannel channel, Serializer serializer, ExecutorService executorService )
+ {
+
+ this.channel = channel;
+ this.serializer = serializer;
+ this.executorService = executorService;
+ }
+
+ @Override
+ public void viewAccepted( View view )
+ {
+ Runnable task;
+ if ( view instanceof MergeView )
+ {
+ task = handleSplitBrainMerge( view );
+ }
+ else
+ {
+ task = handleMemberJoin( view );
+ }
+
+ if ( task != null )
+ {
+ executorService.submit( task );
+ }
+ }
+
+ @Override
+ public void receive( Message msg )
+ {
+ // If we received a ClassDefinitionContainer handle it otherwise just
+ // ignore the message
+ if ( msg.getObject() instanceof ClassDefinitionContainer )
+ {
+ ClassDefinitionContainer container = (ClassDefinitionContainer) msg.getObject();
+ try
+ {
+ serializer.setClassDefinitionContainer( container );
+ }
+ catch ( ClassDefinitionInconsistentException e )
+ {
+ channel.disconnect();
+ throw new LightningClusterException( "Class checksums are not consistent, channel disconnected", e );
+ }
+ }
+ }
+
+ private Runnable handleMemberJoin( View view )
+ {
+ List<Address> members = view.getMembers();
+
+ // Quote from JGroups documentation:
+ // *Note that the first member of a view is the coordinator (the one who
+ // emits new views).*
+ Address coordinator = members.get( 0 );
+
+ if ( channel.getAddress().equals( coordinator ) )
+ {
+ final ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+ final List<Address> receivers = findNewMembers( view );
+
+ try
+ {
+ final byte[] byteBuffer = Util.objectToByteBuffer( container );
+
+ return new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ for ( Address receiver : receivers )
+ {
+ try
+ {
+ channel.send( receiver, byteBuffer );
+ }
+ catch ( Exception e )
+ {
+ throw new LightningClusterException(
+ "Could not send ClassDefinitionContainer to address "
+ + receiver, e );
+ }
+ }
+ }
+ };
+ }
+ catch ( Exception e )
+ {
+ throw new LightningClusterException( "Could not serialize ClassDefinitionContainer", e );
+ }
+ }
+
+ return null;
+ }
+
+ private Runnable handleSplitBrainMerge( View view )
+ {
+ final List<Address> members = new ArrayList<Address>( view.getMembers() );
+
+ // Quote from JGroups documentation:
+ // *Note that the first member of a view is the coordinator (the one who
+ // emits new views).*
+ Address coordinator = members.get( 0 );
+
+ if ( channel.getAddress().equals( coordinator ) )
+ {
+ final ClassDefinitionContainer container = serializer.getClassDefinitionContainer();
+
+ try
+ {
+ final byte[] byteBuffer = Util.objectToByteBuffer( container );
+
+ return new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ for ( int i = 1; i < members.size(); i++ )
+ {
+ Address receiver = members.get( i );
+ if ( receiver == null )
+ {
+ continue;
+ }
+
+ try
+ {
+ channel.send( receiver, byteBuffer );
+ }
+ catch ( Exception e )
+ {
+ throw new LightningClusterException(
+ "Could not send ClassDefinitionContainer to address "
+ + receiver, e );
+ }
+ }
+ }
+ };
+ }
+ catch ( Exception e )
+ {
+ throw new LightningClusterException( "Could not serialize ClassDefinitionContainer", e );
+ }
+ }
+
+ return null;
+ }
+
+ private List<Address> findNewMembers( View view )
+ {
+ List<Address> newMembers = new ArrayList<Address>();
+ for ( Address member : view.getMembers() )
+ {
+ if ( !lastMembersView.contains( member ) )
+ {
+ newMembers.add( member );
+ }
+ }
+ return newMembers;
+ }
+}
diff --git a/lightning-integration/lightning-integration-spring/pom.xml b/lightning-integration/lightning-integration-spring/pom.xml
new file mode 100644
index 0000000..f491763
--- /dev/null
+++ b/lightning-integration/lightning-integration-spring/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-integration-spring</artifactId>
+ <name>Lightning: Spring Integration</name>
+
+ <parent>
+ <artifactId>lightning-integration</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-api</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/LightningFactoryBean.java b/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/LightningFactoryBean.java
new file mode 100644
index 0000000..ad72526
--- /dev/null
+++ b/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/LightningFactoryBean.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.spring;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directmemory.lightning.ClassComparisonStrategy;
+import org.apache.directmemory.lightning.Lightning;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+
+public class LightningFactoryBean
+ implements FactoryBean, InitializingBean
+{
+
+ private Serializer singletonSerializer;
+
+ private boolean prototype = false;
+
+ private List<SerializerDefinition> serializerDefinitions = new ArrayList<SerializerDefinition>();
+
+ private ClassComparisonStrategy classComparisonStrategy = ClassComparisonStrategy.LightningChecksum;
+
+ private Class<? extends Annotation> attributesAnnotation = Attribute.class;
+
+ private SerializationStrategy serializationStrategy = SerializationStrategy.SpeedOptimized;
+
+ private Logger logger = new SpringLoggingAdapter();
+
+ private File debugCacheDirectory = null;
+
+ @Override
+ public Object getObject()
+ throws Exception
+ {
+ if ( isSingleton() )
+ {
+ return singletonSerializer;
+ }
+
+ return Lightning.newBuilder().classComparisonStrategy( classComparisonStrategy ).debugCacheDirectory( debugCacheDirectory ).describesAttributs( attributesAnnotation ).logger( logger ).serializationStrategy( serializationStrategy ).serializerDefinitions( serializerDefinitions ).build();
+ }
+
+ @Override
+ public Class<?> getObjectType()
+ {
+ return Serializer.class;
+ }
+
+ @Override
+ public boolean isSingleton()
+ {
+ return !prototype;
+ }
+
+ @Override
+ public void afterPropertiesSet()
+ throws Exception
+ {
+ if ( isSingleton() )
+ {
+ synchronized ( this )
+ {
+ singletonSerializer =
+ Lightning.newBuilder().classComparisonStrategy( classComparisonStrategy ).debugCacheDirectory( debugCacheDirectory ).describesAttributs( attributesAnnotation ).logger( logger ).serializationStrategy( serializationStrategy ).serializerDefinitions( serializerDefinitions ).build();
+ }
+ }
+ }
+
+ public void setPrototype( boolean prototype )
+ {
+ this.prototype = prototype;
+ }
+
+ public boolean getPrototype()
+ {
+ return prototype;
+ }
+
+ public List<SerializerDefinition> getSerializerDefinitions()
+ {
+ return serializerDefinitions;
+ }
+
+ public void setSerializerDefinitions( List<SerializerDefinition> serializerDefinitions )
+ {
+ this.serializerDefinitions = serializerDefinitions;
+ }
+
+ public ClassComparisonStrategy getClassComparisonStrategy()
+ {
+ return classComparisonStrategy;
+ }
+
+ public void setClassComparisonStrategy( ClassComparisonStrategy classComparisonStrategy )
+ {
+ this.classComparisonStrategy = classComparisonStrategy;
+ }
+
+ public File getDebugCacheDirectory()
+ {
+ return debugCacheDirectory;
+ }
+
+ public void setDebugCacheDirectory( File debugCacheDirectory )
+ {
+ this.debugCacheDirectory = debugCacheDirectory;
+ }
+
+ public Class<? extends Annotation> getAttributesAnnotation()
+ {
+ return attributesAnnotation;
+ }
+
+ public void setAttributesAnnotation( Class<? extends Annotation> attributesAnnotation )
+ {
+ this.attributesAnnotation = attributesAnnotation;
+ }
+
+ public Logger getLogger()
+ {
+ return logger;
+ }
+
+ public void setLogger( Logger logger )
+ {
+ this.logger = logger;
+ }
+
+ public SerializationStrategy getSerializationStrategy()
+ {
+ return serializationStrategy;
+ }
+
+ public void setSerializationStrategy( SerializationStrategy serializationStrategy )
+ {
+ this.serializationStrategy = serializationStrategy;
+ }
+}
diff --git a/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/SpringLoggingAdapter.java b/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/SpringLoggingAdapter.java
new file mode 100644
index 0000000..0c45909
--- /dev/null
+++ b/lightning-integration/lightning-integration-spring/src/main/java/org/apache/directmemory/lightning/spring/SpringLoggingAdapter.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.spring;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.directmemory.lightning.logging.LogLevel;
+import org.apache.directmemory.lightning.logging.Logger;
+
+public class SpringLoggingAdapter
+ implements Logger
+{
+
+ private final Log logger;
+
+ private final String name;
+
+ public SpringLoggingAdapter()
+ {
+ this( SpringLoggingAdapter.class );
+ }
+
+ public SpringLoggingAdapter( Class<?> clazz )
+ {
+ this.logger = LogFactory.getLog( clazz );
+ this.name = clazz.getCanonicalName();
+ }
+
+ public SpringLoggingAdapter( String name )
+ {
+ this.logger = LogFactory.getLog( name );
+ this.name = name;
+ }
+
+ @Override
+ public Logger getChildLogger( Class<?> clazz )
+ {
+ return new SpringLoggingAdapter( clazz );
+ }
+
+ @Override
+ public Logger getChildLogger( String name )
+ {
+ return new SpringLoggingAdapter( name );
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ switch ( logLevel )
+ {
+ case Debug:
+ return isDebugEnabled();
+ case Error:
+ return isErrorEnabled();
+ case Fatal:
+ return isFatalEnabled();
+ case Info:
+ return isInfoEnabled();
+ case Trace:
+ return isTraceEnabled();
+ case Warn:
+ return isWarnEnabled();
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return logger.isTraceEnabled();
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return logger.isDebugEnabled();
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return logger.isInfoEnabled();
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return logger.isWarnEnabled();
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return logger.isErrorEnabled();
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return logger.isFatalEnabled();
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ trace( message, null );
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ logger.trace( message, throwable );
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ debug( message, null );
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ logger.debug( message, throwable );
+ }
+
+ @Override
+ public void info( String message )
+ {
+ info( message, null );
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ logger.info( message, throwable );
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ warn( message, null );
+ }
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ logger.warn( message, throwable );
+ }
+
+ @Override
+ public void error( String message )
+ {
+ error( message, null );
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ logger.error( message, throwable );
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ fatal( message, null );
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ logger.fatal( message, throwable );
+ }
+}
diff --git a/lightning-integration/pom.xml b/lightning-integration/pom.xml
new file mode 100644
index 0000000..8d6e7c1
--- /dev/null
+++ b/lightning-integration/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-integration</artifactId>
+ <packaging>pom</packaging>
+ <name>Lightning: Integration Reactor</name>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <modules>
+ <module>lightning-integration-jgroups</module>
+ <module>lightning-integration-spring</module>
+ </modules>
+</project>
diff --git a/lightning-maven-eclipse-helper-feature/build.properties b/lightning-maven-eclipse-helper-feature/build.properties
new file mode 100644
index 0000000..93b06a6
--- /dev/null
+++ b/lightning-maven-eclipse-helper-feature/build.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+bin.includes = feature.xml,\
+ feature.properties
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper-feature/feature.properties b/lightning-maven-eclipse-helper-feature/feature.properties
new file mode 100644
index 0000000..c28f59e
--- /dev/null
+++ b/lightning-maven-eclipse-helper-feature/feature.properties
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# "featureName" property - name of the feature
+featureName=m2e connector for lightning-maven-eclipse-helper-plugin
+
+# "providerName" property - name of the company that provides the feature
+providerName=Apache Software Foundation
+
+# "updateSiteName" property - label for the update site
+#updateSiteName=The Eclipse Project Updates
+
+# "description" property - description of the feature
+description=m2e connector for lightning-maven-eclipse-helper-plugin
+
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=http://www.apache.org/licenses/LICENSE-2.0.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+\n\
+\n\ Licensed to the Apache Software Foundation (ASF) under one
+\n\ or more contributor license agreements. See the NOTICE file
+\n\ distributed with this work for additional information
+\n\ regarding copyright ownership. The ASF licenses this file
+\n\ to you under the Apache License, Version 2.0 (the
+\n\ "License"); you may not use this file except in compliance
+\n\ with the License. You may obtain a copy of the License at
+\n\
+\n\ http://www.apache.org/licenses/LICENSE-2.0
+\n\
+\n\ Unless required by applicable law or agreed to in writing,
+\n\ software distributed under the License is distributed on an
+\n\ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+\n\ KIND, either express or implied. See the License for the
+\n\ specific language governing permissions and limitations
+\n\ under the License.
+########### end of license property ##########################################
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper-feature/feature.xml b/lightning-maven-eclipse-helper-feature/feature.xml
new file mode 100644
index 0000000..92a1259
--- /dev/null
+++ b/lightning-maven-eclipse-helper-feature/feature.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+-->
+<feature
+ id="lightning-maven-eclipse-helper-feature"
+ label="%featureName"
+ version="0.0.1.qualifier"
+ provider-name="%providerName"
+ plugin="lightning-maven-eclipse-helper">
+
+ <description>%description</description>
+
+ <copyright>%copyright</copyright>
+
+ <license url="%licenseURL">%license</license>
+
+ <plugin
+ id="lightning-maven-eclipse-helper"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+</feature>
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper-feature/pom.xml b/lightning-maven-eclipse-helper-feature/pom.xml
new file mode 100644
index 0000000..efbd33c
--- /dev/null
+++ b/lightning-maven-eclipse-helper-feature/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-maven-eclipse-helper-feature</artifactId>
+ <name>Lightning: Maven Eclipse Helper Feature</name>
+ <packaging>eclipse-feature</packaging>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-maven-plugin</artifactId>
+ <version>0.14.0</version>
+ <extensions>true</extensions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>target-platform-configuration</artifactId>
+ <version>0.14.0</version>
+ <configuration>
+ <resolver>p2</resolver>
+ <ignoreTychoRepositories>true</ignoreTychoRepositories>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>eclipse</id>
+ <url>http://download.eclipse.org/releases/indigo</url>
+ <layout>p2</layout>
+ </pluginRepository>
+ <pluginRepository>
+ <id>m2e</id>
+ <url>http://repository.sonatype.org/content/repositories/forge-sites/m2e/1.1.0/N/LATEST/</url>
+ <layout>p2</layout>
+ </pluginRepository>
+ <pluginRepository>
+ <id>rso</id>
+ <url>http://repository.sonatype.org/content/groups/sonatype-public-grid</url>
+ </pluginRepository>
+ </pluginRepositories>
+ <repositories>
+ <repository>
+ <id>eclipse</id>
+ <url>http://download.eclipse.org/releases/indigo</url>
+ <layout>p2</layout>
+ </repository>
+ <repository>
+ <id>m2e</id>
+ <url>http://repository.sonatype.org/content/repositories/forge-sites/m2e/1.1.0/N/LATEST/</url>
+ <layout>p2</layout>
+ </repository>
+ <repository>
+ <id>rso</id>
+ <url>http://repository.sonatype.org/content/groups/sonatype-public-grid</url>
+ </repository>
+ </repositories>
+</project>
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper/META-INF/MANIFEST.MF b/lightning-maven-eclipse-helper/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..3353eb8
--- /dev/null
+++ b/lightning-maven-eclipse-helper/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: m2e connector for lightning-maven-plugin
+Bundle-SymbolicName: lightning-maven-eclipse-helper;singleton:=true
+Bundle-Version: 0.0.1.qualifier
+Bundle-Vendor: Noctarius
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,
+ JavaSE-1.6
+Require-Bundle: org.eclipse.m2e.jdt;bundle-version="[1.1.0,1.2.0)",
+ org.eclipse.m2e.core;bundle-version="[1.1.0,1.2.0)"
diff --git a/lightning-maven-eclipse-helper/build.properties b/lightning-maven-eclipse-helper/build.properties
new file mode 100644
index 0000000..3fdd888
--- /dev/null
+++ b/lightning-maven-eclipse-helper/build.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+bin.includes = META-INF/,\
+ plugin.xml,\
+ lifecycle-mapping-metadata.xml
+jars.compile.order =
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper/lifecycle-mapping-metadata.xml b/lightning-maven-eclipse-helper/lifecycle-mapping-metadata.xml
new file mode 100644
index 0000000..f7d2160
--- /dev/null
+++ b/lightning-maven-eclipse-helper/lifecycle-mapping-metadata.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <artifactId>lightning-maven-plugin</artifactId>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute>
+ <runOnIncremental>true</runOnIncremental>
+ <runOnConfiguration>true</runOnConfiguration>
+ </execute>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+</lifecycleMappingMetadata>
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper/plugin.xml b/lightning-maven-eclipse-helper/plugin.xml
new file mode 100644
index 0000000..5550f5c
--- /dev/null
+++ b/lightning-maven-eclipse-helper/plugin.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+-->
+<plugin>
+ <extension
+ point="org.eclipse.m2e.core.lifecycleMappingMetadataSource">
+ </extension>
+</plugin>
\ No newline at end of file
diff --git a/lightning-maven-eclipse-helper/pom.xml b/lightning-maven-eclipse-helper/pom.xml
new file mode 100644
index 0000000..5312ed7
--- /dev/null
+++ b/lightning-maven-eclipse-helper/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-maven-eclipse-helper</artifactId>
+ <name>Lightning: Maven Eclipse Helper</name>
+ <packaging>eclipse-plugin</packaging>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-maven-plugin</artifactId>
+ <version>0.14.0</version>
+ <extensions>true</extensions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>target-platform-configuration</artifactId>
+ <version>0.14.0</version>
+ <configuration>
+ <resolver>p2</resolver>
+ <ignoreTychoRepositories>true</ignoreTychoRepositories>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>eclipse</id>
+ <url>http://download.eclipse.org/releases/indigo</url>
+ <layout>p2</layout>
+ </pluginRepository>
+ <pluginRepository>
+ <id>m2e</id>
+ <url>http://repository.sonatype.org/content/repositories/forge-sites/m2e/1.1.0/N/LATEST/</url>
+ <layout>p2</layout>
+ </pluginRepository>
+ <pluginRepository>
+ <id>rso</id>
+ <url>http://repository.sonatype.org/content/groups/sonatype-public-grid</url>
+ </pluginRepository>
+ </pluginRepositories>
+ <repositories>
+ <repository>
+ <id>eclipse</id>
+ <url>http://download.eclipse.org/releases/indigo</url>
+ <layout>p2</layout>
+ </repository>
+ <repository>
+ <id>m2e</id>
+ <url>http://repository.sonatype.org/content/repositories/forge-sites/m2e/1.1.0/N/LATEST/</url>
+ <layout>p2</layout>
+ </repository>
+ <repository>
+ <id>rso</id>
+ <url>http://repository.sonatype.org/content/groups/sonatype-public-grid</url>
+ </repository>
+ </repositories>
+</project>
\ No newline at end of file
diff --git a/lightning-maven-integration-test/pom.xml b/lightning-maven-integration-test/pom.xml
new file mode 100644
index 0000000..e2ad728
--- /dev/null
+++ b/lightning-maven-integration-test/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-maven-integration-test</artifactId>
+ <name>Lightning: Maven Integration Test</name>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-api</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <artifactId>lightning-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <phase>process-classes</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/Foo.java b/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/Foo.java
new file mode 100644
index 0000000..20ef0d5
--- /dev/null
+++ b/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/Foo.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven.integration;
+
+import org.apache.directmemory.lightning.metadata.Attribute;
+
+public class Foo
+{
+
+ @Attribute
+ private String foo;
+
+ @Attribute
+ private int bar;
+
+ public String getFoo()
+ {
+ return foo;
+ }
+
+ public void setFoo( String foo )
+ {
+ this.foo = foo;
+ }
+
+ public int getBar()
+ {
+ return bar;
+ }
+
+ public void setBar( int bar )
+ {
+ this.bar = bar;
+ }
+}
diff --git a/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/FooSerializerDefinition.java b/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/FooSerializerDefinition.java
new file mode 100644
index 0000000..3d48946
--- /dev/null
+++ b/lightning-maven-integration-test/src/main/java/org/apache/directmemory/lightning/maven/integration/FooSerializerDefinition.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven.integration;
+
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+
+public class FooSerializerDefinition
+ extends AbstractSerializerDefinition
+{
+
+ @Override
+ protected void configure()
+ {
+ serialize( Foo.class ).attributes();
+ }
+}
diff --git a/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/MavenGeneratorTestCase.java b/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/MavenGeneratorTestCase.java
new file mode 100644
index 0000000..22fe2e9
--- /dev/null
+++ b/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/MavenGeneratorTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven.integration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.charset.Charset;
+
+import org.junit.Test;
+
+public class MavenGeneratorTestCase
+{
+
+ @Test
+ public void testGeneration()
+ throws Exception
+ {
+ File target = new File( "target/classes" );
+ assertTrue( recursiveSearchClassFile( "FooLightningGeneratedMarshaller.class", target ) );
+
+ File testfile = new File( getClass().getClassLoader().getResource( "generated.java.out" ).toURI() );
+ File generatedFile =
+ new File(
+ "target/generated-sources/lightning/org/apache/directmemory/lightning/maven/integration/FooLightningGeneratedMarshaller.java" );
+ String expected = SupportUtil.readAllText( testfile, Charset.forName( "UTF-8" ) );
+ String result = SupportUtil.readAllText( generatedFile, Charset.forName( "UTF-8" ) );
+ assertEquals( expected, result );
+ }
+
+ private boolean recursiveSearchClassFile( String classFile, File path )
+ {
+ if ( path.isFile() && path.getName().equals( classFile ) )
+ {
+ return true;
+ }
+
+ if ( path.isDirectory() )
+ {
+ for ( File childPath : path.listFiles() )
+ {
+ if ( recursiveSearchClassFile( classFile, childPath ) )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/SupportUtil.java b/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/SupportUtil.java
new file mode 100644
index 0000000..4b97d52
--- /dev/null
+++ b/lightning-maven-integration-test/src/test/java/org/apache/directmemory/lightning/maven/integration/SupportUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven.integration;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class SupportUtil
+{
+
+ private SupportUtil()
+ {
+ }
+
+ public static List<File> recursiveGetAllJavaSources( File file, ArrayList<File> list, FileFilter fileFilter )
+ {
+ if ( file.isDirectory() )
+ {
+ for ( File f : file.listFiles( fileFilter ) )
+ {
+ recursiveGetAllJavaSources( f, list, fileFilter );
+ }
+ }
+ else
+ {
+ list.add( file );
+ }
+ return list;
+ }
+
+ public static String readAllText( File file, Charset charset )
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ LineNumberReader reader = new LineNumberReader( new FileReader( file ) );
+ String line = null;
+ while ( ( line = reader.readLine() ) != null )
+ {
+ sb.append( line );
+ }
+ return sb.toString();
+ }
+ catch ( IOException e )
+ {
+ return null;
+ }
+ }
+}
diff --git a/lightning-maven-integration-test/src/test/resources/generated.java.out b/lightning-maven-integration-test/src/test/resources/generated.java.out
new file mode 100644
index 0000000..47a9847
--- /dev/null
+++ b/lightning-maven-integration-test/src/test/resources/generated.java.out
@@ -0,0 +1,91 @@
+
+package org.apache.directmemory.lightning.maven.integration;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.internal.generator.AbstractGeneratedMarshaller;
+import org.apache.directmemory.lightning.metadata.ValuePropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public final class FooLightningGeneratedMarshaller extends AbstractGeneratedMarshaller {
+
+ private final PropertyDescriptor DESCRIPTOR_BAR_LIGHTNING;
+ private final Marshaller MARSHALLER_BAR_LIGHTNING;
+ private final ValuePropertyAccessor ACCESSOR_BAR_LIGHTNING;
+ private final PropertyDescriptor DESCRIPTOR_FOO_LIGHTNING;
+ private final Marshaller MARSHALLER_FOO_LIGHTNING;
+ private final ValuePropertyAccessor ACCESSOR_FOO_LIGHTNING;
+
+ public FooLightningGeneratedMarshaller (Class<?> marshalledType, Map<Class<?>, Marshaller> marshallers,
+ ClassDescriptorAwareSerializer serializer, ObjectInstantiatorFactory objectInstantiatorFactory,
+ List<PropertyDescriptor> propertyDescriptors) {
+
+ super(marshalledType, marshallers, serializer, objectInstantiatorFactory);
+ DESCRIPTOR_BAR_LIGHTNING = propertyDescriptors.get(0);
+
+ PropertyDescriptor bar = findPropertyDescriptor("bar", propertyDescriptors);
+ Marshaller barMarshaller = bar.getMarshaller();
+ if (barMarshaller == null) {
+ barMarshaller = findMarshaller(bar);
+ }
+ MARSHALLER_BAR_LIGHTNING = barMarshaller;
+
+ ACCESSOR_BAR_LIGHTNING = (ValuePropertyAccessor) getPropertyAccessor("bar");
+ DESCRIPTOR_FOO_LIGHTNING = propertyDescriptors.get(1);
+
+ PropertyDescriptor foo = findPropertyDescriptor("foo", propertyDescriptors);
+ Marshaller fooMarshaller = foo.getMarshaller();
+ if (fooMarshaller == null) {
+ fooMarshaller = findMarshaller(foo);
+ }
+ MARSHALLER_FOO_LIGHTNING = fooMarshaller;
+
+ ACCESSOR_FOO_LIGHTNING = (ValuePropertyAccessor) getPropertyAccessor("foo");
+ }
+
+ public void marshall(Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput, SerializationContext serializationContext) throws IOException {
+ if (isAlreadyMarshalled(value, propertyDescriptor.getType(), dataOutput, serializationContext)) {
+ return;
+ }
+
+ ValuePropertyAccessor barPropertyAccessor = this.ACCESSOR_BAR_LIGHTNING;
+ PropertyDescriptor barPropertyDescriptor = this.DESCRIPTOR_BAR_LIGHTNING;
+ this.MARSHALLER_BAR_LIGHTNING.marshall(Integer.valueOf(barPropertyAccessor.readInt(value)), barPropertyDescriptor, dataOutput, serializationContext);
+
+ ValuePropertyAccessor fooPropertyAccessor = this.ACCESSOR_FOO_LIGHTNING;
+ PropertyDescriptor fooPropertyDescriptor = this.DESCRIPTOR_FOO_LIGHTNING;
+ this.MARSHALLER_FOO_LIGHTNING.marshall(fooPropertyAccessor.readObject(value), fooPropertyDescriptor, dataOutput, serializationContext);
+
+ }
+
+ public <V> V unmarshall(V instance, PropertyDescriptor propertyDescriptor, DataInput dataInput, SerializationContext serializationContext) throws IOException {
+ ValuePropertyAccessor barPropertyAccessor = this.ACCESSOR_BAR_LIGHTNING;
+ PropertyDescriptor barPropertyDescriptor = this.DESCRIPTOR_BAR_LIGHTNING;
+ Object barValue = this.MARSHALLER_BAR_LIGHTNING.unmarshall(barPropertyDescriptor, dataInput, serializationContext);
+ barPropertyAccessor.writeInt(instance, ((Integer) barValue).intValue());
+
+ ValuePropertyAccessor fooPropertyAccessor = this.ACCESSOR_FOO_LIGHTNING;
+ PropertyDescriptor fooPropertyDescriptor = this.DESCRIPTOR_FOO_LIGHTNING;
+ Object fooValue = this.MARSHALLER_FOO_LIGHTNING.unmarshall(fooPropertyDescriptor, dataInput, serializationContext);
+ fooPropertyAccessor.writeObject(instance, fooValue);
+
+ return instance;
+ }
+
+ private PropertyDescriptor findPropertyDescriptor(String propertyName, List<PropertyDescriptor> propertyDescriptors) {
+ for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+ if (propertyDescriptor.getPropertyName().equals(propertyName)) {
+ return propertyDescriptor;
+ }
+ }
+ return null;
+ }
+}
diff --git a/lightning-maven-plugin/pom.xml b/lightning-maven-plugin/pom.xml
new file mode 100644
index 0000000..c8615a6
--- /dev/null
+++ b/lightning-maven-plugin/pom.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>lightning-maven-plugin</artifactId>
+ <name>Lightning: Maven Plugin</name>
+ <packaging>maven-plugin</packaging>
+
+ <parent>
+ <artifactId>lightning-reactor</artifactId>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-api</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lightning-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-api</artifactId>
+ <version>1.8.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-manager</artifactId>
+ <version>1.8.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-javac</artifactId>
+ <version>1.8.1</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.plugin-testing</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
\ No newline at end of file
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/AbstractCompilerMojo.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/AbstractCompilerMojo.java
new file mode 100644
index 0000000..e2502cb
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/AbstractCompilerMojo.java
@@ -0,0 +1,786 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.toolchain.Toolchain;
+import org.apache.maven.toolchain.ToolchainManager;
+import org.codehaus.plexus.compiler.Compiler;
+import org.codehaus.plexus.compiler.CompilerConfiguration;
+import org.codehaus.plexus.compiler.CompilerError;
+import org.codehaus.plexus.compiler.CompilerException;
+import org.codehaus.plexus.compiler.CompilerOutputStyle;
+import org.codehaus.plexus.compiler.manager.CompilerManager;
+import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
+import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
+import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
+import org.codehaus.plexus.compiler.util.scan.mapping.SingleTargetSourceMapping;
+import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
+import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * TODO: At least one step could be optimized, currently the plugin will do two scans of all the source code if the
+ * compiler has to have the entire set of sources. This is currently the case for at least the C# compiler and most
+ * likely all the other .NET compilers too.
+ *
+ * @author others
+ * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
+ * @version $Id$
+ * @since 2.0
+ */
+public abstract class AbstractCompilerMojo
+ extends AbstractMojo
+{
+
+ // ----------------------------------------------------------------------
+ // Configurables
+ // ----------------------------------------------------------------------
+
+ /**
+ * Indicates whether the build will continue even if there are compilation errors; defaults to true.
+ *
+ * @parameter expression="${maven.compiler.failOnError}" default-value="true"
+ * @since 2.0.2
+ */
+ private boolean failOnError = true;
+
+ /**
+ * Set to true to include debugging information in the compiled class files.
+ *
+ * @parameter expression="${maven.compiler.debug}" default-value="true"
+ */
+ private boolean debug = true;
+
+ /**
+ * Set to true to show messages about what the compiler is doing.
+ *
+ * @parameter expression="${maven.compiler.verbose}" default-value="false"
+ */
+ private boolean verbose;
+
+ /**
+ * Sets whether to show source locations where deprecated APIs are used.
+ *
+ * @parameter expression="${maven.compiler.showDeprecation}" default-value="false"
+ */
+ private boolean showDeprecation;
+
+ /**
+ * Set to true to optimize the compiled code using the compiler's optimization methods.
+ *
+ * @parameter expression="${maven.compiler.optimize}" default-value="false"
+ */
+ private boolean optimize;
+
+ /**
+ * Set to true to show compilation warnings.
+ *
+ * @parameter expression="${maven.compiler.showWarnings}" default-value="false"
+ */
+ private boolean showWarnings;
+
+ /**
+ * The -source argument for the Java compiler.
+ *
+ * @parameter expression="${maven.compiler.source}" default-value="1.5"
+ */
+ protected String source;
+
+ /**
+ * The -target argument for the Java compiler.
+ *
+ * @parameter expression="${maven.compiler.target}" default-value="1.5"
+ */
+ protected String target;
+
+ /**
+ * The -encoding argument for the Java compiler.
+ *
+ * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
+ */
+ protected String encoding;
+
+ /**
+ * Sets the granularity in milliseconds of the last modification date for testing whether a source needs
+ * recompilation.
+ *
+ * @parameter expression="${lastModGranularityMs}" default-value="0"
+ */
+ private int staleMillis;
+
+ /**
+ * The compiler id of the compiler to use. See this <a href="non-javac-compilers.html">guide</a> for more
+ * information.
+ *
+ * @parameter expression="${maven.compiler.compilerId}" default-value="javac"
+ */
+ private String compilerId;
+
+ /**
+ * Version of the compiler to use, ex. "1.3", "1.5", if fork is set to true.
+ *
+ * @parameter expression="${maven.compiler.compilerVersion}"
+ */
+ private String compilerVersion;
+
+ /**
+ * Allows running the compiler in a separate process. If "false" it uses the built in compiler, while if "true" it
+ * will use an executable.
+ *
+ * @parameter expression="${maven.compiler.fork}" default-value="false"
+ */
+ private boolean fork;
+
+ /**
+ * Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m" if fork is set to true.
+ *
+ * @parameter expression="${maven.compiler.meminitial}"
+ * @since 2.0.1
+ */
+ private String meminitial;
+
+ /**
+ * Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m" if fork is set to true.
+ *
+ * @parameter expression="${maven.compiler.maxmem}"
+ * @since 2.0.1
+ */
+ private String maxmem;
+
+ /**
+ * Sets the executable of the compiler to use when fork is true.
+ *
+ * @parameter expression="${maven.compiler.executable}"
+ */
+ private String executable;
+
+ /**
+ * <p>
+ * Sets whether annotation processing is performed or not. Only applies to JDK 1.6+ If not set, both compilation and
+ * annotation processing are performed at the same time.
+ * </p>
+ * <p>
+ * Allowed values are: none - no annotation processing is performed. only - only annotation processing is done, no
+ * compilation.
+ * </p>
+ *
+ * @parameter
+ * @since 2.2
+ */
+ private String proc;
+
+ /**
+ * <p>
+ * Names of annotation processors to run. Only applies to JDK 1.6+ If not set, the default annotation processors
+ * discovery process applies.
+ * </p>
+ *
+ * @parameter
+ * @since 2.2
+ */
+ private String[] annotationProcessors;
+
+ /**
+ * <p>
+ * Sets the arguments to be passed to the compiler (prepending a dash) if fork is set to true.
+ * </p>
+ * <p>
+ * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
+ * </p>
+ *
+ * @parameter
+ * @since 2.0.1
+ */
+ protected Map<String, String> compilerArguments;
+
+ /**
+ * <p>
+ * Sets the unformatted argument string to be passed to the compiler if fork is set to true.
+ * </p>
+ * <p>
+ * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
+ * </p>
+ *
+ * @parameter
+ */
+ protected String compilerArgument;
+
+ /**
+ * Sets the name of the output file when compiling a set of sources to a single file.
+ *
+ * @parameter expression="${project.build.finalName}"
+ */
+ private String outputFileName;
+
+ /**
+ * Keyword list to be appended to the -g command-line switch. Legal values are none or a comma-separated list of the
+ * following keywords: lines, vars, and source. If debuglevel is not specified, by default, nothing will be appended
+ * to -g. If debug is not turned on, this attribute will be ignored.
+ *
+ * @parameter expression="${maven.compiler.debuglevel}"
+ * @since 2.1
+ */
+ private String debuglevel;
+
+ /** @component */
+ private ToolchainManager toolchainManager;
+
+ // ----------------------------------------------------------------------
+ // Read-only parameters
+ // ----------------------------------------------------------------------
+
+ /**
+ * The directory to run the compiler from if fork is true.
+ *
+ * @parameter default-value="${basedir}"
+ * @required
+ * @readonly
+ */
+ private File basedir;
+
+ /**
+ * The target directory of the compiler if fork is true.
+ *
+ * @parameter default-value="${project.build.directory}"
+ * @required
+ * @readonly
+ */
+ private File buildDirectory;
+
+ /**
+ * Plexus compiler manager.
+ *
+ * @component
+ */
+ private CompilerManager compilerManager;
+
+ /**
+ * The current build session instance. This is used for toolchain manager API calls.
+ *
+ * @parameter default-value="${session}"
+ * @required
+ * @readonly
+ */
+ private MavenSession session;
+
+ protected abstract SourceInclusionScanner getSourceInclusionScanner( int staleMillis );
+
+ protected abstract SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding );
+
+ protected abstract List<String> getClasspathElements();
+
+ protected abstract List<String> getCompileSourceRoots();
+
+ protected abstract File getOutputDirectory();
+
+ protected abstract String getSource();
+
+ protected abstract String getTarget();
+
+ protected abstract String getCompilerArgument();
+
+ protected abstract Map<String, String> getCompilerArguments();
+
+ protected abstract File getGeneratedSourcesDirectory();
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public void execute()
+ throws MojoExecutionException, CompilationFailureException
+ {
+ // ----------------------------------------------------------------------
+ // Look up the compiler. This is done before other code than can
+ // cause the mojo to return before the lookup is done possibly resulting
+ // in misconfigured POMs still building.
+ // ----------------------------------------------------------------------
+
+ Compiler compiler;
+
+ getLog().debug( "Using compiler '" + compilerId + "'." );
+
+ try
+ {
+ compiler = compilerManager.getCompiler( compilerId );
+ }
+ catch ( NoSuchCompilerException e )
+ {
+ throw new MojoExecutionException( "No such compiler '" + e.getCompilerId() + "'." );
+ }
+
+ // -----------toolchains start here ----------------------------------
+ // use the compilerId as identifier for toolchains as well.
+ Toolchain tc = getToolchain();
+ if ( tc != null )
+ {
+ getLog().info( "Toolchain in compiler-plugin: " + tc );
+ if ( executable != null )
+ {
+ getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + executable );
+ }
+ else
+ {
+ fork = true;
+ // TODO somehow shaky dependency between compilerId and tool
+ // executable.
+ executable = tc.findTool( compilerId );
+ }
+ }
+ // ----------------------------------------------------------------------
+ //
+ // ----------------------------------------------------------------------
+
+ List<String> compileSourceRoots = removeEmptyCompileSourceRoots( getCompileSourceRoots() );
+
+ if ( compileSourceRoots.isEmpty() )
+ {
+ getLog().info( "No sources to compile" );
+
+ return;
+ }
+
+ if ( getLog().isDebugEnabled() )
+ {
+ getLog().debug( "Source directories: " + compileSourceRoots.toString().replace( ',', '\n' ) );
+ getLog().debug( "Classpath: " + getClasspathElements().toString().replace( ',', '\n' ) );
+ getLog().debug( "Output directory: " + getOutputDirectory() );
+ }
+
+ // ----------------------------------------------------------------------
+ // Create the compiler configuration
+ // ----------------------------------------------------------------------
+
+ CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
+
+ compilerConfiguration.setOutputLocation( getOutputDirectory().getAbsolutePath() );
+
+ compilerConfiguration.setClasspathEntries( getClasspathElements() );
+
+ compilerConfiguration.setSourceLocations( compileSourceRoots );
+
+ compilerConfiguration.setOptimize( optimize );
+
+ compilerConfiguration.setDebug( debug );
+
+ if ( debug && StringUtils.isNotEmpty( debuglevel ) )
+ {
+ String[] split = StringUtils.split( debuglevel, "," );
+ for ( int i = 0; i < split.length; i++ )
+ {
+ if ( !( split[i].equalsIgnoreCase( "none" ) || split[i].equalsIgnoreCase( "lines" )
+ || split[i].equalsIgnoreCase( "vars" ) || split[i].equalsIgnoreCase( "source" ) ) )
+ {
+ throw new IllegalArgumentException( "The specified debug level: '" + split[i]
+ + "' is unsupported. " + "Legal values are 'none', 'lines', 'vars', and 'source'." );
+ }
+ }
+ compilerConfiguration.setDebugLevel( debuglevel );
+ }
+
+ compilerConfiguration.setVerbose( verbose );
+
+ compilerConfiguration.setShowWarnings( showWarnings );
+
+ compilerConfiguration.setShowDeprecation( showDeprecation );
+
+ compilerConfiguration.setSourceVersion( getSource() );
+
+ compilerConfiguration.setTargetVersion( getTarget() );
+
+ compilerConfiguration.setProc( proc );
+
+ compilerConfiguration.setGeneratedSourcesDirectory( getGeneratedSourcesDirectory() );
+
+ compilerConfiguration.setAnnotationProcessors( annotationProcessors );
+
+ compilerConfiguration.setSourceEncoding( encoding );
+
+ Map<String, String> effectiveCompilerArguments = getCompilerArguments();
+
+ String effectiveCompilerArgument = getCompilerArgument();
+
+ if ( ( effectiveCompilerArguments != null ) || ( effectiveCompilerArgument != null ) )
+ {
+ LinkedHashMap<String, String> cplrArgsCopy = new LinkedHashMap<String, String>();
+ if ( effectiveCompilerArguments != null )
+ {
+ for ( Map.Entry<String, String> me : effectiveCompilerArguments.entrySet() )
+ {
+ String key = me.getKey();
+ String value = me.getValue();
+ if ( !key.startsWith( "-" ) )
+ {
+ key = "-" + key;
+ }
+ cplrArgsCopy.put( key, value );
+ }
+ }
+ if ( !StringUtils.isEmpty( effectiveCompilerArgument ) )
+ {
+ cplrArgsCopy.put( effectiveCompilerArgument, null );
+ }
+ compilerConfiguration.setCustomCompilerArguments( cplrArgsCopy );
+ }
+
+ compilerConfiguration.setFork( fork );
+
+ if ( fork )
+ {
+ if ( !StringUtils.isEmpty( meminitial ) )
+ {
+ String value = getMemoryValue( meminitial );
+
+ if ( value != null )
+ {
+ compilerConfiguration.setMeminitial( value );
+ }
+ else
+ {
+ getLog().info( "Invalid value for meminitial '" + meminitial + "'. Ignoring this option." );
+ }
+ }
+
+ if ( !StringUtils.isEmpty( maxmem ) )
+ {
+ String value = getMemoryValue( maxmem );
+
+ if ( value != null )
+ {
+ compilerConfiguration.setMaxmem( value );
+ }
+ else
+ {
+ getLog().info( "Invalid value for maxmem '" + maxmem + "'. Ignoring this option." );
+ }
+ }
+ }
+
+ compilerConfiguration.setExecutable( executable );
+
+ compilerConfiguration.setWorkingDirectory( basedir );
+
+ compilerConfiguration.setCompilerVersion( compilerVersion );
+
+ compilerConfiguration.setBuildDirectory( buildDirectory );
+
+ compilerConfiguration.setOutputFileName( outputFileName );
+
+ // TODO: have an option to always compile (without need to clean)
+ Set<File> staleSources;
+
+ boolean canUpdateTarget;
+
+ try
+ {
+ staleSources =
+ computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
+
+ canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
+
+ if ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
+ && !canUpdateTarget )
+ {
+ getLog().info( "RESCANNING!" );
+ // TODO: This second scan for source files is sub-optimal
+ String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
+
+ Set<File> sources =
+ computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( inputFileEnding ) );
+
+ compilerConfiguration.setSourceFiles( sources );
+ }
+ else
+ {
+ compilerConfiguration.setSourceFiles( staleSources );
+ }
+ }
+ catch ( CompilerException e )
+ {
+ throw new MojoExecutionException( "Error while computing stale sources.", e );
+ }
+
+ if ( staleSources.isEmpty() )
+ {
+ getLog().info( "Nothing to compile - all classes are up to date" );
+
+ return;
+ }
+
+ // ----------------------------------------------------------------------
+ // Dump configuration
+ // ----------------------------------------------------------------------
+
+ if ( getLog().isDebugEnabled() )
+ {
+ getLog().debug( "Classpath:" );
+
+ for ( String s : getClasspathElements() )
+ {
+ getLog().debug( " " + s );
+ }
+
+ getLog().debug( "Source roots:" );
+
+ for ( String root : getCompileSourceRoots() )
+ {
+ getLog().debug( " " + root );
+ }
+
+ try
+ {
+ if ( fork )
+ {
+ if ( compilerConfiguration.getExecutable() != null )
+ {
+ getLog().debug( "Excutable: " );
+ getLog().debug( " " + compilerConfiguration.getExecutable() );
+ }
+ }
+
+ String[] cl = compiler.createCommandLine( compilerConfiguration );
+ if ( cl != null && cl.length > 0 )
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append( cl[0] );
+ for ( int i = 1; i < cl.length; i++ )
+ {
+ sb.append( " " );
+ sb.append( cl[i] );
+ }
+ getLog().debug( "Command line options:" );
+ getLog().debug( sb );
+ }
+ }
+ catch ( CompilerException ce )
+ {
+ getLog().debug( ce );
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ // Compile!
+ // ----------------------------------------------------------------------
+
+ if ( StringUtils.isEmpty( compilerConfiguration.getSourceEncoding() ) )
+ {
+ getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
+ + ", i.e. build is platform dependent!" );
+ }
+
+ List<CompilerError> messages;
+
+ try
+ {
+ messages = compiler.compile( compilerConfiguration );
+ }
+ catch ( Exception e )
+ {
+ // TODO: don't catch Exception
+ throw new MojoExecutionException( "Fatal error compiling", e );
+ }
+
+ List<CompilerError> warnings = new ArrayList<CompilerError>();
+ List<CompilerError> errors = new ArrayList<CompilerError>();
+ if ( messages != null )
+ {
+ for ( CompilerError message : messages )
+ {
+ if ( message.isError() )
+ {
+ errors.add( message );
+ }
+ else
+ {
+ warnings.add( message );
+ }
+ }
+ }
+
+ if ( failOnError && !errors.isEmpty() )
+ {
+ if ( !warnings.isEmpty() )
+ {
+ getLog().info( "-------------------------------------------------------------" );
+ getLog().warn( "COMPILATION WARNING : " );
+ getLog().info( "-------------------------------------------------------------" );
+ for ( CompilerError warning : warnings )
+ {
+ getLog().warn( warning.toString() );
+ }
+ getLog().info( warnings.size() + ( ( warnings.size() > 1 ) ? " warnings " : " warning" ) );
+ getLog().info( "-------------------------------------------------------------" );
+ }
+
+ getLog().info( "-------------------------------------------------------------" );
+ getLog().error( "COMPILATION ERROR : " );
+ getLog().info( "-------------------------------------------------------------" );
+
+ for ( CompilerError error : errors )
+ {
+ getLog().error( error.toString() );
+ }
+ getLog().info( errors.size() + ( ( errors.size() > 1 ) ? " errors " : " error" ) );
+ getLog().info( "-------------------------------------------------------------" );
+
+ throw new CompilationFailureException( errors );
+ }
+ else
+ {
+ for ( CompilerError message : messages )
+ {
+ getLog().warn( message.toString() );
+ }
+ }
+ }
+
+ private String getMemoryValue( String setting )
+ {
+ String value = null;
+
+ // Allow '128' or '128m'
+ if ( isDigits( setting ) )
+ {
+ value = setting + "m";
+ }
+ else
+ {
+ if ( ( isDigits( setting.substring( 0, setting.length() - 1 ) ) )
+ && ( setting.toLowerCase().endsWith( "m" ) ) )
+ {
+ value = setting;
+ }
+ }
+ return value;
+ }
+
+ // TODO remove the part with ToolchainManager lookup once we depend on
+ // 3.0.9 (have it as prerequisite). Define as regular component field then.
+ private Toolchain getToolchain()
+ {
+ Toolchain tc = null;
+ if ( toolchainManager != null )
+ {
+ tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
+ }
+ return tc;
+ }
+
+ private boolean isDigits( String string )
+ {
+ for ( int i = 0; i < string.length(); i++ )
+ {
+ if ( !Character.isDigit( string.charAt( i ) ) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private Set<File> computeStaleSources( CompilerConfiguration compilerConfiguration, Compiler compiler,
+ SourceInclusionScanner scanner )
+ throws MojoExecutionException, CompilerException
+ {
+ CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
+
+ SourceMapping mapping;
+
+ File outputDirectory;
+
+ if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE )
+ {
+ mapping =
+ new SuffixMapping( compiler.getInputFileEnding( compilerConfiguration ),
+ compiler.getOutputFileEnding( compilerConfiguration ) );
+
+ outputDirectory = getOutputDirectory();
+ }
+ else if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
+ {
+ mapping =
+ new SingleTargetSourceMapping( compiler.getInputFileEnding( compilerConfiguration ),
+ compiler.getOutputFile( compilerConfiguration ) );
+
+ outputDirectory = buildDirectory;
+ }
+ else
+ {
+ throw new MojoExecutionException( "Unknown compiler output style: '" + outputStyle + "'." );
+ }
+
+ scanner.addSourceMapping( mapping );
+
+ Set<File> staleSources = new HashSet<File>();
+
+ for ( String sourceRoot : getCompileSourceRoots() )
+ {
+ File rootFile = new File( sourceRoot );
+
+ if ( !rootFile.isDirectory() )
+ {
+ continue;
+ }
+
+ try
+ {
+ staleSources.addAll( scanner.getIncludedSources( rootFile, outputDirectory ) );
+ }
+ catch ( InclusionScanException e )
+ {
+ throw new MojoExecutionException( "Error scanning source root: \'" + sourceRoot + "\' "
+ + "for stale files to recompile.", e );
+ }
+ }
+
+ return staleSources;
+ }
+
+ /**
+ * @todo also in ant plugin. This should be resolved at some point so that it does not need to be calculated
+ * continuously - or should the plugins accept empty source roots as is?
+ */
+ private static List<String> removeEmptyCompileSourceRoots( List<String> compileSourceRootsList )
+ {
+ List<String> newCompileSourceRootsList = new ArrayList<String>();
+ if ( compileSourceRootsList != null )
+ {
+ // copy as I may be modifying it
+ for ( String srcDir : compileSourceRootsList )
+ {
+ if ( !newCompileSourceRootsList.contains( srcDir ) && new File( srcDir ).exists() )
+ {
+ newCompileSourceRootsList.add( srcDir );
+ }
+ }
+ }
+ return newCompileSourceRootsList;
+ }
+}
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/CompilationFailureException.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/CompilationFailureException.java
new file mode 100644
index 0000000..5e08b7c
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/CompilationFailureException.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import org.apache.maven.plugin.MojoFailureException;
+import org.codehaus.plexus.compiler.CompilerError;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @version $Id$
+ * @since 2.0
+ */
+@SuppressWarnings( "serial" )
+public class CompilationFailureException
+ extends MojoFailureException
+{
+
+ private static final String LS = System.getProperty( "line.separator" );
+
+ public CompilationFailureException( List<CompilerError> messages )
+ {
+ super( null, shortMessage( messages ), longMessage( messages ) );
+ }
+
+ public static String longMessage( List<CompilerError> messages )
+ {
+ StringBuffer sb = new StringBuffer();
+
+ if ( messages != null )
+ {
+ for ( CompilerError compilerError : messages )
+ {
+ sb.append( compilerError ).append( LS );
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Short message will have the error message if there's only one, useful for errors forking the compiler
+ *
+ * @param messages
+ * @return the short error message
+ * @since 2.0.2
+ */
+ public static String shortMessage( List<CompilerError> messages )
+ {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append( "Compilation failure" );
+
+ if ( messages.size() == 1 )
+ {
+ sb.append( LS );
+
+ CompilerError compilerError = messages.get( 0 );
+
+ sb.append( compilerError ).append( LS );
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/LightningGeneratorMojo.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/LightningGeneratorMojo.java
new file mode 100644
index 0000000..cb24af4
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/LightningGeneratorMojo.java
@@ -0,0 +1,437 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.tools.SimpleJavaFileObject;
+
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.Serializer;
+import org.apache.directmemory.lightning.base.AbstractSerializerDefinition;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.logging.LogLevel;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
+import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
+import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
+
+/**
+ * Generates sourcecode of native marshallers for Lightning {@link Serializer} by exploring all source
+ * {@link SerializerDefinition} files.
+ *
+ * @goal generate
+ * @lifecycle process-classes
+ * @phase process-classes
+ * @execute phase="process-classes"
+ * @execute goal="process-classes:generate"
+ * @requiresDependencyResolution compile
+ * @requiresProject true
+ * @threadSafe true
+ */
+public class LightningGeneratorMojo
+ extends AbstractCompilerMojo
+{
+
+ /**
+ * The current build session instance. This is used for toolchain manager API calls.
+ *
+ * @parameter default-value="${session}"
+ * @required
+ * @readonly
+ */
+ private MavenSession session;
+
+ /**
+ * The java generated-source directory.
+ *
+ * @parameter default-value= "${project.build.directory}/generated-sources/lightning"
+ */
+ private File generatedSourceDirectory;
+
+ /**
+ * The directory where compiled classes resist.
+ *
+ * @parameter default-value="${project.build.directory}/classes"
+ */
+ private File targetBuildDirectory;
+
+ /**
+ * Project classpath.
+ *
+ * @parameter default-value="${project.compileClasspathElements}"
+ * @required
+ * @readonly
+ */
+ private List<String> classpathElements;
+
+ /**
+ * The generator strategy.
+ *
+ * @parameter default-value="speed"
+ */
+ private String strategy;
+
+ @Override
+ public void execute()
+ throws MojoExecutionException, CompilationFailureException
+ {
+ if ( encoding == null )
+ {
+ encoding = "UTF-8";
+ }
+
+ SerializationStrategy serializationStrategy =
+ "size".equalsIgnoreCase( strategy ) ? SerializationStrategy.SizeOptimized
+ : SerializationStrategy.SpeedOptimized;
+
+ MavenLoggerAdapter logger = new MavenLoggerAdapter( LightningGeneratorMojo.class.getCanonicalName() );
+ getLog().info( "Searching in path " + targetBuildDirectory.getAbsolutePath() );
+ List<File> files =
+ SupportUtil.recursiveGetAllJavaSources( targetBuildDirectory, new ArrayList<File>(), fileFilter );
+
+ List<URL> urlClasspathElements = new ArrayList<URL>();
+ if ( getClasspathElements() != null )
+ {
+ for ( String classpathElement : getClasspathElements() )
+ {
+ try
+ {
+ URL url = new File( classpathElement ).toURI().toURL();
+ urlClasspathElements.add( url );
+ }
+ catch ( Exception e )
+ {
+ // Intentionally left blank
+ }
+ }
+ }
+ ClassLoader classLoader =
+ new URLClassLoader( urlClasspathElements.toArray( new URL[urlClasspathElements.size()] ),
+ getClass().getClassLoader() );
+
+ for ( File file : files )
+ {
+ try
+ {
+ String className = file.getAbsolutePath().replace( targetBuildDirectory.getAbsolutePath(), "" );
+ if ( className.startsWith( "/" ) || className.startsWith( "\\" ) )
+ {
+ className = className.substring( 1 );
+ }
+
+ className = className.replace( ".class", "" ).replace( "/", "." ).replace( "\\", "." );
+
+ getLog().debug( "Trying class " + className );
+ Class<?> clazz = classLoader.loadClass( className );
+ if ( AbstractSerializerDefinition.class.isAssignableFrom( clazz ) )
+ {
+ getLog().debug( "Found SerializerDefinition in class " + className );
+
+ AbstractSerializerDefinition definition = (AbstractSerializerDefinition) clazz.newInstance();
+
+ SerializerDefinitionAnalyser analyser = new SerializerDefinitionAnalyser( logger );
+ analyser.analyse( definition );
+ analyser.build( generatedSourceDirectory, serializationStrategy, encoding );
+ }
+ }
+ catch ( Exception e )
+ {
+ logger.error( "Could not generate Lightning source for file " + file.getName(), e );
+ }
+ }
+
+ super.execute();
+
+ // session.getCurrentProject().addCompileSourceRoot(generatedSourceDirectory.getAbsolutePath());
+ }
+
+ @Override
+ protected SourceInclusionScanner getSourceInclusionScanner( int staleMillis )
+ {
+ return new StaleSourceScanner( staleMillis );
+ }
+
+ @Override
+ protected SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding )
+ {
+ return new SimpleSourceInclusionScanner( Collections.singleton( "**/*.java" ), Collections.EMPTY_SET );
+ }
+
+ @Override
+ protected List<String> getClasspathElements()
+ {
+ return classpathElements;
+ }
+
+ @Override
+ protected List<String> getCompileSourceRoots()
+ {
+ return Collections.singletonList( generatedSourceDirectory.getAbsolutePath() );
+ }
+
+ @Override
+ protected File getOutputDirectory()
+ {
+ return targetBuildDirectory;
+ }
+
+ @Override
+ protected String getSource()
+ {
+ return source;
+ }
+
+ @Override
+ protected String getTarget()
+ {
+ return target;
+ }
+
+ @Override
+ protected String getCompilerArgument()
+ {
+ return compilerArgument;
+ }
+
+ @Override
+ protected Map<String, String> getCompilerArguments()
+ {
+ return compilerArguments;
+ }
+
+ @Override
+ protected File getGeneratedSourcesDirectory()
+ {
+ return generatedSourceDirectory;
+ }
+
+ private final FileFilter fileFilter = new FileFilter()
+ {
+
+ @Override
+ public boolean accept( File file )
+ {
+ return file.isDirectory() || file.getName().endsWith( ".class" );
+ }
+ };
+
+ private class FileObject
+ extends SimpleJavaFileObject
+ {
+
+ private final Charset charset;
+
+ private final File file;
+
+ private FileObject( File file, Charset charset )
+ {
+ super( file.toURI(), Kind.SOURCE );
+ this.charset = charset;
+ this.file = file;
+ }
+
+ @Override
+ public CharSequence getCharContent( boolean ignoreEncodingErrors )
+ throws IOException
+ {
+ return SupportUtil.readAllText( file, charset );
+ }
+ }
+
+ private class MavenLoggerAdapter
+ implements Logger
+ {
+
+ private final String name;
+
+ private MavenLoggerAdapter( String name )
+ {
+ this.name = name;
+ }
+
+ @Override
+ public Logger getChildLogger( Class<?> clazz )
+ {
+ return getChildLogger( clazz.getCanonicalName() );
+ }
+
+ @Override
+ public Logger getChildLogger( String name )
+ {
+ return new MavenLoggerAdapter( name );
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public boolean isLogLevelEnabled( LogLevel logLevel )
+ {
+ if ( logLevel == LogLevel.Debug )
+ {
+ return getLog().isDebugEnabled();
+ }
+
+ if ( logLevel == LogLevel.Error )
+ {
+ return getLog().isErrorEnabled();
+ }
+
+ if ( logLevel == LogLevel.Fatal )
+ {
+ return getLog().isErrorEnabled();
+ }
+
+ if ( logLevel == LogLevel.Trace )
+ {
+ return getLog().isDebugEnabled();
+ }
+
+ if ( logLevel == LogLevel.Warn )
+ {
+ return getLog().isWarnEnabled();
+ }
+
+ return getLog().isInfoEnabled();
+ }
+
+ @Override
+ public boolean isTraceEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Trace );
+ }
+
+ @Override
+ public boolean isDebugEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Debug );
+ }
+
+ @Override
+ public boolean isInfoEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Info );
+ }
+
+ @Override
+ public boolean isWarnEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Warn );
+ }
+
+ @Override
+ public boolean isErrorEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Error );
+ }
+
+ @Override
+ public boolean isFatalEnabled()
+ {
+ return isLogLevelEnabled( LogLevel.Fatal );
+ }
+
+ @Override
+ public void trace( String message )
+ {
+ trace( message, null );
+ }
+
+ @Override
+ public void trace( String message, Throwable throwable )
+ {
+ debug( message, throwable );
+ }
+
+ @Override
+ public void debug( String message )
+ {
+ debug( message, null );
+ }
+
+ @Override
+ public void debug( String message, Throwable throwable )
+ {
+ getLog().debug( message, throwable );
+ }
+
+ @Override
+ public void info( String message )
+ {
+ info( message, null );
+ }
+
+ @Override
+ public void info( String message, Throwable throwable )
+ {
+ getLog().info( message, throwable );
+ }
+
+ @Override
+ public void warn( String message )
+ {
+ warn( message, null );
+ }
+
+ @Override
+ public void warn( String message, Throwable throwable )
+ {
+ getLog().warn( message, throwable );
+ }
+
+ @Override
+ public void error( String message )
+ {
+ error( message, null );
+ }
+
+ @Override
+ public void error( String message, Throwable throwable )
+ {
+ getLog().error( message, throwable );
+ }
+
+ @Override
+ public void fatal( String message )
+ {
+ fatal( message, null );
+ }
+
+ @Override
+ public void fatal( String message, Throwable throwable )
+ {
+ error( message, throwable );
+ }
+ }
+}
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SerializerDefinitionAnalyser.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SerializerDefinitionAnalyser.java
new file mode 100644
index 0000000..956b764
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SerializerDefinitionAnalyser.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.MarshallerStrategy;
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.configuration.SerializerDefinition;
+import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
+import org.apache.directmemory.lightning.generator.DefinitionVisitor;
+import org.apache.directmemory.lightning.generator.PropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.InternalClassDescriptor;
+import org.apache.directmemory.lightning.internal.InternalDefinitionBuildingContext;
+import org.apache.directmemory.lightning.internal.InternalMarshallerStrategy;
+import org.apache.directmemory.lightning.internal.beans.InternalPropertyDescriptorFactory;
+import org.apache.directmemory.lightning.internal.util.ClassUtil;
+import org.apache.directmemory.lightning.internal.util.TypeUtil;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.Attribute;
+import org.apache.directmemory.lightning.metadata.ClassDefinition;
+import org.apache.directmemory.lightning.metadata.ClassDescriptor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public class SerializerDefinitionAnalyser
+{
+
+ private final Logger logger;
+
+ private final Map<Class<?>, InternalClassDescriptor> classDescriptors =
+ new HashMap<Class<?>, InternalClassDescriptor>();
+
+ private final List<SerializerDefinition> serializerDefinitions = new ArrayList<SerializerDefinition>();
+
+ private final Map<Class<?>, Marshaller> marshallers = new HashMap<Class<?>, Marshaller>();
+
+ private Class<? extends Annotation> attributeAnnotation = Placeholder.class;
+
+ private final DefinitionVisitor definitionVisitor = new GeneratorDefinitionVisitor();
+
+ public SerializerDefinitionAnalyser( Logger logger )
+ {
+ this.logger = logger;
+ }
+
+ public void analyse( SerializerDefinition serializerDefinition )
+ {
+ PropertyDescriptorFactory propertyDescriptorFactory = new InternalPropertyDescriptorFactory( logger );
+ MarshallerStrategy marshallerStrategy = new InternalMarshallerStrategy();
+ DefinitionBuildingContext definitionBuildingContext =
+ new InternalDefinitionBuildingContext( marshallerStrategy, propertyDescriptorFactory );
+
+ serializerDefinition.configure( definitionBuildingContext, null );
+ serializerDefinition.acceptVisitor( definitionVisitor );
+ }
+
+ public List<File> build( File outputFolder, SerializationStrategy serializationStrategy, String encoding )
+ {
+ Charset charset = Charset.forName( encoding );
+
+ List<ClassDefinition> classDefinitions = new ArrayList<ClassDefinition>();
+ for ( InternalClassDescriptor classDescriptor : classDescriptors.values() )
+ {
+ classDefinitions.add( classDescriptor.build( ClassUtil.CLASS_DESCRIPTORS ).getClassDefinition() );
+ }
+
+ List<File> files = new ArrayList<File>();
+ for ( ClassDescriptor classDescriptor : classDescriptors.values() )
+ {
+ if ( classDescriptor instanceof InternalClassDescriptor && classDescriptor.getMarshaller() == null )
+ {
+ try
+ {
+ SourceMarshallerGenerator generator = new SourceMarshallerGenerator( charset, logger );
+ File sourceFile =
+ generator.generateMarshaller( classDescriptor.getType(),
+ classDescriptor.getPropertyDescriptors(), serializationStrategy,
+ outputFolder );
+
+ files.add( sourceFile );
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return files;
+ }
+
+ public List<SerializerDefinition> getVisitedSerializerDefinitions()
+ {
+ return serializerDefinitions;
+ }
+
+ private InternalClassDescriptor findClassDescriptor( Class<?> type )
+ {
+ InternalClassDescriptor classDescriptor = classDescriptors.get( type );
+ if ( classDescriptor == null )
+ {
+ classDescriptor = new InternalClassDescriptor( type, logger );
+ classDescriptors.put( type, classDescriptor );
+ }
+
+ return classDescriptor;
+ }
+
+ private class GeneratorDefinitionVisitor
+ implements DefinitionVisitor
+ {
+
+ private final Stack<Class<? extends Annotation>> attributeAnnotation = new Stack<Class<? extends Annotation>>();
+
+ @Override
+ public void visitSerializerDefinition( SerializerDefinition serializerDefinition )
+ {
+ // If at top level definition just add the base annotation
+ if ( attributeAnnotation.size() == 0 )
+ {
+ if ( SerializerDefinitionAnalyser.this.attributeAnnotation == null )
+ {
+ attributeAnnotation.push( Attribute.class );
+ }
+ else
+ {
+ attributeAnnotation.push( SerializerDefinitionAnalyser.this.attributeAnnotation );
+ }
+ }
+ else
+ {
+ Class<? extends Annotation> annotation = attributeAnnotation.peek();
+ attributeAnnotation.push( annotation );
+ }
+
+ // Save visited SerializerDefinition
+ serializerDefinitions.add( serializerDefinition );
+ }
+
+ @Override
+ public void visitAttributeAnnotation( Class<? extends Annotation> attributeAnnotation )
+ {
+ // Remove last element and replace it with the real annotation to
+ // use right from that moment
+ this.attributeAnnotation.pop();
+ this.attributeAnnotation.push( attributeAnnotation );
+ }
+
+ @Override
+ public void visitClassDefine( Type type, Marshaller marshaller )
+ {
+ Class<?> rawType = TypeUtil.getBaseType( type );
+ InternalClassDescriptor classDescriptor = findClassDescriptor( rawType );
+ classDescriptor.setMarshaller( marshaller );
+
+ marshallers.put( rawType, marshaller );
+ }
+
+ @Override
+ public void visitAnnotatedAttribute( PropertyDescriptor propertyDescriptor, Marshaller marshaller )
+ {
+ InternalClassDescriptor classDescriptor = findClassDescriptor( propertyDescriptor.getDefinedClass() );
+
+ if ( logger.isTraceEnabled() )
+ {
+ logger.trace( "Found property " + propertyDescriptor.getName() + " ("
+ + propertyDescriptor.getInternalSignature() + ") on type "
+ + propertyDescriptor.getDefinedClass().getCanonicalName() );
+ }
+
+ classDescriptor.push( propertyDescriptor );
+ }
+
+ @Override
+ public void visitPropertyDescriptor( PropertyDescriptor propertyDescriptor, Marshaller marshaller )
+ {
+ InternalClassDescriptor classDescriptor = findClassDescriptor( propertyDescriptor.getDefinedClass() );
+
+ if ( logger.isTraceEnabled() )
+ {
+ logger.trace( "Found property " + propertyDescriptor.getName() + " ("
+ + propertyDescriptor.getInternalSignature() + ") on type "
+ + propertyDescriptor.getDefinedClass().getCanonicalName() );
+ }
+
+ classDescriptor.push( propertyDescriptor );
+ }
+
+ @Override
+ public void visitFinalizeSerializerDefinition( SerializerDefinition serializerDefinition )
+ {
+ // Clean this level up
+ this.attributeAnnotation.pop();
+ }
+ }
+
+ public static @interface Placeholder
+ {
+ }
+}
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SourceMarshallerGenerator.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SourceMarshallerGenerator.java
new file mode 100644
index 0000000..92cdeb4
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SourceMarshallerGenerator.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.directmemory.lightning.SerializationStrategy;
+import org.apache.directmemory.lightning.logging.Logger;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+public class SourceMarshallerGenerator
+{
+
+ private final VelocityEngine engine;
+
+ private final Template marshallerTemplate;
+
+ private final Charset charset;
+
+ private final Logger logger;
+
+ public SourceMarshallerGenerator( Charset charset, Logger logger )
+ throws IOException
+ {
+ this.charset = charset;
+ this.logger = logger;
+
+ Properties properties = new Properties();
+ InputStream stream = getClass().getClassLoader().getResourceAsStream( "velocity.properties" );
+ properties.load( stream );
+ engine = new VelocityEngine( properties );
+
+ engine.init();
+ marshallerTemplate = engine.getTemplate( "marshaller.vm", "UTF-8" );
+ }
+
+ public File generateMarshaller( Class<?> type, List<PropertyDescriptor> propertyDescriptors,
+ SerializationStrategy serializationStrategy, File outputFolder )
+ throws IOException
+ {
+
+ // Copy properties and sort them by name
+ List<PropertyDescriptor> propertyDescriptorsCopy = new ArrayList<PropertyDescriptor>( propertyDescriptors );
+ Collections.sort( propertyDescriptorsCopy );
+
+ String packageName = type.getPackage() != null ? type.getPackage().getName() : "lightning";
+ String className = type.getName().replace( packageName + ".", "" ) + "LightningGeneratedMarshaller";
+
+ File packageFolder = new File( outputFolder, packageName.replace( ".", "/" ) );
+ if ( !packageFolder.exists() )
+ {
+ packageFolder.mkdirs();
+ }
+
+ File outputFile = new File( packageFolder, className + ".java" );
+
+ logger.info( "Generating source :" + outputFile.getAbsolutePath() );
+
+ FileOutputStream stream = new FileOutputStream( outputFile );
+ OutputStreamWriter writer = new OutputStreamWriter( stream, charset );
+
+ VelocityContext context = new VelocityContext();
+
+ context.put( "support", new Support() );
+ context.put( "packageName", packageName );
+ context.put( "className", className );
+ context.put( "properties", propertyDescriptorsCopy );
+ context.put( "strategy", serializationStrategy.name() );
+
+ marshallerTemplate.merge( context, writer );
+
+ writer.flush();
+ writer.close();
+
+ return outputFile;
+ }
+
+ public static class Support
+ {
+
+ public String toFinalFieldName( String prefix, PropertyDescriptor propertyDescriptor )
+ {
+ return new StringBuilder( prefix.toUpperCase() ).append( "_" ).append( propertyDescriptor.getPropertyName().toUpperCase() ).append( "_LIGHTNING" ).toString();
+ }
+
+ public String generateWriter( PropertyDescriptor propertyDescriptor, String instanceName )
+ {
+ StringBuilder sb =
+ new StringBuilder( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor.write" );
+ Class<?> type = propertyDescriptor.getType();
+ if ( type == boolean.class )
+ {
+ sb.append( "Boolean(" ).append( instanceName ).append( ", ((Boolean) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").booleanValue())" );
+ }
+ else if ( type == byte.class )
+ {
+ sb.append( "Byte(" ).append( instanceName ).append( ", ((Byte) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").byteValue())" );
+ }
+ else if ( type == char.class )
+ {
+ sb.append( "Char(" ).append( instanceName ).append( ", ((Character) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").charValue())" );
+ }
+ else if ( type == short.class )
+ {
+ sb.append( "Short(" ).append( instanceName ).append( ", ((Short) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").shortValue())" );
+ }
+ else if ( type == int.class )
+ {
+ sb.append( "Int(" ).append( instanceName ).append( ", ((Integer) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").intValue())" );
+ }
+ else if ( type == long.class )
+ {
+ sb.append( "Long(" ).append( instanceName ).append( ", ((Long) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").longValue())" );
+ }
+ else if ( type == float.class )
+ {
+ sb.append( "Float(" ).append( instanceName ).append( ", ((Float) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").floatValue())" );
+ }
+ else if ( type == double.class )
+ {
+ sb.append( "Double(" ).append( instanceName ).append( ", ((Double) " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ").doubleValue())" );
+ }
+ else
+ {
+ sb.append( "Object(" ).append( instanceName ).append( ", " ).append( propertyDescriptor.getPropertyName() ).append( "Value" ).append( ")" );
+ }
+
+ return sb.append( ";" ).toString();
+ }
+
+ public String generateReader( PropertyDescriptor propertyDescriptor )
+ {
+ StringBuilder sb = new StringBuilder();
+ Class<?> type = propertyDescriptor.getType();
+ if ( type == boolean.class )
+ {
+ sb.append( "Boolean.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readBoolean(" );
+ }
+ else if ( type == byte.class )
+ {
+ sb.append( "Byte.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readByte(" );
+ }
+ else if ( type == char.class )
+ {
+ sb.append( "Character.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readChar(" );
+ }
+ else if ( type == short.class )
+ {
+ sb.append( "Short.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readShort(" );
+ }
+ else if ( type == int.class )
+ {
+ sb.append( "Integer.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readInt(" );
+ }
+ else if ( type == long.class )
+ {
+ sb.append( "Long.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readLong(" );
+ }
+ else if ( type == float.class )
+ {
+ sb.append( "Float.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readFloat(" );
+ }
+ else if ( type == double.class )
+ {
+ sb.append( "Double.valueOf(" ).append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readDouble(" );
+ }
+ else
+ {
+ sb.append( propertyDescriptor.getPropertyName() ).append( "PropertyAccessor" ).append( ".readObject(" );
+ }
+
+ sb.append( "value)" );
+
+ if ( type.isPrimitive() )
+ {
+ sb.append( ")" );
+ }
+
+ return sb.toString();
+ }
+ }
+}
diff --git a/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SupportUtil.java b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SupportUtil.java
new file mode 100644
index 0000000..f6cd05f
--- /dev/null
+++ b/lightning-maven-plugin/src/main/java/org/apache/directmemory/lightning/maven/SupportUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class SupportUtil
+{
+
+ private SupportUtil()
+ {
+ }
+
+ public static List<File> recursiveGetAllJavaSources( File file, ArrayList<File> list, FileFilter fileFilter )
+ {
+ if ( file.isDirectory() )
+ {
+ for ( File f : file.listFiles( fileFilter ) )
+ {
+ recursiveGetAllJavaSources( f, list, fileFilter );
+ }
+ }
+ else
+ {
+ list.add( file );
+ }
+ return list;
+ }
+
+ public static String readAllText( File file, Charset charset )
+ {
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ LineNumberReader reader = new LineNumberReader( new FileReader( file ) );
+ String line = null;
+ while ( ( line = reader.readLine() ) != null )
+ {
+ sb.append( line );
+ }
+ return sb.toString();
+ }
+ catch ( IOException e )
+ {
+ return null;
+ }
+ }
+}
diff --git a/lightning-maven-plugin/src/main/resources/marshaller.vm b/lightning-maven-plugin/src/main/resources/marshaller.vm
new file mode 100644
index 0000000..b5a60de
--- /dev/null
+++ b/lightning-maven-plugin/src/main/resources/marshaller.vm
@@ -0,0 +1,96 @@
+#**
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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 ${packageName};
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directmemory.lightning.Marshaller;
+import org.apache.directmemory.lightning.SerializationContext;
+import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
+import org.apache.directmemory.lightning.internal.ClassDescriptorAwareSerializer;
+import org.apache.directmemory.lightning.internal.generator.AbstractGeneratedMarshaller;
+import org.apache.directmemory.lightning.metadata.ValuePropertyAccessor;
+import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
+
+public final class ${className} extends AbstractGeneratedMarshaller {
+
+#foreach( $property in ${properties} )
+ private final PropertyDescriptor ${support.toFinalFieldName("descriptor", $property)};
+ private final Marshaller ${support.toFinalFieldName("marshaller", $property)};
+ private final ValuePropertyAccessor ${support.toFinalFieldName("accessor", $property)};
+#end
+
+ public ${className} (Class<?> marshalledType, Map<Class<?>, Marshaller> marshallers,
+ ClassDescriptorAwareSerializer serializer, ObjectInstantiatorFactory objectInstantiatorFactory,
+ List<PropertyDescriptor> propertyDescriptors) {
+
+ super(marshalledType, marshallers, serializer, objectInstantiatorFactory);
+#set( $index = 0)
+#foreach( $property in ${properties} )
+ ${support.toFinalFieldName("descriptor", $property)} = propertyDescriptors.get(${index});
+
+ PropertyDescriptor ${property.propertyName} = findPropertyDescriptor("${property.propertyName}", propertyDescriptors);
+ Marshaller ${property.propertyName}Marshaller = ${property.propertyName}.getMarshaller();
+ if (${property.propertyName}Marshaller == null) {
+ ${property.propertyName}Marshaller = findMarshaller(${property.propertyName});
+ }
+ ${support.toFinalFieldName("marshaller", $property)} = ${property.propertyName}Marshaller;
+
+ ${support.toFinalFieldName("accessor", $property)} = (ValuePropertyAccessor) getPropertyAccessor("${property.propertyName}");
+#set( $index = $index + 1)
+#end
+ }
+
+ public void marshall(Object value, PropertyDescriptor propertyDescriptor, DataOutput dataOutput, SerializationContext serializationContext) throws IOException {
+ if (isAlreadyMarshalled(value, propertyDescriptor.getType(), dataOutput, serializationContext)) {
+ return;
+ }
+
+#foreach( $property in ${properties} )
+ ValuePropertyAccessor ${property.propertyName}PropertyAccessor = this.${support.toFinalFieldName("accessor", $property)};
+ PropertyDescriptor ${property.propertyName}PropertyDescriptor = this.${support.toFinalFieldName("descriptor", $property)};
+ this.${support.toFinalFieldName("marshaller", $property)}.marshall(${support.generateReader($property)}, ${property.propertyName}PropertyDescriptor, dataOutput, serializationContext);
+
+#end
+ }
+
+ public <V> V unmarshall(V instance, PropertyDescriptor propertyDescriptor, DataInput dataInput, SerializationContext serializationContext) throws IOException {
+#foreach( $property in ${properties} )
+ ValuePropertyAccessor ${property.propertyName}PropertyAccessor = this.${support.toFinalFieldName("accessor", $property)};
+ PropertyDescriptor ${property.propertyName}PropertyDescriptor = this.${support.toFinalFieldName("descriptor", $property)};
+ Object ${property.propertyName}Value = this.${support.toFinalFieldName("marshaller", $property)}.unmarshall(${property.propertyName}PropertyDescriptor, dataInput, serializationContext);
+ ${support.generateWriter($property, "instance")}
+
+#end
+ return instance;
+ }
+
+ private PropertyDescriptor findPropertyDescriptor(String propertyName, List<PropertyDescriptor> propertyDescriptors) {
+ for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+ if (propertyDescriptor.getPropertyName().equals(propertyName)) {
+ return propertyDescriptor;
+ }
+ }
+ return null;
+ }
+}
diff --git a/lightning-maven-plugin/src/main/resources/velocity.properties b/lightning-maven-plugin/src/main/resources/velocity.properties
new file mode 100644
index 0000000..6d187e9
--- /dev/null
+++ b/lightning-maven-plugin/src/main/resources/velocity.properties
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+runtime.log=target/velocity.log
+resource.loader = class
+class.resource.loader.description = Velocity Classpath Loader
+class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
\ No newline at end of file
diff --git a/lightning-maven-plugin/src/test/java/org/apache/directmemory/lightning/maven/GeneratorTestCase.java b/lightning-maven-plugin/src/test/java/org/apache/directmemory/lightning/maven/GeneratorTestCase.java
new file mode 100644
index 0000000..b564afe
--- /dev/null
+++ b/lightning-maven-plugin/src/test/java/org/apache/directmemory/lightning/maven/GeneratorTestCase.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2012 the original author or authors.
+ *
+ * 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.apache.directmemory.lightning.maven;
+
+import java.io.File;
+import java.net.URL;
+
+import org.apache.directmemory.lightning.maven.LightningGeneratorMojo;
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.junit.Test;
+
+public class GeneratorTestCase
+ extends AbstractMojoTestCase
+{
+
+ @Test
+ public void testGeneration()
+ throws Exception
+ {
+ URL url = getClass().getClassLoader().getResource( "generate-pom.xml" );
+ LightningGeneratorMojo mojo = (LightningGeneratorMojo) lookupMojo( "generate", new File( url.toURI() ) );
+ mojo.execute();
+ }
+}
diff --git a/lightning-maven-plugin/src/test/resources/generate-pom.xml b/lightning-maven-plugin/src/test/resources/generate-pom.xml
new file mode 100644
index 0000000..99d18f6
--- /dev/null
+++ b/lightning-maven-plugin/src/test/resources/generate-pom.xml
@@ -0,0 +1,50 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>test</groupId>
+ <artifactId>test</artifactId>
+ <version>0</version>
+ <name>test</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <artifactId>lightning-maven-plugin</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ generate
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <generatedSourceDirectory>target/test-generate</generatedSourceDirectory>
+ <targetBuildDirectory>target/test-classes</targetBuildDirectory>
+ <compilerId>javac</compilerId>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..02da73d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,461 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.directmemory.lightning</groupId>
+ <artifactId>lightning-reactor</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>Lightning: Reactor</name>
+ <description>Lightning fast Java Serialization</description>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>lightning-core</module>
+ <module>lightning-maven-plugin</module>
+ <module>lightning-api</module>
+ <module>lightning-maven-integration-test</module>
+ <module>lightning-maven-eclipse-helper</module>
+ <module>lightning-maven-eclipse-helper-feature</module>
+ <module>lightning-integration</module>
+ </modules>
+
+ <distributionManagement>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <name>Nexus Release Repository</name>
+ <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/
+ </url>
+ </repository>
+ <snapshotRepository>
+ <id>sonatype-nexus-snapshots</id>
+ <name>Sonatype Nexus Snapshots</name>
+ <url>http://oss.sonatype.org/content/repositories/snapshots</url>
+ </snapshotRepository>
+ </distributionManagement>
+
+ <developers>
+ <developer>
+ <id>noctarius</id>
+ <name>Christoph Engelbert</name>
+ <roles>
+ <role>Committer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <licenses>
+ <license>
+ <name>Apache License Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <issueManagement>
+ <system>GitHub Issue Tracker</system>
+ <url>https://github.com/noctarius/Lightning/issues</url>
+ </issueManagement>
+
+ <scm>
+ <connection>scm:git:http://github.com/Lightning/Lightning</connection>
+ <developerConnection>scm:git:https://github.com/Lightning/Lightning</developerConnection>
+ <url>http://github.com/Lightning/Lightning</url>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+ <maven.version>[3.0.3,)</maven.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Core dependencies -->
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode</groupId>
+ <artifactId>reflectasm</artifactId>
+ <version>1.01</version>
+ <exclusions>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.9</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- Core dependencies -->
+
+ <!-- Integration dependencies -->
+ <dependency>
+ <groupId>org.jgroups</groupId>
+ <artifactId>jgroups</artifactId>
+ <version>3.0.4.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>2.5.6</version>
+ </dependency>
+ <!-- Integration dependencies -->
+
+ <!-- Maven plugin dependencies -->
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>${maven.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings-builder</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-repository-metadata</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model-builder</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-aether-provider</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-impl</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.sonatype.aether</groupId>
+ <artifactId>aether-util</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.sonatype.sisu</groupId>
+ <artifactId>sisu-inject-plexus</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-interpolation</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-classworlds</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-annotations</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.sonatype.plexus</groupId>
+ <artifactId>plexus-sec-dispatcher</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.plugin-testing</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <version>2.0-alpha-1</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- Maven plugin dependencies -->
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.1</version>
+ <configuration>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1.2</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8.1</version>
+ <configuration>
+ <excludePackageNames>*.internal*</excludePackageNames>
+ <detectJavaApiLink>true</detectJavaApiLink>
+ <detectLinks>true</detectLinks>
+ <source>1.6</source>
+ <links>
+ <link>http://docs.oracle.com/javase/6/docs/api/</link>
+ </links>
+ </configuration>
+ <executions>
+ <execution>
+ <id>package-javadoc</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>changelog-maven-plugin</artifactId>
+ <version>2.0-beta-1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>2.4.0</version>
+ <configuration>
+ <effort>Max</effort>
+ <threshold>Low</threshold>
+ <xmlOutput>true</xmlOutput>
+ <failOnError>false</failOnError>
+ <findbugsXmlOutput>true</findbugsXmlOutput>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <version>1.0-alpha-3</version>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <addDefaultLicenseMatchers>false</addDefaultLicenseMatchers>
+ <licenseMatchers>
+ <classNames>
+ <className>rat.analysis.license.ApacheSoftwareLicense20</className>
+ </classNames>
+ </licenseMatchers>
+ <includes>
+ <include>pom.xml</include>
+ <include>src/**</include>
+ </includes>
+ <excludes>
+ <exclude>src/**/bundle/**</exclude>
+ <exclude>src/**/jrockit/**</exclude>
+ <exclude>src/**/generated.java.out</exclude>
+ <exclude>META-INF/MANIFEST.MF</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <targetPath>target/classes</targetPath>
+ <directory>${basedir}</directory>
+ <includes>
+ <include>*.txt</include>
+ </includes>
+ </resource>
+ </resources>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>jarjar-maven-plugin</artifactId>
+ <versionRange>[1.4,)</versionRange>
+ <goals>
+ <goal>jarjar</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>2.4.0</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <profiles>
+ <profile>
+ <id>release-sign-artifacts</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <modules>
+ <module>lightning-core</module>
+ <module>lightning-maven-plugin</module>
+ <module>lightning-api</module>
+ <module>lightning-maven-integration-test</module>
+ <module>lightning-integration</module>
+ </modules>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>sign-artifacts</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file