Author: sergeyb
Date: Wed Apr 29 10:55:04 2009
New Revision: 769741
URL: http://svn.apache.org/viewvc?rev=769741&view=rev
Log:
JAXRS: Implementing ResponseBuilder.variants() plus various minor updates
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/VariantListBuilderImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MetadataMapTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProviderTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImplTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
Wed Apr 29 10:55:04 2009
@@ -42,12 +42,12 @@
this(store, false, false);
}
+ public MetadataMap(boolean readOnly, boolean caseInsensitive) {
+ this(null, readOnly, caseInsensitive);
+ }
+
public MetadataMap(Map<K, List<V>> store, boolean readOnly, boolean
caseInsensitive) {
- if (!readOnly && caseInsensitive) {
- throw new IllegalArgumentException(
- "Case-insensitive keys are only supported for read-only maps
at the moment");
- }
this.caseInsensitive = caseInsensitive;
this.m = new LinkedHashMap<K, List<V>>();
@@ -65,7 +65,7 @@
}
public void add(K key, V value) {
- List<V> data = m.get(key);
+ List<V> data = this.get(key);
if (data == null) {
data = new ArrayList<V>();
m.put(key, data);
@@ -74,14 +74,14 @@
}
public V getFirst(K key) {
- List<V> data = get(key);
+ List<V> data = this.get(key);
return data == null ? null : data.get(0);
}
public void putSingle(K key, V value) {
List<V> data = new ArrayList<V>();
data.add(value);
- m.put(key, data);
+ this.put(key, data);
}
public void clear() {
@@ -162,4 +162,5 @@
return m.toString();
}
+
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProvider.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProvider.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProvider.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProvider.java
Wed Apr 29 10:55:04 2009
@@ -19,7 +19,6 @@
package org.apache.cxf.jaxrs.impl;
-import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
@@ -95,9 +94,7 @@
if (value.isSecure()) {
sb.append(';').append(SECURE);
}
- if (value.getVersion() != Cookie.DEFAULT_VERSION) {
- sb.append(';').append(VERSION).append('=').append(1);
- }
+ sb.append(';').append(VERSION).append('=').append(value.getVersion());
return sb.toString();
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImpl.java
Wed Apr 29 10:55:04 2009
@@ -53,8 +53,8 @@
public Response build() {
ResponseImpl r = new ResponseImpl(status, entity);
- MetadataMap<String, Object> m = new MetadataMap<String, Object>();
- m.putAll(metadata);
+ MetadataMap<String, Object> m =
+ new MetadataMap<String, Object>(metadata, false, true);
r.addMetadata(m);
reset();
return r;
@@ -146,7 +146,46 @@
@Override
public ResponseBuilder variants(List<Variant> variants) {
- throw new UnsupportedOperationException("Only a single variant option
is supported");
+ if (variants == null) {
+ metadata.remove(HttpHeaders.VARY);
+ return this;
+ }
+ String acceptVary = null;
+ String acceptLangVary = null;
+ String acceptEncVary = null;
+ for (Variant v : variants) {
+ MediaType mt = v.getMediaType();
+ if (mt != null) {
+ acceptVary = HttpHeaders.ACCEPT;
+ addHeader(HttpHeaders.ACCEPT, mt);
+ }
+ Locale l = v.getLanguage();
+ if (l != null) {
+ acceptLangVary = HttpHeaders.ACCEPT_LANGUAGE;
+ addHeader(HttpHeaders.ACCEPT_LANGUAGE, l);
+ }
+ String enc = v.getEncoding();
+ if (enc != null) {
+ acceptEncVary = HttpHeaders.ACCEPT_ENCODING;
+ addHeader(HttpHeaders.ACCEPT_ENCODING, enc);
+ }
+ }
+ handleVaryValue(acceptVary, acceptLangVary, acceptEncVary);
+ return this;
+ }
+
+ private void handleVaryValue(String ...values) {
+ List<Object> varyValues = metadata.get(HttpHeaders.VARY);
+ for (String v : values) {
+ if (v == null) {
+ metadata.remove(v);
+ if (varyValues != null) {
+ varyValues.remove(v);
+ }
+ } else {
+ addHeader(HttpHeaders.VARY, v);
+ }
+ }
}
// CHECKSTYLE:OFF
@@ -180,11 +219,18 @@
private ResponseBuilder addHeader(String name, Object... values) {
if (values != null && values.length >= 1 && values[0] != null) {
for (Object value : values) {
- metadata.add(name, value.toString());
+ if (!valueExists(name, value)) {
+ metadata.add(name, value.toString());
+ }
}
} else {
metadata.remove(name);
}
return this;
}
+
+ private boolean valueExists(String key, Object value) {
+ List<Object> values = metadata.get(key);
+ return values == null ? false : values.contains(value.toString());
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
Wed Apr 29 10:55:04 2009
@@ -273,6 +273,11 @@
@Override
public UriBuilder path(String path) throws IllegalArgumentException {
+
+ if (path == null) {
+ throw new IllegalArgumentException("path is null");
+ }
+
List<PathSegment> segments = JAXRSUtils.getPathSegments(path, false,
false);
if (!paths.isEmpty() && !matrix.isEmpty()) {
PathSegment ps = paths.remove(paths.size() - 1);
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/VariantListBuilderImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/VariantListBuilderImpl.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/VariantListBuilderImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/VariantListBuilderImpl.java
Wed Apr 29 10:55:04 2009
@@ -22,10 +22,8 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Variant;
@@ -33,9 +31,9 @@
public class VariantListBuilderImpl extends VariantListBuilder {
- private Set<String> encodings = new HashSet<String>();
- private Set<Locale> languages = new HashSet<Locale>();
- private Set<MediaType> mediaTypes = new HashSet<MediaType>();
+ private List<String> encodings = new ArrayList<String>();
+ private List<Locale> languages = new ArrayList<Locale>();
+ private List<MediaType> mediaTypes = new ArrayList<MediaType>();
private List<Variant> variants = new ArrayList<Variant>();
public VariantListBuilderImpl() {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/servlet/CXFNonSpringJaxrsServlet.java
Wed Apr 29 10:55:04 2009
@@ -20,11 +20,15 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
@@ -33,6 +37,7 @@
import javax.ws.rs.ext.Provider;
import org.apache.commons.lang.ClassUtils;
+import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.PerRequestResourceProvider;
import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
@@ -42,6 +47,8 @@
public class CXFNonSpringJaxrsServlet extends CXFNonSpringServlet {
+ private static final Logger LOG =
LogUtils.getL7dLogger(CXFNonSpringJaxrsServlet.class);
+
private static final String SERVICE_ADDRESS_PARAM = "jaxrs.address";
private static final String SERVICE_CLASSES_PARAM = "jaxrs.serviceClasses";
private static final String PROVIDERS_PARAM = "jaxrs.providers";
@@ -166,7 +173,7 @@
}
protected void createServerFromApplication(String cName) throws
ServletException {
- Class<?> appClass = loadClass(cName);
+ Class<?> appClass = loadClass(cName, "Application");
Application app = null;
try {
app = (Application)appClass.newInstance();
@@ -180,14 +187,19 @@
+ " can not be instantiated due to
IllegalAccessException");
}
+ verifySingletons(app.getSingletons());
+
List<Class> resourceClasses = new ArrayList<Class>();
List<Object> providers = new ArrayList<Object>();
Map<Class, ResourceProvider> map = new HashMap<Class,
ResourceProvider>();
// at the moment we don't support per-request providers, only resource
classes
+ // Note, app.getClasse() returns a list of per-resource classes
for (Class<?> c : app.getClasses()) {
- resourceClasses.add(c);
- map.put(c, new PerRequestResourceProvider(c));
+ if (isValidPerRequestResourceClass(c, app.getSingletons())) {
+ resourceClasses.add(c);
+ map.put(c, new PerRequestResourceProvider(c));
+ }
}
// we can get either a provider or resource class here
@@ -212,10 +224,52 @@
}
private Class<?> loadClass(String cName) throws ServletException {
+ return loadClass(cName, "Resource");
+ }
+
+ private Class<?> loadClass(String cName, String classType) throws
ServletException {
try {
return
ClassUtils.getClass(CXFNonSpringJaxrsServlet.class.getClassLoader(),
cName.trim());
} catch (ClassNotFoundException ex) {
- throw new ServletException("No resource class " + cName.trim() + "
can be found", ex);
+ throw new ServletException("No " + classType + " class " +
cName.trim() + " can be found", ex);
+ }
+ }
+
+ private boolean isValidResourceClass(Class<?> c) {
+ if (c.isInterface() || Modifier.isAbstract(c.getModifiers())) {
+ LOG.info("Ignoring invalid resource class " + c.getName());
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isValidPerRequestResourceClass(Class<?> c, Set<Object>
singletons) {
+ if (!isValidResourceClass(c)) {
+ return false;
+ }
+ for (Object s : singletons) {
+ if (c == s.getClass()) {
+ LOG.info("Ignoring per-request resource class " + c.getName()
+ + " as it is also registered as singleton");
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ private void verifySingletons(Set<Object> singletons) throws
ServletException {
+ if (singletons.isEmpty()) {
+ return;
+ }
+ Set<String> map = new HashSet<String>();
+ for (Object s : singletons) {
+ if (map.contains(s.getClass().getName())) {
+ throw new ServletException("More than one instance of the same
singleton class "
+ + s.getClass().getName() + " is
available");
+ } else {
+ map.add(s.getClass().getName());
+ }
}
}
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MetadataMapTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MetadataMapTest.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MetadataMapTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/MetadataMapTest.java
Wed Apr 29 10:55:04 2009
@@ -82,7 +82,8 @@
m2.remove("baz");
}
- public void testCaseInsensitive() {
+ @Test
+ public void testGetCaseInsensitive() {
MetadataMap<String, Object> m = new MetadataMap<String, Object>();
m.add("Baz", "bar");
MetadataMap<String, Object> m2 = new MetadataMap<String, Object>(m,
true, true);
@@ -90,5 +91,11 @@
assertEquals("bar", m2.getFirst("Baz"));
assertTrue(m2.containsKey("BaZ"));
assertTrue(m2.containsKey("Baz"));
+ List<Object> values = m2.get("baz");
+ assertEquals(1, values.size());
+ assertEquals("bar", values.get(0).toString());
}
+
+
+
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProviderTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProviderTest.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProviderTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/NewCookieHeaderProviderTest.java
Wed Apr 29 10:55:04 2009
@@ -69,7 +69,7 @@
@Test
public void testToString() {
NewCookie c = new NewCookie("foo", "bar", "path", "domain", "comment",
2, true);
-
assertEquals("foo=bar;Comment=comment;Domain=domain;Max-Age=2;Path=path;Secure",
+
assertEquals("foo=bar;Comment=comment;Domain=domain;Max-Age=2;Path=path;Secure;Version=1",
c.toString());
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImplTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImplTest.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImplTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseBuilderImplTest.java
Wed Apr 29 10:55:04 2009
@@ -22,11 +22,14 @@
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Variant;
import org.apache.cxf.jaxrs.utils.HttpUtils;
@@ -36,7 +39,7 @@
public class ResponseBuilderImplTest extends Assert {
-
+
@Test
public void testLanguage() {
MetadataMap<String, Object> m = new MetadataMap<String, Object>();
@@ -65,8 +68,8 @@
@Test
public void testAddCookie() {
MetadataMap<String, Object> m = new MetadataMap<String, Object>();
- m.add("Set-Cookie", "a=b");
- m.add("Set-Cookie", "c=d");
+ m.add("Set-Cookie", "a=b;Version=1");
+ m.add("Set-Cookie", "c=d;Version=1");
checkBuild(Response.ok().cookie(new NewCookie("a", "b"))
.cookie(new NewCookie("c", "d")).build(),
200, null, m);
@@ -93,6 +96,20 @@
}
@Test
+ public void testVariant() throws Exception {
+
+ MetadataMap<String, Object> m = new MetadataMap<String, Object>();
+ m.putSingle("Content-Type", "text/xml");
+ m.putSingle("Content-Language", "en");
+ m.putSingle("Content-Encoding", "gzip");
+ Variant v = new Variant(MediaType.TEXT_XML_TYPE, new Locale("en"),
"gzip");
+
+ checkBuild(Response.ok().variant(v).build(),
+ 200, null, m);
+ }
+
+
+ @Test
public void testCreatedNoEntity() throws Exception {
MetadataMap<String, Object> m = new MetadataMap<String, Object>();
@@ -104,6 +121,7 @@
}
+
private void checkBuild(Response r, int status, Object entity,
MetadataMap<String, Object> meta) {
ResponseImpl ri = (ResponseImpl)r;
@@ -112,4 +130,27 @@
assertEquals("Wrong meta", ri.getMetadata(), meta);
}
+ @Test
+ public void testVariants() throws Exception {
+
+ MetadataMap<String, Object> m = new MetadataMap<String, Object>();
+ m.add("Accept", "text/xml");
+ m.add("Accept", "application/xml");
+ m.add("Accept-Language", "en_UK");
+ m.add("Accept-Language", "en_GB");
+ m.add("Accept-Encoding", "compress");
+ m.add("Accept-Encoding", "gzip");
+ m.add("Vary", "Accept");
+ m.add("Vary", "Accept-Language");
+ m.add("Vary", "Accept-Encoding");
+ List<Variant> vts = Variant.VariantListBuilder.newInstance()
+ .mediaTypes(MediaType.TEXT_XML_TYPE,
MediaType.APPLICATION_XML_TYPE).
+ languages(new Locale("en", "UK"), new Locale("en",
"GB")).encodings("compress", "gzip").
+ add().build();
+
+ checkBuild(Response.ok().variants(vts).build(),
+ 200, null, m);
+ }
+
+
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
Wed Apr 29 10:55:04 2009
@@ -41,6 +41,11 @@
public void testCtorNull() throws Exception {
new UriBuilderImpl(null);
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testPathStringNull() throws Exception {
+ new UriBuilderImpl().path((String)null);
+ }
@Test
public void testCtorAndBuild() throws Exception {
Modified:
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java?rev=769741&r1=769740&r2=769741&view=diff
==============================================================================
---
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
(original)
+++
cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
Wed Apr 29 10:55:04 2009
@@ -29,6 +29,7 @@
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(org.apache.cxf.systest.jaxrs.BookStorePerRequest.class);
+ classes.add(org.apache.cxf.systest.jaxrs.BookStoreJaxrsJaxws.class);
return classes;
}