You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by ma...@apache.org on 2009/07/15 14:51:41 UTC
svn commit: r794252 - in /incubator/wink/trunk: src/doc/DeveloperGuide/
wink-common/src/main/java/org/apache/wink/common/internal/uri/
wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/
wink-common/src/main/java/org/apache/wink/comm...
Author: martins
Date: Wed Jul 15 12:51:40 2009
New Revision: 794252
URL: http://svn.apache.org/viewvc?rev=794252&view=rev
Log:
Fix JIRA [WINK-94] and [WINK-96]
Removed:
incubator/wink/trunk/src/doc/DeveloperGuide/Apache_Wink_0.1_Features_List.docx
incubator/wink/trunk/src/doc/DeveloperGuide/Apache_Wink_0.1_Features_List.pdf
Modified:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/UriTemplateProcessor.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/UriHelper.java
incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/utils/UriHelperTest.java
incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/UriInfoImpl.java
incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/jaxrs/UriInfoImplTest.java
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uri/UriEncoder.java Wed Jul 15 12:51:40 2009
@@ -20,6 +20,7 @@
package org.apache.wink.common.internal.uri;
+import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
@@ -44,6 +45,8 @@
/** Hexadecimal digits for escaping. */
private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F'};
+
+ private static final byte[] normalizedHexDigits = new byte[128];
private static final boolean[] isHexDigit = new boolean[128];
@@ -51,16 +54,16 @@
* Unreserved characters according to RFC 3986. Each character below ASCII 128 has single array
* item with true if it is unreserved and false if it is reserved.
*/
- private static final boolean[] unreservedChars = new boolean[128];
- private static final boolean[] userInfoChars = new boolean[128];
- private static final boolean[] segmentChars = new boolean[128];
- private static final boolean[] matrixChars = new boolean[128];
- private static final boolean[] pathChars = new boolean[128];
- private static final boolean[] queryChars = new boolean[128];
- private static final boolean[] queryParamChars = new boolean[128];
- private static final boolean[] fragmentChars = new boolean[128];
- private static final boolean[] uriChars = new boolean[128];
- private static final boolean[] uriTemplateChars = new boolean[128];
+ public static final boolean[] unreservedChars = new boolean[128];
+ public static final boolean[] userInfoChars = new boolean[128];
+ public static final boolean[] segmentChars = new boolean[128];
+ public static final boolean[] matrixChars = new boolean[128];
+ public static final boolean[] pathChars = new boolean[128];
+ public static final boolean[] queryChars = new boolean[128];
+ public static final boolean[] queryParamChars = new boolean[128];
+ public static final boolean[] fragmentChars = new boolean[128];
+ public static final boolean[] uriChars = new boolean[128];
+ public static final boolean[] uriTemplateChars = new boolean[128];
static {
// unreserved - ALPHA / DIGIT / "-" / "." / "_" / "~"
@@ -132,6 +135,31 @@
Arrays.fill(isHexDigit, '0', '9' + 1, true);
Arrays.fill(isHexDigit, 'a', 'f' + 1, true);
Arrays.fill(isHexDigit, 'A', 'F' + 1, true);
+
+ // fill the normalizedHexDigits array
+ normalizedHexDigits['0'] = '0';
+ normalizedHexDigits['1'] = '1';
+ normalizedHexDigits['2'] = '2';
+ normalizedHexDigits['3'] = '3';
+ normalizedHexDigits['4'] = '4';
+ normalizedHexDigits['5'] = '5';
+ normalizedHexDigits['6'] = '6';
+ normalizedHexDigits['7'] = '7';
+ normalizedHexDigits['8'] = '8';
+ normalizedHexDigits['9'] = '9';
+ normalizedHexDigits['A'] = 'A';
+ normalizedHexDigits['B'] = 'B';
+ normalizedHexDigits['C'] = 'C';
+ normalizedHexDigits['D'] = 'D';
+ normalizedHexDigits['E'] = 'E';
+ normalizedHexDigits['F'] = 'F';
+ normalizedHexDigits['a'] = 'A';
+ normalizedHexDigits['b'] = 'B';
+ normalizedHexDigits['c'] = 'C';
+ normalizedHexDigits['d'] = 'D';
+ normalizedHexDigits['e'] = 'E';
+ normalizedHexDigits['f'] = 'F';
+
}
private static int decodeHexDigit(char c) {
@@ -384,7 +412,7 @@
* @return decoded query
*/
public static String decodeQuery(String string) {
- return decodeString(string, true);
+ return decodeString(string, true, null);
}
/**
@@ -395,10 +423,22 @@
* @return decoded uri
*/
public static String decodeString(String string) {
- return decodeString(string, false);
+ return decodeString(string, false, null);
+ }
+
+ /**
+ * Decodes only the unreserved chars, according to <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
+ * section 6.2.2.2
+ *
+ * @param string
+ * US-ASCII uri to decode
+ * @return decoded uri
+ */
+ public static String normalize(String string){
+ return decodeString(string, false, unreservedChars);
}
- private static String decodeString(String string, boolean query) {
+ private static String decodeString(String string, boolean query, boolean[] decodeChars) {
if (string == null) {
return null;
}
@@ -420,8 +460,15 @@
if (d1 >= 0 && d2 >= 0) {
v = d1;
v = v << 4 | d2;
- buffer.put((byte)v);
- i += 2;
+ if(decodeChars != null && !decodeChars[v]){
+ buffer.put((byte)string.charAt(i));
+ buffer.put(normalizedHexDigits[string.charAt(i + 1)]);
+ buffer.put(normalizedHexDigits[string.charAt(i + 2)]);
+ }
+ else{
+ buffer.put((byte)v);
+ }
+ i+=2;
} else {
buffer.put((byte)c);
}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/UriTemplateProcessor.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/UriTemplateProcessor.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/UriTemplateProcessor.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/uritemplate/UriTemplateProcessor.java Wed Jul 15 12:51:40 2009
@@ -34,7 +34,7 @@
import org.apache.wink.common.http.HttpStatus;
import org.apache.wink.common.internal.MultivaluedMapImpl;
import org.apache.wink.common.internal.uri.UriEncoder;
-import org.apache.wink.common.internal.uri.UriPathNormalizer;
+import org.apache.wink.common.internal.utils.UriHelper;
/**
@@ -262,16 +262,14 @@
public static String normalizeUri(String uri) {
String normalizedUri;
if (uri != null) {
- normalizedUri = UriPathNormalizer.normalize(uri);
+ normalizedUri = UriHelper.normalize(uri);
} else {
normalizedUri = "";
}
if (normalizedUri.startsWith("/")) {
normalizedUri = normalizedUri.substring(1);
}
-// if (normalizedUri.endsWith("/")) {
-// normalizedUri = normalizedUri.substring(0, normalizedUri.length() - 1);
-// }
+
return normalizedUri;
}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/UriHelper.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/UriHelper.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/UriHelper.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/UriHelper.java Wed Jul 15 12:51:40 2009
@@ -475,5 +475,21 @@
}
return query;
}
-
+
+ /**
+ * Normalize input uri according to <a> href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
+ * section 6.2.2. - Syntax-Based Normalization
+ * @param string
+ * @return normalized instance of uri
+ */
+ public static String normalize(String uri){
+
+ // Path Segment Normalization
+ uri = UriPathNormalizer.normalize(uri);
+
+ // Percent-Encoding Normalization & Case Normalization
+ uri = UriEncoder.normalize(uri);
+
+ return uri;
+ }
}
Modified: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/utils/UriHelperTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/utils/UriHelperTest.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/utils/UriHelperTest.java (original)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/utils/UriHelperTest.java Wed Jul 15 12:51:40 2009
@@ -285,4 +285,9 @@
assertNull(parsedQuery.getFirst("e"));
}
+ public void testNormalize(){
+ // test URI Syntax-Based Normalization according to RFC 3986, section 6.2.2
+ String normalize = UriHelper.normalize("ab%72c%2F123/d%2fdef/a/../b/./c%20sss");
+ assertEquals("abrc%2F123/d%2Fdef/b/c%20sss", normalize);
+ }
}
Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/UriInfoImpl.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/UriInfoImpl.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/UriInfoImpl.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/contexts/UriInfoImpl.java Wed Jul 15 12:51:40 2009
@@ -39,6 +39,7 @@
import org.apache.wink.common.internal.MultivaluedMapImpl;
import org.apache.wink.common.internal.PathSegmentImpl;
import org.apache.wink.common.internal.uri.UriEncoder;
+import org.apache.wink.common.internal.uri.UriPathNormalizer;
import org.apache.wink.common.internal.utils.UriHelper;
import org.apache.wink.server.handlers.MessageContext;
import org.apache.wink.server.internal.handlers.SearchResult;
@@ -325,7 +326,10 @@
private String buildRequestPath(HttpServletRequest request) {
// we cannot use request.getPathInfo() since it cuts off the ';' parameters on Tomcat
String requestPath = request.getRequestURI();
-
+
+ // Syntax-Based Normalization (RFC 3986, section 6.2.2)
+ requestPath = UriHelper.normalize(requestPath);
+
// cut off the context path from the beginning
if (request.getContextPath() != null) {
requestPath = requestPath.substring(request.getContextPath().length());
Modified: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/jaxrs/UriInfoImplTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/jaxrs/UriInfoImplTest.java?rev=794252&r1=794251&r2=794252&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/jaxrs/UriInfoImplTest.java (original)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/internal/jaxrs/UriInfoImplTest.java Wed Jul 15 12:51:40 2009
@@ -34,12 +34,11 @@
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
-
public class UriInfoImplTest extends MockServletInvocationTest {
@Override
protected Class<?>[] getClasses() {
- return new Class[] { FooResource.class, TestResource.class};
+ return new Class[] {FooResource.class, TestResource.class};
}
@Path("/te st/{id}")
@@ -48,20 +47,20 @@
@Produces("text/plain")
public void getFoo(@Context UriInfo uriInfo) {
assertNotNull(uriInfo.getAbsolutePath());
- assertEquals("http://localhost:80/te%20st/5", uriInfo.getAbsolutePath().toString());
+ assertEquals("http://localhost:80/te%20st/5", uriInfo.getAbsolutePath().toString());
assertNotNull(uriInfo.getBaseUri());
- assertEquals("http://localhost:80/", uriInfo.getBaseUri().toString());
+ assertEquals("http://localhost:80/", uriInfo.getBaseUri().toString());
assertNotNull(uriInfo.getPath());
- assertEquals("te st/5", uriInfo.getPath().toString());
- assertEquals("te%20st/5", uriInfo.getPath(false).toString());
+ assertEquals("te st/5", uriInfo.getPath().toString());
+ assertEquals("te%20st/5", uriInfo.getPath(false).toString());
MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
assertNotNull(pathParameters);
assertEquals(1, pathParameters.size());
List<String> paramValue = pathParameters.get("id");
assertNotNull(paramValue);
assertEquals(1, paramValue.size());
- assertEquals("5", paramValue.get(0));
-
+ assertEquals("5", paramValue.get(0));
+
List<PathSegment> pathSegmentsDecoded = uriInfo.getPathSegments();
assertNotNull(pathSegmentsDecoded);
assertEquals(2, pathSegmentsDecoded.size());
@@ -72,22 +71,20 @@
assertEquals(2, pathSegmentsEncoded.size());
assertEquals("5", pathSegmentsEncoded.get(1).getPath());
-
MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
assertNotNull(queryParameters);
assertEquals(1, queryParameters.size());
List<String> queryParam = queryParameters.get("abc");
assertNotNull(queryParam);
assertEquals(1, queryParam.size());
- assertEquals("6",queryParam.get(0));
-
+ assertEquals("6", queryParam.get(0));
+
assertEquals("http://localhost:80/te%20st/5?abc=6", uriInfo.getRequestUri().toString());
-
+
return;
}
}
-
-
+
@Path("/foo")
public static class FooResource {
@GET
@@ -99,7 +96,7 @@
assertNotNull(uriInfo.getMatchedURIs());
assertEquals(1, uriInfo.getMatchedURIs().size());
assertEquals("foo", uriInfo.getMatchedURIs().get(0));
-
+
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(1, uriInfo.getMatchedResources().size());
@@ -118,17 +115,17 @@
String firstUri = uriInfo.getMatchedURIs().get(0);
assertEquals("foo/bar", firstUri);
String secondUri = uriInfo.getMatchedURIs().get(1);
- assertEquals("foo",secondUri);
-
+ assertEquals("foo", secondUri);
+
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(1, uriInfo.getMatchedResources().size());
Object matchedResource = uriInfo.getMatchedResources().get(0);
assertNotNull(matchedResource);
assertTrue(matchedResource instanceof FooResource);
- return new BarResource();
+ return new BarResource();
}
-
+
@GET
@Path("bar1")
public String getBar1Resource(@Context UriInfo uriInfo) {
@@ -139,25 +136,24 @@
String firstUri = uriInfo.getMatchedURIs().get(0);
assertEquals("foo/bar1", firstUri);
String secondUri = uriInfo.getMatchedURIs().get(1);
- assertEquals("foo",secondUri);
-
+ assertEquals("foo", secondUri);
+
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(1, uriInfo.getMatchedResources().size());
Object matchedResource = uriInfo.getMatchedResources().get(0);
assertNotNull(matchedResource);
assertTrue(matchedResource instanceof FooResource);
- return "Bar Resource";
+ return "Bar Resource";
}
-
-
+
}
public static class BarResource {
@GET
@Produces("text/plain")
public String getBar(@Context UriInfo uriInfo) {
-
+
// test matched URIs
assertNotNull(uriInfo);
assertNotNull(uriInfo.getMatchedURIs());
@@ -165,24 +161,24 @@
String firstUri = uriInfo.getMatchedURIs().get(0);
assertEquals("foo/bar", firstUri);
String secondUri = uriInfo.getMatchedURIs().get(1);
- assertEquals("foo",secondUri);
-
+ assertEquals("foo", secondUri);
+
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(2, uriInfo.getMatchedResources().size());
Object matchedResource = uriInfo.getMatchedResources().get(0);
assertTrue(matchedResource instanceof BarResource);
-
+
matchedResource = uriInfo.getMatchedResources().get(1);
assertTrue(matchedResource instanceof FooResource);
-
+
return "Bar Resurse";
}
-
+
@Path("level3")
@Produces("text/plain")
public BarResourceLevel3 getBarLevel3(@Context UriInfo uriInfo) {
-
+
// test matched URIs
assertNotNull(uriInfo);
assertNotNull(uriInfo.getMatchedURIs());
@@ -190,28 +186,28 @@
String firstUri = uriInfo.getMatchedURIs().get(0);
assertEquals("foo/bar/level3", firstUri);
String secondUri = uriInfo.getMatchedURIs().get(1);
- assertEquals("foo/bar",secondUri);
+ assertEquals("foo/bar", secondUri);
String thirdUri = uriInfo.getMatchedURIs().get(2);
- assertEquals("foo",thirdUri);
-
+ assertEquals("foo", thirdUri);
+
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(2, uriInfo.getMatchedResources().size());
Object matchedResource = uriInfo.getMatchedResources().get(0);
assertTrue(matchedResource instanceof BarResource);
-
+
matchedResource = uriInfo.getMatchedResources().get(1);
assertTrue(matchedResource instanceof FooResource);
-
+
return new BarResourceLevel3();
}
}
-
+
public static class BarResourceLevel3 {
@GET
@Produces("text/plain")
public String getBar(@Context UriInfo uriInfo) {
-
+
// test matched URIs
assertNotNull(uriInfo);
assertNotNull(uriInfo.getMatchedURIs());
@@ -219,11 +215,10 @@
String firstUri = uriInfo.getMatchedURIs().get(0);
assertEquals("foo/bar/level3", firstUri);
String secondUri = uriInfo.getMatchedURIs().get(1);
- assertEquals("foo/bar",secondUri);
+ assertEquals("foo/bar", secondUri);
String thirdUri = uriInfo.getMatchedURIs().get(2);
- assertEquals("foo",thirdUri);
+ assertEquals("foo", thirdUri);
-
// test matched Resources
assertNotNull(uriInfo.getMatchedResources());
assertEquals(3, uriInfo.getMatchedResources().size());
@@ -233,39 +228,58 @@
matchedResource = uriInfo.getMatchedResources().get(1);
assertTrue(matchedResource instanceof BarResource);
-
+
matchedResource = uriInfo.getMatchedResources().get(2);
assertTrue(matchedResource instanceof FooResource);
-
+
return "Bar Resourse Level 3";
}
}
-
-
@Test
public void testUriInfoMatchedResourcesAndURIs() throws Exception {
- MockHttpServletRequest servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo", "text/plain");
+ MockHttpServletRequest servletRequest =
+ MockRequestConstructor.constructMockRequest("GET", "/foo", "text/plain");
invoke(servletRequest);
-
+
servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo/bar", "text/plain");
invoke(servletRequest);
-
+
servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo/bar1", "text/plain");
invoke(servletRequest);
-
+
servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo/bar/level3", "text/plain");
invoke(servletRequest);
-
}
-
+
@Test
public void testUriInfo() throws Exception {
- MockHttpServletRequest servletRequest = MockRequestConstructor.constructMockRequest("GET", "/te%20st/5", "text/plain");
+ MockHttpServletRequest servletRequest =
+ MockRequestConstructor.constructMockRequest("GET", "/te%20st/5", "text/plain");
servletRequest.setQueryString("abc=6");
invoke(servletRequest);
}
+ @Test
+ public void testUriInfoNormalization() throws Exception {
+
+ MockHttpServletRequest servletRequest =
+ MockRequestConstructor.constructMockRequest("GET", "/foo/../foo", "text/plain");
+ invoke(servletRequest);
+
+ servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo/../foo/bar", "text/plain");
+ invoke(servletRequest);
+
+ servletRequest = MockRequestConstructor.constructMockRequest("GET", "/foo/bar1/../bar1", "text/plain");
+ invoke(servletRequest);
+
+ servletRequest =
+ MockRequestConstructor.constructMockRequest("GET",
+ "/foo/../foo/bar/../bar/level3/../level3/nonsense/..",
+ "text/plain");
+ invoke(servletRequest);
+ }
+
}