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 2012/08/17 15:48:25 UTC
svn commit: r1374255 - in /cxf/trunk/rt/frontend/jaxrs/src:
main/java/org/apache/cxf/jaxrs/impl/ test/java/org/apache/cxf/jaxrs/impl/
Author: sergeyb
Date: Fri Aug 17 13:48:25 2012
New Revision: 1374255
URL: http://svn.apache.org/viewvc?rev=1374255&view=rev
Log:
[CXF-4455] Initial support for Link header
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java (with props)
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java (with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java?rev=1374255&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java Fri Aug 17 13:48:25 2012
@@ -0,0 +1,139 @@
+/**
+ * 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.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.Link;
+import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
+
+public class LinkHeaderProvider implements HeaderDelegate<Link> {
+
+ private static final String REL = "rel";
+ private static final String TYPE = "type";
+ private static final String TITLE = "title";
+
+ private static final Set<String> KNOWN_PARAMETERS;
+ static {
+ KNOWN_PARAMETERS = new HashSet<String>(Arrays.asList(REL, TYPE, TITLE));
+ }
+
+ public Link fromString(String value) {
+
+ if (value == null) {
+ throw new IllegalArgumentException("Link value can not be null");
+ }
+ value = value.trim();
+ int closeIndex = value.indexOf('>');
+ if (!value.startsWith("<") || closeIndex < 2) {
+ throw new IllegalArgumentException("Link URI is missing");
+ }
+ Link.Builder builder = new Link.Builder();
+ builder.uri(value.substring(1, closeIndex).trim());
+ if (closeIndex < value.length() - 1) {
+
+ String[] tokens = value.substring(closeIndex + 1).split(";");
+ for (String token : tokens) {
+ String theToken = token.trim();
+ if (theToken.isEmpty()) {
+ continue;
+ }
+ String paramName = null;
+ String paramValue = null;
+ int i = token.indexOf('=');
+ if (i != -1) {
+ paramName = theToken.substring(0, i).trim();
+ paramValue = i == theToken.length() - 1 ? "" : theToken.substring(i + 1).trim();
+ }
+ if (REL.equals(paramName)) {
+ String[] rels = removeQuotesIfNeeded(paramValue).split(",");
+ for (String rel : rels) {
+ builder.rel(rel.trim());
+ }
+ } else if (TYPE.equals(paramName)) {
+ builder.type(removeQuotesIfNeeded(paramValue));
+ } else if (TITLE.equals(paramName)) {
+ builder.title(removeQuotesIfNeeded(paramValue));
+ } else {
+ builder.param(paramName, paramValue);
+ }
+ }
+ }
+ return builder.build();
+
+ }
+
+ private String removeQuotesIfNeeded(String value) {
+ if (value.length() > 1 && value.startsWith("\"") && value.endsWith("\"")) {
+ return value.substring(1, value.length() - 1);
+ } else {
+ return value;
+ }
+ }
+
+ public String toString(Link link) {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append('<');
+ sb.append(link.getUri());
+ sb.append('>');
+
+ List<String> rels = link.getRel();
+ if (!rels.isEmpty()) {
+ sb.append(";").append(REL).append('=');
+ writeListParamValues(sb, rels);
+ }
+ if (link.getTitle() != null) {
+ sb.append(";").append(TITLE).append("=\"").append(link.getTitle()).append('"');
+ }
+ if (link.getType() != null) {
+ sb.append(";").append(TYPE).append('=').append(link.getType());
+ }
+ for (Map.Entry<String, List<String>> entry : link.getParams().entrySet()) {
+ if (KNOWN_PARAMETERS.contains(entry.getKey())) {
+ continue;
+ }
+ sb.append(";").append(entry.getKey()).append('=');
+ writeListParamValues(sb, entry.getValue());
+ }
+
+ return sb.toString();
+
+ }
+
+ private void writeListParamValues(StringBuilder sb, List<String> values) {
+ if (values.size() > 1) {
+ sb.append('"');
+ }
+ for (int i = 0; i < values.size(); i++) {
+ sb.append(values.get(i));
+ if (i < values.size() - 1) {
+ sb.append(',');
+ }
+ }
+ if (values.size() > 1) {
+ sb.append('"');
+ }
+ }
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/LinkHeaderProvider.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java?rev=1374255&r1=1374254&r2=1374255&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java Fri Aug 17 13:48:25 2012
@@ -39,7 +39,6 @@ import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Link;
-import javax.ws.rs.core.Link.Builder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
@@ -217,26 +216,42 @@ public final class ResponseImpl extends
return header == null ? null : MediaType.valueOf(header);
}
+ public boolean hasLink(String relation) {
+ return getLink(relation) != null;
+ }
+
public Link getLink(String relation) {
- // TODO Auto-generated method stub
+ Set<Map.Entry<List<String>, Link>> entries = getAllLinks().entrySet();
+ for (Map.Entry<List<String>, Link> entry : entries) {
+ if (entry.getKey().contains(relation)) {
+ return entry.getValue();
+ }
+ }
return null;
}
- public Builder getLinkBuilder(String arg0) {
- // TODO Auto-generated method stub
- return null;
+ public Link.Builder getLinkBuilder(String relation) {
+ return Link.fromLink(getLink(relation));
}
public Set<Link> getLinks() {
- // TODO Auto-generated method stub
- return null;
+ return new HashSet<Link>(getAllLinks().values());
}
- public boolean hasLink(String relation) {
- // TODO Auto-generated method stub
- return false;
+ private Map<List<String>, Link> getAllLinks() {
+ List<Object> linkValues = metadata.get(HttpHeaders.LINK);
+ if (linkValues == null) {
+ return Collections.emptyMap();
+ } else {
+ Map<List<String>, Link> links = new HashMap<List<String>, Link>();
+ for (Object o : linkValues) {
+ Link link = Link.valueOf(o.toString());
+ links.put(link.getRel(), link);
+ }
+ return links;
+ }
}
-
+
public <T> T readEntity(Class<T> cls) throws MessageProcessingException, IllegalStateException {
return readEntity(cls, new Annotation[]{});
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java?rev=1374255&r1=1374254&r2=1374255&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java Fri Aug 17 13:48:25 2012
@@ -26,6 +26,7 @@ import javax.ws.rs.core.Application;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.Link;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response.ResponseBuilder;
@@ -49,6 +50,7 @@ public class RuntimeDelegateImpl extends
headerProviders.put(EntityTag.class, new EntityTagHeaderProvider());
headerProviders.put(Cookie.class, new CookieHeaderProvider());
headerProviders.put(NewCookie.class, new NewCookieHeaderProvider());
+ headerProviders.put(Link.class, new LinkHeaderProvider());
}
Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java?rev=1374255&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java Fri Aug 17 13:48:25 2012
@@ -0,0 +1,63 @@
+/**
+ * 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.List;
+
+import javax.ws.rs.core.Link;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LinkHeaderProviderTest extends Assert {
+
+ @Test
+ public void testFromSimpleString() {
+ Link l = Link.valueOf("<http://bar>");
+ assertEquals("http://bar", l.getUri().toString());
+ }
+
+ @Test
+ public void testFromSimpleString2() {
+ Link l = Link.valueOf("</>");
+ assertEquals("/", l.getUri().toString());
+ }
+
+ @Test
+ public void testFromComplexString() {
+ Link l = Link.valueOf("<http://bar>;rel=next;title=\"Next Link\";type=text/xml;method=get");
+ assertEquals("http://bar", l.getUri().toString());
+ List<String> rels = l.getRel();
+ assertEquals(1, rels.size());
+ assertEquals("next", rels.get(0));
+ assertEquals("Next Link", l.getTitle());
+ assertEquals("get", l.getMethod());
+ }
+
+ @Test
+ public void testToString() {
+ String headerValue = "<http://bar>;rel=next;title=\"Next Link\";type=text/xml;method=get";
+ Link l = Link.valueOf(headerValue);
+ String result = l.toString();
+ assertEquals(result, headerValue);
+ }
+
+
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/LinkHeaderProviderTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java?rev=1374255&r1=1374254&r2=1374255&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java Fri Aug 17 13:48:25 2012
@@ -21,8 +21,10 @@ package org.apache.cxf.jaxrs.impl;
import java.io.ByteArrayInputStream;
import java.util.Map;
+import java.util.Set;
import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Link;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
@@ -171,4 +173,34 @@ public class ResponseImplTest extends As
ri.addMetadata(meta);
assertEquals("text/xml", ri.getMediaType().toString());
}
+
+ @Test
+ public void testGetLinks() {
+ ResponseImpl ri = new ResponseImpl(200);
+ MetadataMap<String, Object> meta = new MetadataMap<String, Object>();
+ ri.addMetadata(meta);
+ assertFalse(ri.hasLink("next"));
+ assertNull(ri.getLink("next"));
+ assertFalse(ri.hasLink("prev"));
+ assertNull(ri.getLink("prev"));
+
+ meta.add(HttpHeaders.LINK, "<http://next>;rel=next");
+ meta.add(HttpHeaders.LINK, "<http://prev>;rel=prev");
+
+ assertTrue(ri.hasLink("next"));
+ Link next = ri.getLink("next");
+ assertNotNull(next);
+ assertTrue(ri.hasLink("prev"));
+ Link prev = ri.getLink("prev");
+ assertNotNull(prev);
+
+ Set<Link> links = ri.getLinks();
+ assertTrue(links.contains(next));
+ assertTrue(links.contains(prev));
+
+ assertEquals("http://next", next.getUri().toString());
+ assertEquals("next", next.getRel().get(0));
+ assertEquals("http://prev", prev.getUri().toString());
+ assertEquals("prev", prev.getRel().get(0));
+ }
}