You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by tb...@apache.org on 2014/06/24 13:45:59 UTC

git commit: Prototype: Protocol Buffer Support

Repository: olingo-odata2
Updated Branches:
  refs/heads/ProtocolBufferPrototype [created] 62bc99e37


Prototype: Protocol Buffer Support


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/62bc99e3
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/62bc99e3
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/62bc99e3

Branch: refs/heads/ProtocolBufferPrototype
Commit: 62bc99e37a209c35f58fb91c7a2bd58f7f8b9bf6
Parents: f86e307
Author: Tamara Boehm <ta...@sap.com>
Authored: Tue Jun 24 13:20:51 2014 +0200
Committer: Tamara Boehm <ta...@sap.com>
Committed: Tue Jun 24 13:20:51 2014 +0200

----------------------------------------------------------------------
 odata2-lib/odata-ref/pom.xml                    | 100 +++++++++-----
 .../odata2/ref/processor/ListsProcessor.java    | 131 +++++++++++++++++++
 2 files changed, 200 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/62bc99e3/odata2-lib/odata-ref/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-ref/pom.xml b/odata2-lib/odata-ref/pom.xml
index 84a49d5..434966f 100644
--- a/odata2-lib/odata-ref/pom.xml
+++ b/odata2-lib/odata-ref/pom.xml
@@ -1,22 +1,14 @@
 <?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.
--->
+<!-- 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>
@@ -69,6 +61,47 @@
 					</instructions>
 				</configuration>
 			</plugin>
+			<plugin>
+				<groupId>de.softwareforge.mojo</groupId>
+				<artifactId>maven-protoc-plugin</artifactId>
+				<version>0.2-HPS-2</version>
+				<executions>
+					<execution>
+						<id>generate-sources</id>
+						<goals>
+							<goal>compile</goal>
+						</goals>
+						<phase>generate-sources</phase>
+						<configuration>
+							<protoSourceRoot>${basedir}/src/main/resources/</protoSourceRoot>
+							<includes>
+								<param>**/*.proto</param>
+							</includes>
+						</configuration>
+					</execution>
+				</executions>
+				<configuration>
+					<protocExecutable>/usr/local/bin/protoc</protocExecutable>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>build-helper-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>add-source</id>
+						<phase>generate-sources</phase>
+						<goals>
+							<goal>add-source</goal>
+						</goals>
+						<configuration>
+							<sources>
+								<source>${project.build.directory}/generated-sources/java/</source>
+							</sources>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
 
@@ -84,7 +117,7 @@
 			<artifactId>slf4j-api</artifactId>
 			<version>${slf4j.version}</version>
 		</dependency>
-    
+
 		<dependency>
 			<groupId>org.apache.olingo</groupId>
 			<artifactId>olingo-odata2-core</artifactId>
@@ -97,18 +130,23 @@
 			<version>${project.version}</version>
 			<scope>test</scope>
 		</dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-all</artifactId>
-            <version>${mockito.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>${junit.version}</version>
-            <scope>test</scope>
-        </dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-all</artifactId>
+			<version>${mockito.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.protobuf</groupId>
+			<artifactId>protobuf-java</artifactId>
+			<version>2.5.0</version>
+		</dependency>
 	</dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/62bc99e3/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java
----------------------------------------------------------------------
diff --git a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java
index 7e22a3d..e6781f3 100644
--- a/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java
+++ b/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java
@@ -18,9 +18,13 @@
  ******************************************************************************/
 package org.apache.olingo.odata2.ref.processor;
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -76,9 +80,11 @@ import org.apache.olingo.odata2.api.exception.ODataHttpException;
 import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
 import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
 import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
 import org.apache.olingo.odata2.api.processor.ODataRequest;
 import org.apache.olingo.odata2.api.processor.ODataResponse;
 import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
 import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
 import org.apache.olingo.odata2.api.uri.KeyPredicate;
 import org.apache.olingo.odata2.api.uri.NavigationSegment;
