add PrefetchTreeNodeSchema to support readResolve() method; update Protostuff version; cleanup;
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/5ce1af22 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/5ce1af22 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/5ce1af22 Branch: refs/heads/master Commit: 5ce1af220f4f91e9366920ebefe7c6ef1d58b316 Parents: 0c26497 Author: Savva Kolbachev <s.kolbac...@gmail.com> Authored: Tue May 17 19:36:21 2016 +0300 Committer: Savva Kolbachev <s.kolbac...@gmail.com> Committed: Mon May 23 17:23:08 2016 +0300 ---------------------------------------------------------------------- cayenne-protostuff/pom.xml | 2 +- .../rop/client/ProtostuffModule.java | 4 +- .../cayenne/query/PrefetchTreeNodeSchema.java | 157 +++++++++++++++++++ .../ProtostuffROPSerializationService.java | 41 ++--- ...otostuffROPSerializationServiceProvider.java | 32 ---- .../apache/cayenne/rop/protostuff/Wrapper.java | 38 +++++ .../ProtostuffPrefetchTreeNodeSchemaIT.java | 62 ++++++++ .../ProtostuffROPSerializationServiceIT.java | 4 +- .../apache/cayenne/query/PrefetchTreeNode.java | 12 +- 9 files changed, 291 insertions(+), 61 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/pom.xml ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/pom.xml b/cayenne-protostuff/pom.xml index 76af8a4..0934f64 100644 --- a/cayenne-protostuff/pom.xml +++ b/cayenne-protostuff/pom.xml @@ -21,7 +21,7 @@ <name>Cayenne Protostuff Extension</name> <properties> - <protostuff.version>1.4.1</protostuff.version> + <protostuff.version>1.4.2</protostuff.version> </properties> <dependencyManagement> http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/main/java/org/apache/cayenne/configuration/rop/client/ProtostuffModule.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/main/java/org/apache/cayenne/configuration/rop/client/ProtostuffModule.java b/cayenne-protostuff/src/main/java/org/apache/cayenne/configuration/rop/client/ProtostuffModule.java index b4a89e5..45d6d65 100644 --- a/cayenne-protostuff/src/main/java/org/apache/cayenne/configuration/rop/client/ProtostuffModule.java +++ b/cayenne-protostuff/src/main/java/org/apache/cayenne/configuration/rop/client/ProtostuffModule.java @@ -21,7 +21,7 @@ package org.apache.cayenne.configuration.rop.client; import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.Module; import org.apache.cayenne.rop.ROPSerializationService; -import org.apache.cayenne.rop.protostuff.ProtostuffROPSerializationServiceProvider; +import org.apache.cayenne.rop.protostuff.ProtostuffROPSerializationService; /** * A DI module that uses Protostuff Object Graph Serialization as Cayenne {@link ROPSerializationService}. @@ -39,6 +39,6 @@ public class ProtostuffModule implements Module { @Override public void configure(Binder binder) { - binder.bind(ROPSerializationService.class).toProvider(ProtostuffROPSerializationServiceProvider.class); + binder.bind(ROPSerializationService.class).to(ProtostuffROPSerializationService.class).inSingletonScope(); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/main/java/org/apache/cayenne/query/PrefetchTreeNodeSchema.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/main/java/org/apache/cayenne/query/PrefetchTreeNodeSchema.java b/cayenne-protostuff/src/main/java/org/apache/cayenne/query/PrefetchTreeNodeSchema.java new file mode 100644 index 0000000..2d4a9a2 --- /dev/null +++ b/cayenne-protostuff/src/main/java/org/apache/cayenne/query/PrefetchTreeNodeSchema.java @@ -0,0 +1,157 @@ +/***************************************************************** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.cayenne.query; + +import io.protostuff.Input; +import io.protostuff.Output; +import io.protostuff.Schema; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * As {@link PrefetchTreeNode} has {@link PrefetchTreeNode#readResolve readResolve} method, which isn't supported + * by Protostuff, we have to provide custom schema for this class. + * + * @see java.io.Serializable + */ +public class PrefetchTreeNodeSchema implements Schema<PrefetchTreeNode> { + + private static final HashMap<String, Integer> fieldMap = new HashMap<>(); + + static { + fieldMap.put("name", 1); + fieldMap.put("phantom", 2); + fieldMap.put("semantics", 3); + fieldMap.put("ejbqlPathEntityId", 4); + fieldMap.put("entityName", 5); + fieldMap.put("children", 6); + } + + @Override + public String getFieldName(int number) { + switch (number) { + case 1: + return "name"; + case 2: + return "phantom"; + case 3: + return "semantics"; + case 4: + return "ejbqlPathEntityId"; + case 5: + return "entityName"; + case 6: + return "children"; + default: + return null; + } + } + + @Override + public int getFieldNumber(String name) { + return fieldMap.getOrDefault(name, 0); + } + + @Override + public boolean isInitialized(PrefetchTreeNode message) { + return true; + } + + @Override + public PrefetchTreeNode newMessage() { + return new PrefetchTreeNode(); + } + + @Override + public String messageName() { + return PrefetchTreeNode.class.getSimpleName(); + } + + @Override + public String messageFullName() { + return PrefetchTreeNode.class.getName(); + } + + @Override + public Class<PrefetchTreeNode> typeClass() { + return PrefetchTreeNode.class; + } + + @Override + public void mergeFrom(Input input, PrefetchTreeNode message) throws IOException { + for (int number = input.readFieldNumber(this);; number = input.readFieldNumber(this)) { + switch (number) { + case 0: + message.readResolve(); + return; + case 1: + message.name = input.readString(); + break; + case 2: + message.setPhantom(input.readBool()); + break; + case 3: + message.setSemantics(input.readInt32()); + break; + case 4: + message.setEjbqlPathEntityId(input.readString()); + break; + case 5: + message.setEntityName(input.readString()); + break; + case 6: + if (message.children == null) { + message.children = new ArrayList<>(4); + } + message.children.add(input.mergeObject(null, this)); + break; + default: + input.handleUnknownField(number, this); + } + } + } + + @Override + public void writeTo(Output output, PrefetchTreeNode message) throws IOException { + if (message.getName() != null) { + output.writeString(1, message.getName(), false); + } + + output.writeBool(2, message.isPhantom(), false); + output.writeInt32(3, message.getSemantics(), false); + + if (message.getEjbqlPathEntityId() != null) { + output.writeString(4, message.getEjbqlPathEntityId(), false); + } + + if (message.getEntityName() != null) { + output.writeString(5, message.getEntityName(), false); + } + + if (message.hasChildren()) { + for (PrefetchTreeNode node : message.getChildren()) { + output.writeObject(6, node, this, true); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationService.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationService.java b/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationService.java index 39cdbc9..371c42f 100644 --- a/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationService.java +++ b/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationService.java @@ -22,7 +22,10 @@ import io.protostuff.GraphIOUtil; import io.protostuff.LinkedBuffer; import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; +import org.apache.cayenne.query.PrefetchTreeNode; +import org.apache.cayenne.query.PrefetchTreeNodeSchema; import org.apache.cayenne.rop.ROPSerializationService; +import org.apache.cayenne.util.PersistentObjectList; import java.io.IOException; import java.io.InputStream; @@ -31,43 +34,45 @@ import java.io.OutputStream; /** * This {@link ROPSerializationService} implementation uses Protostuff {@link GraphIOUtil} to (de)serialize * Cayenne object graph. + * + * @since 4.0 */ public class ProtostuffROPSerializationService implements ROPSerializationService { + protected Schema<Wrapper> wrapperSchema; + + public ProtostuffROPSerializationService() { + this.wrapperSchema = RuntimeSchema.getSchema(Wrapper.class); + registerSchemas(); + } + + protected void registerSchemas() { + RuntimeSchema.register(PersistentObjectList.class, RuntimeSchema.getSchema(PersistentObjectList.class)); + RuntimeSchema.register(PrefetchTreeNode.class, new PrefetchTreeNodeSchema()); + } + @Override public byte[] serialize(Object object) throws IOException { - Schema<Wrapper> schema = RuntimeSchema.getSchema(Wrapper.class); - return GraphIOUtil.toByteArray(new Wrapper(object), schema, LinkedBuffer.allocate()); + return GraphIOUtil.toByteArray(new Wrapper(object), wrapperSchema, LinkedBuffer.allocate()); } @Override public void serialize(Object object, OutputStream outputStream) throws IOException { - Schema<Wrapper> schema = RuntimeSchema.getSchema(Wrapper.class); - GraphIOUtil.writeTo(outputStream, new Wrapper(object), schema, LinkedBuffer.allocate()); + GraphIOUtil.writeTo(outputStream, new Wrapper(object), wrapperSchema, LinkedBuffer.allocate()); } @Override public <T> T deserialize(InputStream inputStream, Class<T> objectClass) throws IOException { - Schema<Wrapper> schema = RuntimeSchema.getSchema(Wrapper.class); - Wrapper result = schema.newMessage(); - GraphIOUtil.mergeFrom(inputStream, result, schema, LinkedBuffer.allocate()); + Wrapper result = wrapperSchema.newMessage(); + GraphIOUtil.mergeFrom(inputStream, result, wrapperSchema, LinkedBuffer.allocate()); return objectClass.cast(result.data); - } @Override public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException { - Schema<Wrapper> schema = RuntimeSchema.getSchema(Wrapper.class); - Wrapper result = schema.newMessage(); - GraphIOUtil.mergeFrom(serializedObject, result, schema); + Wrapper result = wrapperSchema.newMessage(); + GraphIOUtil.mergeFrom(serializedObject, result, wrapperSchema); return objectClass.cast(result.data); } - private class Wrapper { - private Object data; - - public Wrapper(Object data) { - this.data = data; - } - } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceProvider.java b/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceProvider.java deleted file mode 100644 index 35a164d..0000000 --- a/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/***************************************************************** - * 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.cayenne.rop.protostuff; - -import org.apache.cayenne.di.DIRuntimeException; -import org.apache.cayenne.di.Provider; -import org.apache.cayenne.rop.ROPSerializationService; - -public class ProtostuffROPSerializationServiceProvider implements Provider<ROPSerializationService> { - - @Override - public ROPSerializationService get() throws DIRuntimeException { - return new ProtostuffROPSerializationService(); - } - -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/Wrapper.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/Wrapper.java b/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/Wrapper.java new file mode 100644 index 0000000..c3679b0 --- /dev/null +++ b/cayenne-protostuff/src/main/java/org/apache/cayenne/rop/protostuff/Wrapper.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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.cayenne.rop.protostuff; + +import java.io.Serializable; + +/** + * As Protostuff has limitation that nested messages should not contain references to the root message, so we provide + * a simple wrapper for the root message. + * + * <a href="http://www.protostuff.io/documentation/object-graphs/"> + */ +public class Wrapper implements Serializable { + + public Object data; + + public Wrapper(Object data) { + this.data = data; + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/test/java/org/apache/cayenne/query/ProtostuffPrefetchTreeNodeSchemaIT.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/test/java/org/apache/cayenne/query/ProtostuffPrefetchTreeNodeSchemaIT.java b/cayenne-protostuff/src/test/java/org/apache/cayenne/query/ProtostuffPrefetchTreeNodeSchemaIT.java new file mode 100644 index 0000000..3f182b4 --- /dev/null +++ b/cayenne-protostuff/src/test/java/org/apache/cayenne/query/ProtostuffPrefetchTreeNodeSchemaIT.java @@ -0,0 +1,62 @@ +/***************************************************************** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.cayenne.query; + +import org.apache.cayenne.rop.ROPSerializationService; +import org.apache.cayenne.rop.protostuff.ProtostuffROPSerializationService; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class ProtostuffPrefetchTreeNodeSchemaIT { + + private ROPSerializationService clientService; + private ROPSerializationService serverService; + + @Before + public void setUp() throws Exception { + clientService = new ProtostuffROPSerializationService(); + serverService = new ProtostuffROPSerializationService(); + } + + @Test + public void testPrefetchTreeNodeSchema() throws IOException { + PrefetchTreeNode parent = new PrefetchTreeNode(null, "parent"); + PrefetchTreeNode child = new PrefetchTreeNode(parent, "child"); + parent.addChild(child); + + byte[] data = clientService.serialize(parent); + PrefetchTreeNode parent0 = serverService.deserialize(data, PrefetchTreeNode.class); + + assertNotNull(parent0); + assertTrue(parent0.hasChildren()); + + PrefetchTreeNode child0 = parent0.getChild("child"); + assertNotNull(child0); + assertNotNull(child0.parent); + assertEquals(child0.parent, parent0); + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceIT.java ---------------------------------------------------------------------- diff --git a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceIT.java b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceIT.java index b077056..0b73dd6 100644 --- a/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceIT.java +++ b/cayenne-protostuff/src/test/java/org/apache/cayenne/rop/protostuff/ProtostuffROPSerializationServiceIT.java @@ -80,8 +80,8 @@ public class ProtostuffROPSerializationServiceIT { table2.setTable1(table1); table2.setGlobalAttribute(GLOBAL_ATTRIBUTE2); - clientService = new ProtostuffROPSerializationServiceProvider().get(); - serverService = new ProtostuffROPSerializationServiceProvider().get(); + clientService = new ProtostuffROPSerializationService(); + serverService = new ProtostuffROPSerializationService(); } @Test http://git-wip-us.apache.org/repos/asf/cayenne/blob/5ce1af22/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java index e44b08d..d71a7f4 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java @@ -19,6 +19,11 @@ package org.apache.cayenne.query; +import org.apache.cayenne.map.Entity; +import org.apache.cayenne.util.Util; +import org.apache.cayenne.util.XMLEncoder; +import org.apache.cayenne.util.XMLSerializable; + import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; @@ -26,11 +31,6 @@ import java.util.Collection; import java.util.Collections; import java.util.StringTokenizer; -import org.apache.cayenne.map.Entity; -import org.apache.cayenne.util.Util; -import org.apache.cayenne.util.XMLEncoder; -import org.apache.cayenne.util.XMLSerializable; - /** * Defines a node in a prefetch tree. * @@ -472,7 +472,7 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable { // implementing 'readResolve' instead of 'readObject' so that this would // work with // hessian - private Object readResolve() throws ObjectStreamException { + protected Object readResolve() throws ObjectStreamException { if (hasChildren()) { for (PrefetchTreeNode child : children) {