You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2009/06/23 23:54:09 UTC
svn commit: r787849 - in /cxf/trunk:
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/
rt/frontend/jaxrs/src/test/java/org...
Author: sergeyb
Date: Tue Jun 23 21:54:08 2009
New Revision: 787849
URL: http://svn.apache.org/viewvc?rev=787849&view=rev
Log:
JAXRS : support for overriding HTTP methods
Added:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java (with props)
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java (with props)
Removed:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/SystemQueryHandler.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/SystemQueryHandlerTest.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java?rev=787849&r1=787848&r2=787849&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java Tue Jun 23 21:54:08 2009
@@ -20,9 +20,12 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.apache.cxf.jaxrs.utils.HttpUtils;
@@ -30,9 +33,27 @@
public class RequestPreprocessor {
+ private static final String ACCEPT_QUERY = "_type";
+ private static final String METHOD_QUERY = "_method";
+ private static final String METHOD_HEADER = "X-HTTP-Method-Override";
+
+
+ private static final Map<String, String> SHORTCUTS;
+ static {
+ SHORTCUTS = new HashMap<String, String>();
+ SHORTCUTS.put("json", "application/json");
+ SHORTCUTS.put("text", "text/*");
+ SHORTCUTS.put("xml", "application/xml");
+ // more to come
+ }
+
private Map<Object, Object> languageMappings;
private Map<Object, Object> extensionMappings;
+ public RequestPreprocessor() {
+ this(null, null);
+ }
+
public RequestPreprocessor(Map<Object, Object> languageMappings,
Map<Object, Object> extensionMappings) {
this.languageMappings =
@@ -44,6 +65,10 @@
public String preprocess(Message m, UriInfo u) {
handleExtensionMappings(m, u);
handleLanguageMappings(m, u);
+
+ MultivaluedMap<String, String> queries = u.getQueryParameters();
+ handleTypeQuery(m, queries);
+ handleMethod(m, queries, new HttpHeadersImpl(m));
return new UriInfoImpl(m, null).getPath();
}
@@ -70,27 +95,54 @@
}
- private void updateAcceptTypeHeader(Message m, String anotherValue) {
- m.put(Message.ACCEPT_CONTENT_TYPE, anotherValue);
- }
-
@SuppressWarnings("unchecked")
private void updateAcceptLanguageHeader(Message m, String anotherValue) {
List<String> acceptLanguage =
- ((Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS)).get("Accept-Language");
+ ((Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS)).get(HttpHeaders.ACCEPT_LANGUAGE);
if (acceptLanguage == null) {
acceptLanguage = new ArrayList<String>();
}
acceptLanguage.add(anotherValue);
((Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS))
- .put("Accept-Language", acceptLanguage);
+ .put(HttpHeaders.ACCEPT_LANGUAGE, acceptLanguage);
}
private void updatePath(Message m, String path, String suffix) {
String newPath = path.substring(0, path.length() - (suffix.length() + 1));
HttpUtils.updatePath(m, newPath);
- //m.put(Message.REQUEST_URI, newPath);
+ }
+
+ private void handleMethod(Message m,
+ MultivaluedMap<String, String> queries,
+ HttpHeaders headers) {
+ String method = queries.getFirst(METHOD_QUERY);
+ if (method == null) {
+ List<String> values = headers.getRequestHeader(METHOD_HEADER);
+ if (values.size() == 1) {
+ method = values.get(0);
+ }
+ }
+ if (method != null) {
+ m.put(Message.HTTP_REQUEST_METHOD, method);
+ }
+ }
+
+ private void handleTypeQuery(Message m, MultivaluedMap<String, String> queries) {
+ String type = queries.getFirst(ACCEPT_QUERY);
+ if (type != null) {
+ if (SHORTCUTS.containsKey(type)) {
+ type = SHORTCUTS.get(type);
+ }
+ updateAcceptTypeHeader(m, type);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateAcceptTypeHeader(Message m, String acceptValue) {
+ m.put(Message.ACCEPT_CONTENT_TYPE, acceptValue);
+ ((Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS))
+ .put(HttpHeaders.ACCEPT, Collections.singletonList(acceptValue));
}
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=787849&r1=787848&r2=787849&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java Tue Jun 23 21:54:08 2009
@@ -42,7 +42,6 @@
import org.apache.cxf.jaxrs.ext.ParameterHandler;
import org.apache.cxf.jaxrs.ext.RequestHandler;
import org.apache.cxf.jaxrs.ext.ResponseHandler;
-import org.apache.cxf.jaxrs.ext.SystemQueryHandler;
import org.apache.cxf.jaxrs.impl.RequestPreprocessor;
import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper;
import org.apache.cxf.jaxrs.model.ProviderInfo;
@@ -78,7 +77,6 @@
new PrimitiveTextProvider(),
new MultipartProvider(),
new WebApplicationExceptionMapper(),
- new SystemQueryHandler(),
new WadlGenerator());
}
Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java?rev=787849&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java Tue Jun 23 21:54:08 2009
@@ -0,0 +1,110 @@
+/**
+ * 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.cxf.jaxrs.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.servlet.ServletDestination;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+
+
+public class RequestPreprocessorTest extends Assert {
+
+ private IMocksControl control;
+
+ @Before
+ public void setUp() {
+ control = EasyMock.createNiceControl();
+ control.makeThreadSafe(true);
+ }
+
+ @Test
+ public void testMethodQuery() {
+ Message m = mockMessage("http://localhost:8080", "/bar", "_method=GET", "POST");
+ RequestPreprocessor sqh = new RequestPreprocessor();
+ sqh.preprocess(m, new UriInfoImpl(m, null));
+ assertEquals("GET", m.get(Message.HTTP_REQUEST_METHOD));
+ }
+
+ @Test
+ public void testMethodOverride() {
+ Message m = mockMessage("http://localhost:8080", "/bar", "bar", "POST", "GET");
+ RequestPreprocessor sqh = new RequestPreprocessor();
+ sqh.preprocess(m, new UriInfoImpl(m, null));
+ assertEquals("GET", m.get(Message.HTTP_REQUEST_METHOD));
+ }
+
+ @Test
+ public void testTypeQuery() {
+ Message m = mockMessage("http://localhost:8080", "/bar", "_type=xml", "POST");
+ RequestPreprocessor sqh = new RequestPreprocessor();
+ sqh.preprocess(m, new UriInfoImpl(m, null));
+ assertEquals("POST", m.get(Message.HTTP_REQUEST_METHOD));
+ assertEquals("application/xml", m.get(Message.ACCEPT_CONTENT_TYPE));
+ }
+
+ private Message mockMessage(String baseAddress,
+ String pathInfo,
+ String query,
+ String method) {
+ return mockMessage(baseAddress, pathInfo, query, method, null);
+ }
+
+ private Message mockMessage(String baseAddress,
+ String pathInfo,
+ String query,
+ String method,
+ String methodHeader) {
+ Message m = new MessageImpl();
+ control.reset();
+ Exchange e = control.createMock(Exchange.class);
+ m.setExchange(e);
+ ServletDestination d = control.createMock(ServletDestination.class);
+ e.getDestination();
+ EasyMock.expectLastCall().andReturn(d).anyTimes();
+ EndpointInfo epr = new EndpointInfo();
+ epr.setAddress(baseAddress);
+ d.getEndpointInfo();
+ EasyMock.expectLastCall().andReturn(epr).anyTimes();
+ m.put(Message.REQUEST_URI, pathInfo);
+ m.put(Message.QUERY_STRING, query);
+ m.put(Message.HTTP_REQUEST_METHOD, method);
+ Map<String, List<String>> headers = new HashMap<String, List<String>>();
+ if (methodHeader != null) {
+ headers.put("X-HTTP-Method-Override", Collections.singletonList(methodHeader));
+ }
+ m.put(Message.PROTOCOL_HEADERS, headers);
+ control.replay();
+ return m;
+ }
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/RequestPreprocessorTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java?rev=787849&r1=787848&r2=787849&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java Tue Jun 23 21:54:08 2009
@@ -127,6 +127,13 @@
return b;
}
+ @RETRIEVE
+ @Path("books/aegis/retrieve")
+ @Produces({"application/html;q=1.0", "application/xml;q=0.5", "application/json;q=0.5" })
+ public Book getBookAegisRetrieve() {
+ return getBookAegis();
+ }
+
@GET
@Path("books/xslt/{id}")
@Produces({"text/html", "application/xhtml+xml", "application/xml" })
Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java?rev=787849&r1=787848&r2=787849&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java Tue Jun 23 21:54:08 2009
@@ -31,6 +31,7 @@
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.FileRequestEntity;
+import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.cxf.helpers.IOUtils;
@@ -61,6 +62,21 @@
}
@Test
+ public void testGetBookXSLTHtml() throws Exception {
+
+ String endpointAddress =
+ "http://localhost:9080/the/thebooks5/bookstore/books/xslt";
+ WebClient wc = WebClient.create(endpointAddress);
+ wc.accept("application/xhtml+xml").path(666).matrix("name2", 2).query("name", "Action - ");
+ XMLSource source = wc.get(XMLSource.class);
+ Map<String, String> namespaces = new HashMap<String, String>();
+ namespaces.put("xhtml", "http://www.w3.org/1999/xhtml");
+ Book2 b = source.getNode("xhtml:html/xhtml:body/xhtml:ul/xhtml:Book", namespaces, Book2.class);
+ assertEquals(666, b.getId());
+ assertEquals("CXF in Action - 2", b.getName());
+ }
+
+ @Test
public void testGetBookByUriInfo2() throws Exception {
String endpointAddress =
"http://localhost:9080/the/thebooks3/bookstore/bookinfo?"
@@ -122,10 +138,18 @@
}
private void getBook(String endpointAddress, String resource, String type) throws Exception {
+ getBook(endpointAddress, resource, type, null);
+ }
+
+ private void getBook(String endpointAddress, String resource, String type, String mHeader)
+ throws Exception {
URL url = new URL(endpointAddress);
URLConnection connect = url.openConnection();
connect.addRequestProperty("Content-Type", "*/*");
connect.addRequestProperty("Accept", type);
+ if (mHeader != null) {
+ connect.addRequestProperty("X-HTTP-Method-Override", mHeader);
+ }
InputStream in = connect.getInputStream();
InputStream expected = getClass().getResourceAsStream(resource);
@@ -192,6 +216,39 @@
}
@Test
+ public void testRetrieveBookAegis1() throws Exception {
+
+ String endpointAddress =
+ "http://localhost:9080/the/thebooks4/bookstore/books/aegis/retrieve?_method=RETRIEVE";
+ getBook(endpointAddress, "resources/expected_add_book_aegis.txt", "application/xml");
+ }
+
+ @Test
+ public void testRetrieveBookAegis2() throws Exception {
+
+ String endpointAddress =
+ "http://localhost:9080/the/thebooks4/bookstore/books/aegis/retrieve";
+ getBook(endpointAddress, "resources/expected_add_book_aegis.txt", "application/xml", "RETRIEVE");
+ }
+
+ @Test
+ @Ignore
+ public void testRetrieveBookAegis3() throws Exception {
+ GetMethod get = new GetMethod("http://localhost:9080/the/thebooks4/bookstore/books/aegis/retrieve");
+ get.setRequestHeader("Content-Type", "*/*");
+ get.setRequestHeader("Accept", "application/xml");
+ HttpClient httpClient = new HttpClient();
+ try {
+ httpClient.executeMethod(get);
+ String aegisData = getStringFromInputStream(get.getResponseBodyAsStream());
+ InputStream expected = getClass().getResourceAsStream("resources/expected_add_book_aegis.txt");
+ assertEquals(getStringFromInputStream(expected), aegisData);
+ } finally {
+ get.releaseConnection();
+ }
+ }
+
+ @Test
public void testGetBookUserResource() throws Exception {
String endpointAddress =
@@ -270,21 +327,6 @@
}
@Test
- public void testGetBookXSLTHtml() throws Exception {
-
- String endpointAddress =
- "http://localhost:9080/the/thebooks5/bookstore/books/xslt";
- WebClient wc = WebClient.create(endpointAddress);
- wc.accept("application/xhtml+xml").path(666).matrix("name2", 2).query("name", "Action - ");
- XMLSource source = wc.get(XMLSource.class);
- Map<String, String> namespaces = new HashMap<String, String>();
- namespaces.put("xhtml", "http://www.w3.org/1999/xhtml");
- Book2 b = source.getNode("xhtml:html/xhtml:body/xhtml:ul/xhtml:Book", namespaces, Book2.class);
- assertEquals(666, b.getId());
- assertEquals("CXF in Action - 2", b.getName());
- }
-
- @Test
public void testAddValidBookJson() throws Exception {
doPost("http://localhost:9080/the/bookstore/books/convert",
200,
@@ -340,6 +382,7 @@
return bos.getOut().toString();
}
+
@Ignore
@XmlRootElement(name = "Book", namespace = "http://www.w3.org/1999/xhtml")
public static class Book2 {
Added: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java?rev=787849&view=auto
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java (added)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java Tue Jun 23 21:54:08 2009
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs;
+
+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("RETRIEVE")
+public @interface RETRIEVE {
+
+}
Propchange: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/RETRIEVE.java
------------------------------------------------------------------------------
svn:keywords = Rev Date