@@ -111,8 +117,15 @@ import org.apache.olingo.odata2.api.uri.info.GetMediaResourceUriInfo;
 import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
 import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
 import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+import org.apache.olingo.odata2.ref.model.AddressBookProtos;
 import org.apache.olingo.odata2.ref.processor.ScenarioDataSource.BinaryData;
 
+import com.google.protobuf.Descriptors;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.GeneratedMessage;
+import com.google.protobuf.Message;
+
 /**
  * Implementation of the centralized parts of OData processing,
  * allowing to use the simplified DataSource for the
@@ -121,10 +134,24 @@ import org.apache.olingo.odata2.ref.processor.ScenarioDataSource.BinaryData;
  */
 public class ListsProcessor extends ODataSingleProcessor {
 
+  private static final String CUSTOM_CONTENT_TYPE = "application/x-protobuf";
   // TODO: Paging size should be configurable.
   private static final int SERVER_PAGING_SIZE = 100;
   private final BeanPropertyAccess valueAccess;
   private final ScenarioDataSource dataSource;
+  private static Map<String, String> mapping;
+  static {
+    mapping = new HashMap<String, String>();
+    mapping.put("org.apache.olingo.odata2.ref.model.Room", "org.apache.olingo.odata2.ref.model.AddressBookProtos$Room");
+    mapping.put("org.apache.olingo.odata2.ref.model.Employee",
+        "org.apache.olingo.odata2.ref.model.AddressBookProtos$Employee");
+    mapping.put("org.apache.olingo.odata2.ref.model.Manager",
+        "org.apache.olingo.odata2.ref.model.AddressBookProtos$Employee");
+    mapping.put("org.apache.olingo.odata2.ref.model.Location",
+        "org.apache.olingo.odata2.ref.model.AddressBookProtos$Employee$Location");
+    mapping.put("org.apache.olingo.odata2.ref.model.City",
+        "org.apache.olingo.odata2.ref.model.AddressBookProtos$Employee$City");
+  }
 
   public ListsProcessor(final ScenarioDataSource dataSource) {
     this(dataSource, new BeanPropertyAccess());
@@ -136,6 +163,21 @@ public class ListsProcessor extends ODataSingleProcessor {
   }
 
   @Override
+  public List<String> getCustomContentTypes(final Class<? extends ODataProcessor> processorFeature)
+      throws ODataException {
+    if (processorFeature == EntitySetProcessor.class) {
+      List<String> customContentTypes = new ArrayList<String>();
+      // otherwise fit fails if no media type has been entered
+      customContentTypes.add(HttpContentType.APPLICATION_ATOM_XML_FEED_UTF8);
+      customContentTypes.add(CUSTOM_CONTENT_TYPE);
+      return customContentTypes;
+    } else {
+      return Collections.emptyList();
+    }
+  }
+
+  @SuppressWarnings({ "rawtypes", "unchecked" })
+  @Override
   public ODataResponse readEntitySet(final GetEntitySetUriInfo uriInfo, final String contentType)
       throws ODataException {
     ArrayList<Object> data = new ArrayList<Object>();
@@ -191,6 +233,47 @@ public class ListsProcessor extends ODataSingleProcessor {
 
     final EdmEntityType entityType = entitySet.getEntityType();
     List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
+
+    if (CUSTOM_CONTENT_TYPE.equals(contentType)) {
+      Descriptors.Descriptor addressBookDescriptor = AddressBookProtos.AddressBook.getDescriptor();
+      AddressBookProtos.AddressBook.Builder addressBook = AddressBookProtos.AddressBook.newBuilder();
+      CircleStreamBuffer buffer = new CircleStreamBuffer();
+      try {
+      for (final Object entryData : data) {
+        String className = mapping.get(entryData.getClass().getName());
+      
+        Class<Message> object = (Class<Message>) Class.forName(className);
+        Descriptors.Descriptor descriptor = ( Descriptors.Descriptor) object.getMethod("getDescriptor").invoke(object);
+        GeneratedMessage.Builder builder = (GeneratedMessage.Builder) object.getMethod("newBuilder").invoke(object);
+        Message message = getStructuralTypeValueMapProtobuf(entryData, descriptor,
+           builder, entityType);
+        
+        FieldDescriptor fd = addressBookDescriptor.findFieldByName(descriptor.getName().toLowerCase());
+        if (fd != null) {
+          addressBook.addRepeatedField(fd, message);
+        }
+      }
+      OutputStream output = buffer.getOutputStream();
+    
+
+        addressBook.build().writeTo(output);
+      } catch (IOException e) {
+        throw new ODataException(e);
+      } catch (IllegalArgumentException e) {
+        throw new ODataException(e);
+      } catch (SecurityException e) {
+        throw new ODataException(e);
+      } catch (IllegalAccessException e) {
+        throw new ODataException(e);
+      } catch (InvocationTargetException e) {
+        throw new ODataException(e);
+      } catch (NoSuchMethodException e) {
+        throw new ODataException(e);
+      } catch (ClassNotFoundException e) {
+        throw new ODataException(e);
+      }
+      return ODataResponse.entity(buffer.getInputStream()).build();
+    }
     for (final Object entryData : data) {
       values.add(getStructuralTypeValueMap(entryData, entityType));
     }
@@ -1522,7 +1605,55 @@ public class ListsProcessor extends ODataSingleProcessor {
       }
     }
   }
+  private Message getStructuralTypeValueMapProtobuf(final Object data, final Descriptors.Descriptor descriptor,
+      final GeneratedMessage.Builder message,
+      final EdmStructuralType type) throws ODataException {
 
+    // String cname = data.getClass().getName();
+    Map<String, Object> valueMap = new HashMap<String, Object>();
+
+    for (final String propertyName : type.getPropertyNames()) {
+      final EdmProperty property = (EdmProperty) type.getProperty(propertyName);
+      final Object value = valueAccess.getPropertyValue(data, property);
+      Descriptors.FieldDescriptor fieldDescriptor = descriptor.findFieldByName(propertyName.toLowerCase());
+      if(value!=null){
+      if (property.isSimple()) {
+        if(value instanceof Calendar){
+          message.setField(fieldDescriptor, ((Calendar)value).getTimeInMillis());
+        } else{
+           message.setField(fieldDescriptor, value);
+        }
+        
+      } else {
+        String className = mapping.get(value.getClass().getName());
+        
+        Class<Message> object;
+        try {
+          object = (Class<Message>) Class.forName(className);
+          Descriptors.Descriptor descr = ( Descriptors.Descriptor) object.getMethod("getDescriptor").invoke(object);
+          GeneratedMessage.Builder builder = (GeneratedMessage.Builder) object.getMethod("newBuilder").invoke(object);
+          message.setField(fieldDescriptor, getStructuralTypeValueMapProtobuf(value,descr,
+              builder, (EdmStructuralType) property.getType()));
+        } catch (ClassNotFoundException e) {
+          throw new ODataException(e);
+        } catch (IllegalArgumentException e) {
+          throw new ODataException(e);
+        } catch (SecurityException e) {
+          throw new ODataException(e);
+        } catch (IllegalAccessException e) {
+          throw new ODataException(e);
+        } catch (InvocationTargetException e) {
+          throw new ODataException(e);
+        } catch (NoSuchMethodException e) {
+          throw new ODataException(e);
+        }
+        
+        }
+    }
+    }
+    return message.build();
+  }
+  
   private <T> Map<String, Object> getSimpleTypeValueMap(final T data, final List<EdmProperty> propertyPath)
       throws ODataException {
     final EdmProperty property = propertyPath.get(propertyPath.size() - 1);