You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2014/03/13 17:30:25 UTC
[37/37] git commit: OLINGO-175 moved ODataJClient test-service into
fit module
OLINGO-175 moved ODataJClient test-service into fit module
Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/commit/70f06578
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/tree/70f06578
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/diff/70f06578
Branch: refs/heads/olingo200
Commit: 70f065789834184a2af16be7381dd3fc5a5d6247
Parents: 119627f
Author: fmartelli <fa...@gmail.com>
Authored: Thu Mar 13 17:29:27 2014 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Thu Mar 13 17:29:27 2014 +0100
----------------------------------------------------------------------
fit/pom.xml | 169 +-
.../org/apache/olingo/fit/AbstractServices.java | 776 ++++++++++
.../fit/UnsupportedMediaTypeException.java | 41 +
.../java/org/apache/olingo/fit/V3Services.java | 38 +
.../java/org/apache/olingo/fit/V4Services.java | 38 +
.../org/apache/olingo/fit/methods/MERGE.java | 31 +
.../org/apache/olingo/fit/methods/PATCH.java | 31 +
.../apache/olingo/fit/rproxy/LinkRewrite.java | 54 +
.../olingo/fit/rproxy/LinkRewriteRenderer.java | 56 +
.../olingo/fit/utils/AbstractUtilities.java | 721 +++++++++
.../org/apache/olingo/fit/utils/Accept.java | 78 +
.../org/apache/olingo/fit/utils/Commons.java | 268 ++++
.../org/apache/olingo/fit/utils/Constants.java | 103 ++
.../org/apache/olingo/fit/utils/FSManager.java | 165 ++
.../apache/olingo/fit/utils/JSONUtilities.java | 428 ++++++
.../org/apache/olingo/fit/utils/LinkInfo.java | 54 +
.../olingo/fit/utils/MetadataLinkInfo.java | 175 +++
.../olingo/fit/utils/NavigationLinks.java | 120 ++
.../apache/olingo/fit/utils/ODataVersion.java | 35 +
.../fit/utils/XHTTPMethodInterceptor.java | 43 +
.../olingo/fit/utils/XMLEventReaderWrapper.java | 144 ++
.../apache/olingo/fit/utils/XMLUtilities.java | 1190 +++++++++++++++
.../org/apache/olingo/fit/utils/XmlElement.java | 99 ++
.../main/resources/META-INF/vfs-providers.xml | 27 +
fit/src/main/resources/context.xml | 25 +
fit/src/main/resources/esigate.properties | 26 +
.../org/esigate/rewrite-proxy.properties | 23 +
fit/src/main/resources/tomcat-users.xml | 27 +
.../main/resources/v3/Car/14/entity.full.json | 13 +
fit/src/main/resources/v3/Car/14/entity.xml | 39 +
.../main/resources/v3/Car/16/entity.full.json | 14 +
fit/src/main/resources/v3/Car/16/entity.xml | 45 +
fit/src/main/resources/v3/Car/feed.full.json | 297 ++++
fit/src/main/resources/v3/Car/feed.xml | 459 ++++++
.../v3/Car/filter/((1 add VIN) eq 16).full.json | 1 +
.../v3/Car/filter/((1 add VIN) eq 16).xml | 45 +
.../v3/Car/filter/((VIN add 1) eq 16).full.json | 1 +
.../v3/Car/filter/((VIN add 1) eq 16).xml | 45 +
.../((VIN lt 16) and (VIN gt 12)).full.json | 1 +
.../filter/((VIN lt 16) and (VIN gt 12)).xml | 81 +
.../v3/Car/filter/(16 eq (1 add VIN)).full.json | 1 +
.../v3/Car/filter/(16 eq (1 add VIN)).xml | 45 +
.../v3/Car/filter/(VIN lt 16).full.json | 1 +
.../resources/v3/Car/filter/(VIN lt 16).xml | 117 ++
...ngth(Description) gt (VIN add 10)).full.json | 1 +
.../(length(Description) gt (VIN add 10)).xml | 117 ++
.../v3/Car/filter/VIN add 5 lt 11.full.json | 1 +
.../resources/v3/Car/filter/VIN add 5 lt 11.xml | 41 +
.../v3/Car/filter/VIN div 2 le 8.full.json | 1 +
.../resources/v3/Car/filter/VIN div 2 le 8.xml | 41 +
.../filter/VIN le 18 and VIN gt 12.full.json | 1 +
.../v3/Car/filter/VIN le 18 and VIN gt 12.xml | 41 +
.../v3/Car/filter/VIN mul 2 le 30.full.json | 1 +
.../resources/v3/Car/filter/VIN mul 2 le 30.xml | 41 +
...not (((VIN ge 16) or (VIN le 12))).full.json | 1 +
.../not (((VIN ge 16) or (VIN le 12))).xml | 81 +
.../startswith(Description,'cen').full.json | 1 +
.../filter/startswith(Description,'cen').xml | 45 +
.../VIN desc/filter/(VIN lt 16).full.json | 9 +
.../Car/orderby/VIN desc/filter/(VIN lt 16).xml | 117 ++
.../v3/ComputerDetail/-10/entity.full.json | 23 +
.../resources/v3/ComputerDetail/-10/entity.xml | 44 +
.../(month(PurchaseDate) eq 12).full.json | 1 +
.../filter/(month(PurchaseDate) eq 12).xml | 64 +
.../filter/day(PurchaseDate) eq 15.full.json | 1 +
.../filter/day(PurchaseDate) eq 15.xml | 41 +
.../filter/hour(PurchaseDate) eq 1.full.json | 1 +
.../filter/hour(PurchaseDate) eq 1.xml | 41 +
.../filter/minute(PurchaseDate) eq 33.full.json | 1 +
.../filter/minute(PurchaseDate) eq 33.xml | 41 +
.../filter/month(PurchaseDate) eq 12.full.json | 1 +
.../filter/month(PurchaseDate) eq 12.xml | 41 +
.../filter/second(PurchaseDate) eq 35.full.json | 1 +
.../filter/second(PurchaseDate) eq 35.xml | 41 +
.../filter/year(PurchaseDate) eq 2020.full.json | 1 +
.../filter/year(PurchaseDate) eq 2020.xml | 41 +
.../resources/v3/Customer/-10/entity.full.json | 673 ++++++++
.../main/resources/v3/Customer/-10/entity.xml | 516 +++++++
.../v3/Customer/-10/links/Info.full.json | 4 +
.../resources/v3/Customer/-10/links/Info.xml | 22 +
.../v3/Customer/-10/links/Logins('3').full.json | 4 +
.../v3/Customer/-10/links/Logins.full.json | 12 +
.../resources/v3/Customer/-10/links/Logins.xml | 25 +
.../v3/Customer/-10/links/Orders(-10).full.json | 4 +
.../v3/Customer/-10/links/Orders.full.json | 13 +
.../resources/v3/Customer/-10/links/Orders.xml | 26 +
.../main/resources/v3/Customer/-7/entity.xml | 381 +++++
.../main/resources/v3/Customer/feed.full.json | 893 +++++++++++
fit/src/main/resources/v3/Customer/feed.xml | 704 +++++++++
....PhoneNumber,'ODataJClient') eq 1).full.json | 1 +
...ePhone.PhoneNumber,'ODataJClient') eq 1).xml | 30 +
...ne.PhoneNumber,'lccvussrv') ne -1).full.json | 1 +
...omePhone.PhoneNumber,'lccvussrv') ne -1).xml | 600 ++++++++
.../Customer/filter/CustomerId eq -10.full.json | 678 ++++++++
.../v3/Customer/filter/CustomerId eq -10.xml | 522 +++++++
.../Customer/filter/CustomerId gt -10.full.json | 1 +
.../v3/Customer/filter/CustomerId gt -10.xml | 740 +++++++++
.../Customer/filter/CustomerId lt -10.full.json | 1 +
.../v3/Customer/filter/CustomerId lt -10.xml | 30 +
.../isof(Name,'Edm.String') eq true.full.json | 1 +
.../filter/isof(Name,'Edm.String') eq true.xml | 1085 +++++++++++++
.../not endswith(Name,'Chandan').full.json | 1 +
.../filter/not endswith(Name,'Chandan').xml | 1065 +++++++++++++
.../v3/Customer/skiptoken/-1.full.json | 6 +
.../main/resources/v3/Customer/skiptoken/-1.xml | 30 +
.../v3/Customer/skiptoken/-10.full.json | 978 ++++++++++++
.../resources/v3/Customer/skiptoken/-10.xml | 953 ++++++++++++
.../v3/Customer/skiptoken/-3.full.json | 776 ++++++++++
.../main/resources/v3/Customer/skiptoken/-3.xml | 613 ++++++++
.../v3/Customer/skiptoken/-5.full.json | 1444 ++++++++++++++++++
.../main/resources/v3/Customer/skiptoken/-5.xml | 1104 +++++++++++++
.../v3/Customer/skiptoken/-7.full.json | 1296 ++++++++++++++++
.../main/resources/v3/Customer/skiptoken/-7.xml | 990 ++++++++++++
.../v3/Customer/skiptoken/-9.full.json | 715 +++++++++
.../main/resources/v3/Customer/skiptoken/-9.xml | 559 +++++++
.../v3/CustomerInfo/11/entity.full.json | 11 +
.../resources/v3/CustomerInfo/11/entity.xml | 37 +
.../v3/CustomerInfo/12/entity.full.json | 11 +
.../resources/v3/CustomerInfo/12/entity.xml | 37 +
.../v3/EdmBooleanSet/true/entity.full.json | 1 +
.../resources/v3/EdmBooleanSet/true/entity.xml | 36 +
.../v3/EdmByteSet/255/entity.full.json | 1 +
.../main/resources/v3/EdmByteSet/255/entity.xml | 36 +
.../entity.full.json | 1 +
.../79228162514264337593543950335M/entity.xml | 36 +
.../1.7976931348623157E308D/entity.full.json | 1 +
.../1.7976931348623157E308D/entity.xml | 36 +
.../entity.full.json | 1 +
.../entity.xml | 36 +
.../v3/EdmInt16Set/32767/entity.full.json | 1 +
.../resources/v3/EdmInt16Set/32767/entity.xml | 36 +
.../v3/EdmInt32Set/-2147483648/entity.full.json | 1 +
.../v3/EdmInt32Set/-2147483648/entity.xml | 36 +
.../9223372036854775807L/entity.full.json | 1 +
.../EdmInt64Set/9223372036854775807L/entity.xml | 36 +
.../EdmSingleSet/3.4028235E38f/entity.full.json | 1 +
.../v3/EdmSingleSet/3.4028235E38f/entity.xml | 36 +
.../v3/EdmStringSet/'$'/entity.full.json | 1 +
.../resources/v3/EdmStringSet/'$'/entity.xml | 36 +
.../entity.full.json | 1 +
.../entity.xml | 36 +
.../v3/InStreamErrorGetCustomer.full.json | 1 +
.../resources/v3/InStreamErrorGetCustomer.xml | 525 +++++++
.../resources/v3/Login/'3'/entity.full.json | 13 +
fit/src/main/resources/v3/Login/'3'/entity.xml | 42 +
.../resources/v3/Message/1 -10/entity.full.json | 17 +
.../main/resources/v3/Message/1 -10/entity.xml | 46 +
.../resources/v3/Order/-10/entity.full.json | 11 +
fit/src/main/resources/v3/Order/-10/entity.xml | 40 +
.../main/resources/v3/Order/-7/entity.full.json | 17 +
fit/src/main/resources/v3/Order/-7/entity.xml | 43 +
.../main/resources/v3/Order/-9/entity.full.json | 17 +
fit/src/main/resources/v3/Order/-9/entity.xml | 43 +
.../v3/OrderLine/-10 -10/entity.full.json | 14 +
.../resources/v3/OrderLine/-10 -10/entity.xml | 42 +
.../resources/v3/OrderLine/-10 -10/etag.txt | 1 +
.../filter/PersonId sub 2 lt -10.full.json | 1 +
.../v3/Person/filter/PersonId sub 2 lt -10.xml | 79 +
...iaDefaultService.SpecialEmployee').full.json | 1 +
....AstoriaDefaultService.SpecialEmployee').xml | 131 ++
.../resources/v3/Product/-10/entity.full.json | 51 +
.../main/resources/v3/Product/-10/entity.xml | 61 +
fit/src/main/resources/v3/Product/-10/etag.txt | 1 +
.../resources/v3/Product/-6/entity.full.json | 51 +
fit/src/main/resources/v3/Product/-6/entity.xml | 61 +
fit/src/main/resources/v3/Product/-6/etag.txt | 1 +
.../resources/v3/Product/-7/entity.full.json | 51 +
fit/src/main/resources/v3/Product/-7/entity.xml | 61 +
fit/src/main/resources/v3/Product/-7/etag.txt | 1 +
.../v3/Product/-7/links/Photos.full.json | 12 +
.../resources/v3/Product/-9/entity.full.json | 60 +
fit/src/main/resources/v3/Product/-9/entity.xml | 68 +
fit/src/main/resources/v3/Product/-9/etag.txt | 1 +
.../main/resources/v3/Product/feed.full.json | 452 ++++++
fit/src/main/resources/v3/Product/feed.xml | 410 +++++
.../ceiling(Dimensions.Width) eq 7338.full.json | 1 +
.../ceiling(Dimensions.Width) eq 7338.xml | 68 +
...', newname') eq 'kdcuklu, newname'.full.json | 1 +
...tion, ', newname') eq 'kdcuklu, newname'.xml | 74 +
.../floor(Dimensions.Width) eq 7337.full.json | 1 +
.../filter/floor(Dimensions.Width) eq 7337.xml | 68 +
.../indexof(Description, 'k') eq 0.full.json | 1 +
.../filter/indexof(Description, 'k') eq 0.xml | 117 ++
.../filter/length(Description) eq 7.full.json | 1 +
.../Product/filter/length(Description) eq 7.xml | 74 +
.../round(Dimensions.Width) eq 7338.full.json | 1 +
.../filter/round(Dimensions.Width) eq 7338.xml | 68 +
...artswith(Description, 'k') eq true.full.json | 1 +
.../startswith(Description, 'k') eq true.xml | 117 ++
...of('kdcuklu', Description) eq true.full.json | 1 +
...stringof('kdcuklu', Description) eq true.xml | 74 +
.../toupper(Description) eq 'KDCUKLU'.full.json | 1 +
.../toupper(Description) eq 'KDCUKLU'.xml | 74 +
.../v3/ProductPhoto/-2 -2/entity.full.json | 10 +
.../resources/v3/ProductPhoto/-2 -2/entity.xml | 39 +
.../v3/ProductPhoto/-3 -3/entity.full.json | 10 +
.../resources/v3/ProductPhoto/-3 -3/entity.xml | 38 +
fit/src/main/resources/v3/badRequest.json | 17 +
fit/src/main/resources/v3/badRequest.xml | 30 +
fit/src/main/resources/v3/largeMetadata.xml | 42 +
fit/src/main/resources/v3/metadata.xml | 719 +++++++++
fit/src/main/resources/v3/notFound.json | 11 +
fit/src/main/resources/v3/notFound.xml | 25 +
fit/src/main/resources/v3/services.full.json | 102 ++
fit/src/main/resources/v3/services.xml | 98 ++
.../main/resources/v3/unsupportedMediaType.json | 17 +
.../main/resources/v3/unsupportedMediaType.xml | 34 +
fit/src/main/resources/v4/metadata.xml | 519 +++++++
.../main/webapp/WEB-INF/applicationContext.xml | 50 +
fit/src/main/webapp/WEB-INF/web.xml | 75 +
pom.xml | 44 +
211 files changed, 30162 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/pom.xml
----------------------------------------------------------------------
diff --git a/fit/pom.xml b/fit/pom.xml
index 3cd2f74..f4578c2 100644
--- a/fit/pom.xml
+++ b/fit/pom.xml
@@ -24,7 +24,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>olingo-fit-incubating</artifactId>
- <packaging>jar</packaging>
+ <packaging>war</packaging>
<name>${project.artifactId}</name>
<parent>
@@ -33,6 +33,22 @@
<version>0.1.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
+
+ <properties>
+ <main.basedir>${project.parent.basedir}</main.basedir>
+
+ <log.directory>${project.build.directory}/log</log.directory>
+
+ <war.maven.plugin.version>2.4</war.maven.plugin.version>
+
+ <cargo.maven.plugin.version>1.4.7</cargo.maven.plugin.version>
+ <cargo.servlet.port>9080</cargo.servlet.port>
+ <cargo.tomcat.ajp.port>9889</cargo.tomcat.ajp.port>
+ <cargo.rmi.port>9805</cargo.rmi.port>
+ <cargo.log>${log.directory}/cargo.log</cargo.log>
+ <cargo.output>${log.directory}/cargo-output.log</cargo.output>
+ <tomcat.version>7.0.50</tomcat.version>
+ </properties>
<dependencies>
<dependency>
@@ -45,5 +61,156 @@
<artifactId>olingo-client-core-incubating</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <!-- Stax -->
+ <dependency>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ <!-- /Stax -->
+
+ <!-- REST services CXF -->
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+ <!-- /REST services CXF -->
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.esigate</groupId>
+ <artifactId>esigate-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-vfs2</artifactId>
+ </dependency>
</dependencies>
+
+ <build>
+ <defaultGoal>clean package cargo:run</defaultGoal>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>${war.maven.plugin.version}</version>
+ <configuration>
+ <webResources>
+ <!--
+ HACK: Include legal files explicity, otherwise they will end up in the wrong path
+ or in another jar file in the war.
+ -->
+ <resource>
+ <directory>${project.build.outputDirectory}</directory>
+ <includes>
+ <include>META-INF/DEPENDENCIES*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${basedir}/../</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>LICENSE</include>
+ </includes>
+ </resource>
+ </webResources>
+ <packagingExcludes>WEB-INF/classes/esigate.properties,WEB-INF/classes/META-INF/LICENSE*,WEB-INF/classes/META-INF/DEPENDENCIES*</packagingExcludes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-maven2-plugin</artifactId>
+ <version>${cargo.maven.plugin.version}</version>
+ <configuration>
+ <container>
+ <containerId>tomcat7x</containerId>
+ <zipUrlInstaller>
+ <url>http://archive.apache.org/dist/tomcat/tomcat-7/v${tomcat.version}/bin/apache-tomcat-${tomcat.version}.zip</url>
+ <downloadDir>${settings.localRepository}/org/codehaus/cargo/cargo-container-archives</downloadDir>
+ <extractDir>${project.build.directory}/cargo/extract</extractDir>
+ </zipUrlInstaller>
+ <log>${cargo.log}</log>
+ <output>${cargo.output}</output>
+ </container>
+ <configuration>
+ <type>standalone</type>
+ <properties>
+ <cargo.servlet.port>${cargo.servlet.port}</cargo.servlet.port>
+ <cargo.tomcat.ajp.port>${cargo.tomcat.ajp.port}</cargo.tomcat.ajp.port>
+ <cargo.rmi.port>${cargo.rmi.port}</cargo.rmi.port>
+
+ <!--<cargo.jvmargs>-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n</cargo.jvmargs>-->
+ <cargo.jvmargs>-noverify -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:MaxPermSize=256m</cargo.jvmargs>
+ </properties>
+ <files>
+ <file>
+ <file>${project.build.directory}/classes/esigate.properties</file>
+ <todir>lib</todir>
+ </file>
+ </files>
+ <configfiles>
+ <configfile>
+ <file>${project.build.directory}/classes/context.xml</file>
+ <todir>conf/</todir>
+ <tofile>context.xml</tofile>
+ </configfile>
+ <configfile>
+ <file>${project.build.directory}/classes/tomcat-users.xml</file>
+ <todir>conf/</todir>
+ <tofile>tomcat-users.xml</tofile>
+ </configfile>
+ </configfiles>
+ </configuration>
+ <deployables>
+ <deployable>
+ <properties>
+ <context>/</context>
+ </properties>
+ </deployable>
+ </deployables>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>..</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>LICENSE</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
new file mode 100644
index 0000000..ec13050
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java
@@ -0,0 +1,776 @@
+/*
+ * 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.olingo.fit;
+
+import org.apache.olingo.fit.utils.Accept;
+import org.apache.olingo.fit.utils.XMLUtilities;
+import org.apache.olingo.fit.utils.JSONUtilities;
+import org.apache.olingo.fit.utils.ODataVersion;
+import org.apache.olingo.fit.utils.FSManager;
+
+import static org.apache.olingo.fit.utils.Constants.*;
+
+import org.apache.olingo.fit.methods.MERGE;
+import org.apache.olingo.fit.methods.PATCH;
+import org.apache.olingo.fit.utils.AbstractUtilities;
+import org.apache.olingo.fit.utils.Commons;
+import org.apache.olingo.fit.utils.LinkInfo;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractServices {
+
+ /**
+ * Logger.
+ */
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractServices.class);
+
+ protected abstract ODataVersion getVersion();
+ protected final XMLUtilities xml;
+
+ protected final JSONUtilities json;
+
+ public AbstractServices() throws Exception {
+ this.xml = new XMLUtilities(getVersion());
+ this.json = new JSONUtilities(getVersion());
+ }
+
+ /**
+ * Provide sample services.
+ *
+ * @param accept Accept header.
+ * @return OData services.
+ */
+ @GET
+ public Response getSevices(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept) {
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion());
+
+ if (acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ return xml.createResponse(
+ FSManager.instance(getVersion()).readFile(SERVICES, acceptType), null, acceptType);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Provide sample metadata.
+ *
+ * @return metadata.
+ */
+ @GET
+ @Path("/$metadata")
+ @Produces("application/xml")
+ public Response getMetadata() {
+ return getMetadata(METADATA);
+ }
+
+ /**
+ * Provide sample lartge metadata.
+ *
+ * @return metadata.
+ */
+ @GET
+ @Path("/large/$metadata")
+ @Produces("application/xml")
+ public Response getLargeMetadata() {
+ return getMetadata("large" + StringUtils.capitalize(METADATA));
+ }
+
+ private Response getMetadata(final String filename) {
+ try {
+ return xml.
+ createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML);
+ } catch (Exception e) {
+ return xml.createFaultResponse(Accept.XML.toString(), e);
+ }
+ }
+
+ @MERGE
+ @Path("/{entitySetName}({entityId})")
+ @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ @Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ public Response mergeEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) String ifMatch,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ final String changes) {
+
+ return patchEntity(accept, prefer, ifMatch, entitySetName, entityId, changes);
+ }
+
+ @PATCH
+ @Path("/{entitySetName}({entityId})")
+ @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ @Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ public Response patchEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) String ifMatch,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ final String changes) {
+
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion());
+
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final AbstractUtilities util = acceptType == Accept.ATOM ? xml : json;
+ InputStream res =
+ util.patchEntity(entitySetName, entityId, IOUtils.toInputStream(changes), acceptType, ifMatch);
+
+ final Response response;
+ if ("return-content".equalsIgnoreCase(prefer)) {
+ response = xml.createResponse(res, null, acceptType, Response.Status.OK);
+ } else {
+ res.close();
+ response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ }
+
+ if (StringUtils.isNotBlank(prefer)) {
+ response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
+ }
+
+ return response;
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @PUT
+ @Path("/{entitySetName}({entityId})")
+ @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ @Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ public Response putNewEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ final String entity) {
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion());
+
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ InputStream res;
+ if (acceptType == Accept.ATOM) {
+ res = xml.addOrReplaceEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
+ } else {
+ res = json.addOrReplaceEntity(entityId, entitySetName, IOUtils.toInputStream(entity));
+ }
+
+ final Response response;
+ if ("return-content".equalsIgnoreCase(prefer)) {
+ response = xml.createResponse(res, null, acceptType, Response.Status.OK);
+ } else {
+ res.close();
+ response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ }
+
+ if (StringUtils.isNotBlank(prefer)) {
+ response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
+ }
+
+ return response;
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @POST
+ @Path("/{entitySetName}")
+ @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ @Consumes({MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
+ public Response postNewEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) String prefer,
+ @PathParam("entitySetName") String entitySetName,
+ final String entity) {
+
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion());
+
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final InputStream res;
+ if (acceptType == Accept.ATOM) {
+ res = xml.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
+ } else {
+ res = json.addOrReplaceEntity(entitySetName, IOUtils.toInputStream(entity));
+ }
+
+ final Response response;
+ if ("return-no-content".equalsIgnoreCase(prefer)) {
+ res.close();
+ response = xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT);
+ } else {
+ response = xml.createResponse(res, null, acceptType, Response.Status.CREATED);
+ }
+
+ if (StringUtils.isNotBlank(prefer)) {
+ response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer));
+ }
+
+ return response;
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Retrieve entity set or function execution sample.
+ *
+ * @param accept Accept header.
+ * @param name entity set or function name.
+ * @param format format query option.
+ * @param inlinecount inlinecount query option.
+ * @param filter filter query option.
+ * @param orderby orderby query option.
+ * @param skiptoken skiptoken query option.
+ * @return entity set or function result.
+ */
+ @GET
+ @Path("/{name}")
+ public Response getEntitySet(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("name") String name,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ @QueryParam("$inlinecount") @DefaultValue(StringUtils.EMPTY) String inlinecount,
+ @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) String filter,
+ @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) String orderby,
+ @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) String skiptoken) {
+
+ try {
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ try {
+ // search for function ...
+ final InputStream func = FSManager.instance(getVersion()).readFile(name, acceptType);
+ return xml.createResponse(func, null, acceptType);
+ } catch (NotFoundException e) {
+ // search for entitySet ...
+ final String basePath = name + File.separatorChar;
+
+ final StringBuilder builder = new StringBuilder();
+ builder.append(basePath);
+
+ if (StringUtils.isNotBlank(orderby)) {
+ builder.append(ORDERBY).append(File.separatorChar).append(orderby).append(File.separatorChar);
+ }
+
+ if (StringUtils.isNotBlank(filter)) {
+ builder.append(FILTER).append(File.separatorChar).append(filter.replaceAll("/", "."));
+ } else if (StringUtils.isNotBlank(skiptoken)) {
+ builder.append(SKIP_TOKEN).append(File.separatorChar).append(skiptoken);
+ } else {
+ builder.append(FEED);
+ }
+
+ InputStream feed = FSManager.instance(getVersion()).readFile(builder.toString(), acceptType);
+ if ("allpages".equals(inlinecount)) {
+ int count = xml.countAllElements(name);
+ feed.close();
+ if (acceptType == Accept.ATOM) {
+ feed = xml.addAtomInlinecount(
+ FSManager.instance(getVersion()).readFile(builder.toString(), acceptType),
+ count,
+ acceptType);
+ } else {
+ feed = json.addJsonInlinecount(
+ FSManager.instance(getVersion()).readFile(builder.toString(), acceptType),
+ count,
+ acceptType);
+ }
+ }
+
+ return xml.createResponse(feed, Commons.getETag(basePath, getVersion()), acceptType);
+ }
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Retrieve entity sample.
+ *
+ * @param accept Accept header.
+ * @param entitySetName Entity set name.
+ * @param entityId entity id.
+ * @param format format query option.
+ * @param expand expand query option.
+ * @param select select query option.
+ * @return entity.
+ */
+ @GET
+ @Path("/{entitySetName}({entityId})")
+ public Response getEntity(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
+ @QueryParam("$expand") @DefaultValue(StringUtils.EMPTY) String expand,
+ @QueryParam("$select") @DefaultValue(StringUtils.EMPTY) String select) {
+
+ try {
+
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ final Map.Entry<String, InputStream> entityInfo = xml.readEntity(entitySetName, entityId, acceptType);
+
+ InputStream entity = entityInfo.getValue();
+
+ if (StringUtils.isNotBlank(select)) {
+ if (acceptType == Accept.ATOM) {
+ entity = xml.selectEntity(entity, select.split(","));
+ } else {
+ entity = json.selectEntity(entity, select.split(","));
+ }
+ }
+
+ if (StringUtils.isNotBlank(expand)) {
+ if (acceptType == Accept.XML || acceptType == Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ } else if (acceptType == Accept.ATOM) {
+ for (String exp : expand.split(",")) {
+ entity = xml.expandEntity(
+ entitySetName,
+ entityId,
+ entity,
+ exp);
+ }
+ } else {
+ for (String exp : expand.split(",")) {
+ entity = json.expandEntity(
+ entitySetName,
+ entityId,
+ entity,
+ exp);
+ }
+ }
+ }
+
+ return xml.createResponse(entity, Commons.getETag(entityInfo.getKey(), getVersion()), acceptType);
+ } catch (Exception e) {
+ LOG.error("Error retrieving entity", e);
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @DELETE
+ @Path("/{entitySetName}({entityId})")
+ public Response removeEntity(
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId) {
+
+ try {
+ final String basePath =
+ entitySetName + File.separatorChar + Commons.getEntityKey(entityId) + File.separatorChar;
+
+ FSManager.instance(getVersion()).deleteFile(basePath + ENTITY);
+
+ return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
+ } catch (Exception e) {
+ return xml.createFaultResponse(Accept.XML.toString(), e);
+ }
+ }
+
+ /**
+ * Retrieve property sample.
+ *
+ * @param accept Accept header.
+ * @param entitySetName Entity set name.
+ * @param entityId entity id.
+ * @param path path.
+ * @param format format query option.
+ * @return property.
+ */
+ @GET
+ @Path("/{entitySetName}({entityId})/{path:.*}")
+ public Response getPath(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("path") String path,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+
+ try {
+ boolean searchForValue = path.endsWith("$value");
+ Accept acceptType = null;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else if (StringUtils.isNotBlank(accept)) {
+ acceptType = Accept.parse(accept, getVersion(), null);
+ }
+
+ final String basePath =
+ entitySetName + File.separatorChar + Commons.getEntityKey(entityId) + File.separatorChar;
+
+ InputStream stream;
+
+ try {
+ final LinkInfo linkInfo = xml.readLinks(entitySetName, entityId, path, Accept.XML);
+ final Map.Entry<String, List<String>> links = XMLUtilities.extractLinkURIs(linkInfo.getLinks());
+
+ switch (acceptType) {
+ case JSON:
+ case JSON_FULLMETA:
+ case JSON_NOMETA:
+ stream = json.readEntities(links.getValue(), path, links.getKey(), linkInfo.isFeed());
+ stream = json.wrapJsonEntities(stream);
+ break;
+ default:
+ stream = xml.readEntities(links.getValue(), path, links.getKey(), linkInfo.isFeed());
+ }
+ } catch (NotFoundException e) {
+ // if the given path is not about any link then search for property
+ LOG.info("Retrieve property {}", path);
+
+ stream = FSManager.instance(getVersion()).readFile(
+ basePath + ENTITY, acceptType == null || acceptType == Accept.TEXT
+ ? Accept.XML : acceptType);
+
+ if (searchForValue) {
+ stream = xml.getAtomPropertyValue(stream, path.split("/"));
+ } else {
+ if (acceptType == null || acceptType == Accept.XML || acceptType == Accept.ATOM) {
+ // retrieve xml
+ stream = xml.getAtomProperty(stream, path.split("/"));
+ } else {
+ // retrieve Edm type from xml
+ final String edmType = xml.getEdmTypeFromXML(
+ FSManager.instance(getVersion()).readFile(basePath + ENTITY, Accept.XML),
+ path.split("/"));
+ // retrieve json property
+ stream = json.getJsonProperty(stream, path.split("/"), edmType);
+ }
+ }
+
+ if ((searchForValue && acceptType != null && acceptType != Accept.TEXT) || acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type " + acceptType);
+ }
+ }
+
+ return xml.createResponse(stream, Commons.getETag(basePath, getVersion()), acceptType);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Retrieve links sample.
+ *
+ * @param accept Accept header.
+ * @param entitySetName Entity set name.
+ * @param entityId entity id.
+ * @param linkName link name.
+ * @param format format query option.
+ * @return links.
+ */
+ @GET
+ @Path("/{entitySetName}({entityId})/$links/{linkName}")
+ public Response getLinks(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ try {
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ if (acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final LinkInfo links = xml.readLinks(entitySetName, entityId, linkName, acceptType);
+
+ return xml.createResponse(
+ links.getLinks(),
+ links.getEtag(),
+ acceptType);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @POST
+ @Path("/{entitySetName}({entityId})/$links/{linkName}")
+ public Response postLink(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ String link,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ try {
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ if (acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final Accept content;
+ if (StringUtils.isNotBlank(contentType)) {
+ content = Accept.parse(contentType, getVersion());
+ } else {
+ content = acceptType;
+ }
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final List<String> links;
+ if (content == Accept.XML || content == Accept.TEXT || content == Accept.ATOM) {
+ links = XMLUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ } else {
+ links = JSONUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ }
+
+ utils.putLinksInMemory(
+ Commons.getEntityBasePath(entitySetName, entityId),
+ entitySetName,
+ entityId,
+ linkName,
+ links);
+
+ return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @MERGE
+ @Path("/{entitySetName}({entityId})/$links/{linkName}")
+ public Response mergeLink(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ String link,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ return putLink(accept, contentType, entitySetName, entityId, linkName, link, format);
+ }
+
+ @PATCH
+ @Path("/{entitySetName}({entityId})/$links/{linkName}")
+ public Response patchLink(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ String link,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ return putLink(accept, contentType, entitySetName, entityId, linkName, link, format);
+ }
+
+ @PUT
+ @Path("/{entitySetName}({entityId})/$links/{linkName}")
+ public Response putLink(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ String link,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ try {
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ if (acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final Accept content;
+ if (StringUtils.isNotBlank(contentType)) {
+ content = Accept.parse(contentType, getVersion());
+ } else {
+ content = acceptType;
+ }
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final List<String> links;
+ if (content == Accept.XML || content == Accept.TEXT || content == Accept.ATOM) {
+ links = XMLUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ } else {
+ links = JSONUtilities.extractLinkURIs(IOUtils.toInputStream(link)).getValue();
+ }
+
+ utils.putLinksInMemory(
+ Commons.getEntityBasePath(entitySetName, entityId),
+ entitySetName,
+ linkName,
+ links);
+
+ return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ @DELETE
+ @Path("/{entitySetName}({entityId})/$links/{linkName}({linkId})")
+ public Response deleteLink(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) String contentType,
+ @PathParam("entitySetName") String entitySetName,
+ @PathParam("entityId") String entityId,
+ @PathParam("linkName") String linkName,
+ @PathParam("linkId") String linkId,
+ @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
+ try {
+ final Accept acceptType;
+ if (StringUtils.isNotBlank(format)) {
+ acceptType = Accept.valueOf(format.toUpperCase());
+ } else {
+ acceptType = Accept.parse(accept, getVersion());
+ }
+
+ if (acceptType == Accept.ATOM) {
+ throw new UnsupportedMediaTypeException("Unsupported media type");
+ }
+
+ final AbstractUtilities utils = getUtilities(acceptType);
+
+ final Map.Entry<String, List<String>> currents = JSONUtilities.extractLinkURIs(utils.readLinks(
+ entitySetName, entityId, linkName, Accept.JSON_FULLMETA).getLinks());
+
+ final Map.Entry<String, List<String>> toBeRemoved = JSONUtilities.extractLinkURIs(utils.readLinks(
+ entitySetName, entityId, linkName + "(" + linkId + ")", Accept.JSON_FULLMETA).getLinks());
+
+ final List<String> remains = currents.getValue();
+ remains.removeAll(toBeRemoved.getValue());
+
+ utils.putLinksInMemory(
+ Commons.getEntityBasePath(entitySetName, entityId),
+ entitySetName,
+ linkName,
+ remains);
+
+ return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ /**
+ * Count sample.
+ *
+ * @param accept Accept header.
+ * @param entitySetName entity set name.
+ * @return count.
+ */
+ @GET
+ @Path("/{entitySetName}/$count")
+ public Response count(
+ @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
+ @PathParam("entitySetName") String entitySetName) {
+ try {
+ final Accept acceptType = Accept.parse(accept, getVersion(), Accept.TEXT);
+
+ if (acceptType != Accept.TEXT) {
+ throw new UnsupportedMediaTypeException("Unsupported type " + accept);
+ }
+
+ int count = xml.countAllElements(entitySetName);
+
+ final Response.ResponseBuilder builder = Response.ok();
+ builder.entity(count);
+
+ return builder.build();
+ } catch (Exception e) {
+ return xml.createFaultResponse(accept, e);
+ }
+ }
+
+ private AbstractUtilities getUtilities(final Accept accept) {
+ final AbstractUtilities utils;
+ if (accept == Accept.XML || accept == Accept.TEXT || accept == Accept.ATOM) {
+ utils = xml;
+ } else {
+ utils = json;
+ }
+
+ return utils;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/UnsupportedMediaTypeException.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/UnsupportedMediaTypeException.java b/fit/src/main/java/org/apache/olingo/fit/UnsupportedMediaTypeException.java
new file mode 100644
index 0000000..ad7e4b4
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/UnsupportedMediaTypeException.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.olingo.fit;
+
+public class UnsupportedMediaTypeException extends RuntimeException {
+
+ private static final long serialVersionUID = 9076398602010056960L;
+
+ /**
+ * Creates a new instance of
+ * <code>UnsupportedMediaTypeException</code> without detail message.
+ */
+ public UnsupportedMediaTypeException() {
+ }
+
+ /**
+ * Constructs an instance of
+ * <code>UnsupportedMediaTypeException</code> with the specified detail message.
+ *
+ * @param msg the detail message.
+ */
+ public UnsupportedMediaTypeException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/V3Services.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/V3Services.java b/fit/src/main/java/org/apache/olingo/fit/V3Services.java
new file mode 100644
index 0000000..7b4ca56
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/V3Services.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.olingo.fit;
+
+import org.apache.olingo.fit.utils.ODataVersion;
+import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
+import javax.ws.rs.Path;
+import org.apache.cxf.interceptor.InInterceptors;
+
+@Path("/V3/Static.svc")
+@InInterceptors(classes = XHTTPMethodInterceptor.class)
+public class V3Services extends AbstractServices {
+
+ public V3Services() throws Exception {
+ super();
+ }
+
+ @Override
+ protected ODataVersion getVersion() {
+ return ODataVersion.v3;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/V4Services.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/V4Services.java b/fit/src/main/java/org/apache/olingo/fit/V4Services.java
new file mode 100644
index 0000000..8906c63
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/V4Services.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.olingo.fit;
+
+import org.apache.olingo.fit.utils.ODataVersion;
+import org.apache.olingo.fit.utils.XHTTPMethodInterceptor;
+import javax.ws.rs.Path;
+import org.apache.cxf.interceptor.InInterceptors;
+
+@Path("/V4/Static.svc")
+@InInterceptors(classes = XHTTPMethodInterceptor.class)
+public class V4Services extends AbstractServices {
+
+ public V4Services() throws Exception {
+ super();
+ }
+
+ @Override
+ protected ODataVersion getVersion() {
+ return ODataVersion.v4;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/methods/MERGE.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/methods/MERGE.java b/fit/src/main/java/org/apache/olingo/fit/methods/MERGE.java
new file mode 100644
index 0000000..2966c11
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/methods/MERGE.java
@@ -0,0 +1,31 @@
+/*
+ * 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.olingo.fit.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.ws.rs.HttpMethod;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("MERGE")
+public @interface MERGE {
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/methods/PATCH.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/methods/PATCH.java b/fit/src/main/java/org/apache/olingo/fit/methods/PATCH.java
new file mode 100644
index 0000000..6fd07b8
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/methods/PATCH.java
@@ -0,0 +1,31 @@
+/*
+ * 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.olingo.fit.methods;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.ws.rs.HttpMethod;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("PATCH")
+public @interface PATCH {
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewrite.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewrite.java b/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewrite.java
new file mode 100644
index 0000000..082708f
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewrite.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.olingo.fit.rproxy;
+
+import java.util.Properties;
+import org.esigate.Driver;
+import org.esigate.DriverConfiguration;
+import org.esigate.events.Event;
+import org.esigate.events.EventDefinition;
+import org.esigate.events.EventManager;
+import org.esigate.events.IEventListener;
+import org.esigate.events.impl.RenderEvent;
+import org.esigate.extension.Extension;
+import org.esigate.util.HttpRequestHelper;
+
+public class LinkRewrite implements Extension, IEventListener {
+
+ private DriverConfiguration config;
+
+ @Override
+ public void init(final Driver driver, final Properties properties) {
+ this.config = driver.getConfiguration();
+ driver.getEventManager().register(EventManager.EVENT_RENDER_PRE, this);
+ }
+
+ @Override
+ public boolean event(final EventDefinition eventDef, final Event event) {
+ final RenderEvent renderEvent = (RenderEvent) event;
+ final String baseUrl = HttpRequestHelper.getBaseUrl(renderEvent.originalRequest).toString();
+ final LinkRewriteRenderer fixup = new LinkRewriteRenderer(baseUrl, config.getVisibleBaseURL(baseUrl));
+
+ // Add fixup renderer as first renderer.
+ renderEvent.renderers.add(0, fixup);
+
+ // Continue processing
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/70f06578/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewriteRenderer.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewriteRenderer.java b/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewriteRenderer.java
new file mode 100644
index 0000000..f3447ac
--- /dev/null
+++ b/fit/src/main/java/org/apache/olingo/fit/rproxy/LinkRewriteRenderer.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.olingo.fit.rproxy;
+
+import java.io.IOException;
+import java.io.Writer;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.esigate.Renderer;
+
+public class LinkRewriteRenderer implements Renderer {
+
+ private static final char SLASH = '/';
+
+ private String baseUrl;
+
+ private String replacementUrl;
+
+ public LinkRewriteRenderer(final String baseUrl, final String visibleBaseUrl) {
+ if (visibleBaseUrl == null || visibleBaseUrl.isEmpty()) {
+ throw new IllegalArgumentException("Need to specify baseUrl and visibleBaseUrl");
+ }
+
+ this.baseUrl = removeLeadingSlash(baseUrl);
+ this.replacementUrl = removeLeadingSlash(visibleBaseUrl);
+ }
+
+ private String removeLeadingSlash(final String src) {
+ final int lastCharPosition = src.length() - 1;
+ return src.charAt(lastCharPosition) == SLASH
+ ? src.substring(0, lastCharPosition)
+ : src;
+ }
+
+ @Override
+ public void render(final HttpEntityEnclosingRequest httpRequest, final String src, final Writer out)
+ throws IOException {
+
+ out.write(src.replaceAll(baseUrl, replacementUrl));
+ }
+}