cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r738961 - in /cxf/branches/2.1.x-fixes: ./ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ rt/frontend/jaxrs/...
Date Thu, 29 Jan 2009 18:59:51 GMT
Author: sergeyb
Date: Thu Jan 29 18:59:50 2009
New Revision: 738961

URL: http://svn.apache.org/viewvc?rev=738961&view=rev
Log:
Merged revisions 738937 via svnmerge from 
https://svn.apache.org/repos/asf/cxf/trunk

........
  r738937 | sergeyb | 2009-01-29 17:45:43 +0000 (Thu, 29 Jan 2009) | 1 line
  
  CXF-1991: applying a 2nd quality patch on behalf of Andrzej Michalec plus fix for UriInfo.getMatchedURIs and ExceptionMapper injection issue  
........

Modified:
    cxf/branches/2.1.x-fixes/   (props changed)
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/MethodInvocationInfo.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
    cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java
    cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java

Propchange: cxf/branches/2.1.x-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Jan 29 18:59:50 2009
@@ -1 +1 @@
-/cxf/trunk:686333-686363,686764,686820,687096,687194,687363,687387,687463,687543,687722,687798,687814,687817,687891,687910,687914,688086,688102,688133,688596,688735,688870,689572,689596,689855,689924,690067,690289,691246,691271,691295,691338,691355,691488,691602,691646,691706,691728,692116,692157,692310,692466,692499,693653,693819,694179,694263,694417,694716,694744,694747,694795,694869,694981,694987,694993,695041,695096,695396,695484,695537,695552,695561,695619,695684,695835,695840,695868,695935,695977,696016,696094,696433,696720,697085,697868,698128,699289,700261,700507,700602,700981,701316,701783,701830,701862,702187,702205-702248,702267,702547,702561,702580,702602,702609,702616,702653,702656,702957,703191,703239,703309,703501,703513,703548,704584,704937,704997,705150,705235,705274,705340,705446,705548,705614,705692,705708,706482,706631,706675,706900,706909,707034,707089,707100,707902,708035,708044,708074,708410,708417,708550,708554,709353-709354,709425,710076,710150,71015
 4,711193,711388,711410,711490,711635,711949,711975,712194,712198,712238,712272,712299,712312,712670,712893,713082,713095-713096,713099,713584,713597,713737,713804,713899,714167-714168,714245,714255,717937-717961,718281-718448,718565,718620,718640,718665,718970,719017,719210,719215-719218,719222-719273,719305,719327-719680,720053,720119-720218,720238,720293-720316,720497,721221,721241,721501,722117,722129,722412,722988,723024,723338,723378,723716-723791,724333-724372,724433-724438,724449,724481,724485,724668,724780,724782,724785,724793,724795,724940,725071,725316,725332,725335,725348,725364,725418,725425-725426,725455,725506,725554,725562,725651,725671,725688,725754,725773,725799,725839,726342,726524,726631,726634,726637,726639,726692,726724,726769,726992,727096,727445,727521,727568,727692,727754,727781,727792,728070,728087,728696,728897,729051,729430,729449,729460,729863,730082,730139,730889,730891,731598,731604,731615,731631,731635,732036,732050,732320,732363,732411,732450,
 732710,732773,732827,732829,733512,733582,733901,734367,734462,734666,734762,734772,734812,734836,734965,735113,735252,735722-735723,735729,735734,735751,735782,735787,735987,736332,736343,736352,736358-736362,736408,736423,736448,736491,736621,736726,736736,736738-736739,736766,736825,736852,737032,737046,737061,737069,737124,737237,737246,737299,737356,737494,737498,737761,737817,737849,737855,737994,738166,738178,738201,738210,738242,738244,738265,738516,738583,738863
+/cxf/trunk:686333-686363,686764,686820,687096,687194,687363,687387,687463,687543,687722,687798,687814,687817,687891,687910,687914,688086,688102,688133,688596,688735,688870,689572,689596,689855,689924,690067,690289,691246,691271,691295,691338,691355,691488,691602,691646,691706,691728,692116,692157,692310,692466,692499,693653,693819,694179,694263,694417,694716,694744,694747,694795,694869,694981,694987,694993,695041,695096,695396,695484,695537,695552,695561,695619,695684,695835,695840,695868,695935,695977,696016,696094,696433,696720,697085,697868,698128,699289,700261,700507,700602,700981,701316,701783,701830,701862,702187,702205-702248,702267,702547,702561,702580,702602,702609,702616,702653,702656,702957,703191,703239,703309,703501,703513,703548,704584,704937,704997,705150,705235,705274,705340,705446,705548,705614,705692,705708,706482,706631,706675,706900,706909,707034,707089,707100,707902,708035,708044,708074,708410,708417,708550,708554,709353-709354,709425,710076,710150,71015
 4,711193,711388,711410,711490,711635,711949,711975,712194,712198,712238,712272,712299,712312,712670,712893,713082,713095-713096,713099,713584,713597,713737,713804,713899,714167-714168,714245,714255,717937-717961,718281-718448,718565,718620,718640,718665,718970,719017,719210,719215-719218,719222-719273,719305,719327-719680,720053,720119-720218,720238,720293-720316,720497,721221,721241,721501,722117,722129,722412,722988,723024,723338,723378,723716-723791,724333-724372,724433-724438,724449,724481,724485,724668,724780,724782,724785,724793,724795,724940,725071,725316,725332,725335,725348,725364,725418,725425-725426,725455,725506,725554,725562,725651,725671,725688,725754,725773,725799,725839,726342,726524,726631,726634,726637,726639,726692,726724,726769,726992,727096,727445,727521,727568,727692,727754,727781,727792,728070,728087,728696,728897,729051,729430,729449,729460,729863,730082,730139,730889,730891,731598,731604,731615,731631,731635,732036,732050,732320,732363,732411,732450,
 732710,732773,732827,732829,733512,733582,733901,734367,734462,734666,734762,734772,734812,734836,734965,735113,735252,735722-735723,735729,735734,735751,735782,735787,735987,736332,736343,736352,736358-736362,736408,736423,736448,736491,736621,736726,736736,736738-736739,736766,736825,736852,737032,737046,737061,737069,737124,737237,737246,737299,737356,737494,737498,737761,737817,737849,737855,737994,738166,738178,738201,738210,738242,738244,738265,738516,738583,738863,738937

Propchange: cxf/branches/2.1.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSInvoker.java Thu Jan 29 18:59:50 2009
@@ -22,7 +22,9 @@
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.logging.Logger;
 
@@ -116,7 +118,9 @@
         try {
             result = invoke(exchange, resourceObject, methodToInvoke, params);
         } catch (Fault ex) {
-            Response excResponse = JAXRSUtils.convertFaultToResponse(ex.getCause(), baseAddress);
+            Response excResponse = JAXRSUtils.convertFaultToResponse(ex.getCause(), 
+                                                                     baseAddress,
+                                                                     exchange.getInMessage());
             if (excResponse == null) {
                 ProviderFactory.getInstance(baseAddress).clearThreadLocalProxies();
                 ClassResourceInfo criRoot =
@@ -180,7 +184,9 @@
 
                 return this.invoke(exchange, newParams, newResourceObjects);
             } catch (WebApplicationException ex) {
-                Response excResponse = JAXRSUtils.convertFaultToResponse(ex, baseAddress);
+                Response excResponse = JAXRSUtils.convertFaultToResponse(ex, 
+                                                                         baseAddress,
+                                                                         exchange.getInMessage());
                 return new MessageContentsList(excResponse);
             }
         }
@@ -236,12 +242,29 @@
         return result;
     }
 
+    @SuppressWarnings("unchecked")
     private void pushOntoStack(OperationResourceInfo ori, Class<?> realClass, Message msg) {
         OperationResourceInfoStack stack = msg.get(OperationResourceInfoStack.class);
         if (stack == null) {
             stack = new OperationResourceInfoStack();
             msg.put(OperationResourceInfoStack.class, stack);
         }
-        stack.push(new MethodInvocationInfo(ori, realClass));
+        
+        
+        MultivaluedMap<String, String> params = 
+            (MultivaluedMap)msg.get(URITemplate.TEMPLATE_PARAMETERS);
+        List<String> values = null;
+        if (params == null || params.size() == 1) {
+            values = Collections.emptyList();
+        } else {
+            values = new ArrayList<String>(params.size() - 1);
+            // if we have {bar}/{foo}/{bar} then we have a problem
+            for (Map.Entry<String, List<String>> entry : params.entrySet()) {
+                if (!entry.getKey().equals(URITemplate.FINAL_MATCH_GROUP)) {
+                    values.addAll(entry.getValue());
+                }
+            }
+        }
+        stack.push(new MethodInvocationInfo(ori, realClass, values));
     }
 }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/MetadataMap.java Thu Jan 29 18:59:50 2009
@@ -21,7 +21,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -33,7 +33,7 @@
     private Map<K, List<V>> m;
     
     public MetadataMap() {
-        this(new HashMap<K, List<V>>());
+        this(new LinkedHashMap<K, List<V>>());
     }
     
     public MetadataMap(Map<K, List<V>> store) {

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java Thu Jan 29 18:59:50 2009
@@ -24,9 +24,13 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.ws.rs.Path;
 import javax.ws.rs.core.MultivaluedMap;
@@ -34,6 +38,7 @@
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriBuilderException;
 
+import org.apache.cxf.jaxrs.model.URITemplate;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 
 public class UriBuilderImpl extends UriBuilder {
@@ -47,34 +52,80 @@
     private String fragment;
     private MultivaluedMap<String, String> query;
 
+    /**
+     * Creates builder with empty URI.
+     */
     public UriBuilderImpl() {
     }
 
-    public UriBuilderImpl(URI uri) {
+    /**
+     * Creates builder initialized with given URI.
+     * 
+     * @param uri initial value for builder
+     * @throws IllegalArgumentException when uri is null
+     */
+    public UriBuilderImpl(URI uri) throws IllegalArgumentException {
         setUriParts(uri);
     }
 
     @Override
     public URI build() throws UriBuilderException {
-        
         try {
             return new URI(scheme, userInfo, host, port, buildPath(), buildQuery(), fragment);
         } catch (URISyntaxException ex) {
             throw new UriBuilderException("URI can not be built", ex);
         }
-        
     }
 
     @Override
-    public URI build(Map<String, Object> parts) throws IllegalArgumentException, UriBuilderException {
-        // TODO Auto-generated method stub
-        return null;
+    public URI build(Map<String, Object> map) throws IllegalArgumentException, UriBuilderException {
+        try {
+            String path = buildPath();
+            path = substituteMapped(path, map);
+            return new URI(scheme, userInfo, host, port, path, buildQuery(), fragment);
+        } catch (URISyntaxException ex) {
+            throw new UriBuilderException("URI can not be built", ex);
+        }
     }
 
     @Override
     public URI build(Object... values) throws IllegalArgumentException, UriBuilderException {
-        // TODO Auto-generated method stub
-        return null;
+        try {
+            String path = buildPath();
+            path = substituteVarargs(path, values);
+            return new URI(scheme, userInfo, host, port, path, buildQuery(), fragment);
+        } catch (URISyntaxException ex) {
+            throw new UriBuilderException("URI can not be built", ex);
+        }
+    }
+
+    private String substituteVarargs(String path, Object... values) {
+        Map<String, String> varValueMap = new HashMap<String, String>();
+        URITemplate templ = new URITemplate(path);
+        // vars in set are properly ordered due to linking in hash set
+        Set<String> uniqueVars = new LinkedHashSet<String>(templ.getVariables());
+        if (values.length < uniqueVars.size()) {
+            throw new IllegalArgumentException("Unresolved variables; only " + values.length
+                                               + " value(s) given for " + uniqueVars.size()
+                                               + " unique variable(s)");
+        }
+        int idx = 0;
+        for (String var : uniqueVars) {
+            Object oval = values[idx++];
+            varValueMap.put(var, oval.toString());
+        }
+        return templ.substitute(varValueMap);
+    }
+
+    private String substituteMapped(String path, Map<String, ? extends Object> varValueMap) {
+        URITemplate templ = new URITemplate(path);
+        Set<String> uniqueVars = new HashSet<String>(templ.getVariables());
+        if (varValueMap.size() < uniqueVars.size()) {
+            throw new IllegalArgumentException("Unresolved variables; only " + varValueMap.size()
+                                               + " value(s) given for " + uniqueVars.size()
+                                               + " unique variable(s)");
+        }
+        return templ.substitute(varValueMap);
     }
 
     // CHECKSTYLE:OFF
@@ -134,6 +185,7 @@
         return path(((Path)ann).value());
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public UriBuilder path(Method... methods) throws IllegalArgumentException {
         if (methods == null) {
@@ -262,6 +314,9 @@
     }
 
     private void setUriParts(URI uri) {
+        if (uri == null) {
+            throw new IllegalArgumentException("uri is null");
+        }
         scheme = uri.getScheme();
         port = uri.getPort();
         host = uri.getHost();
@@ -273,15 +328,17 @@
 
     private String buildPath() {
         StringBuilder sb = new StringBuilder();
-        for (PathSegment ps : paths) {
-            String p = ps.getPath();
-            if (!p.startsWith("/") && (sb.length() == 0 || sb.charAt(sb.length() - 1) != '/')) {
-                sb.append('/');
+        Iterator<PathSegment> iter = paths.iterator();
+        while (iter.hasNext()) {
+            String p = iter.next().getPath();
+            if (p.length() != 0 || !iter.hasNext()) {
+                if (!p.startsWith("/")) {
+                    sb.append('/');
+                }
+                sb.append(p);
             }
-            sb.append(p);
         }
         return sb.toString();
-
     }
 
     private String buildQuery() {
@@ -300,4 +357,6 @@
         return b.length() > 0 ? b.toString() : null;
     }
 
+
+
 }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java Thu Jan 29 18:59:50 2009
@@ -147,6 +147,7 @@
 
     public List<String> getAncestorResourceURIs(boolean decode) {
         if (stack != null) {
+            List<String> objects = new ArrayList<String>();
             List<String> uris = new ArrayList<String>(stack.size());
             String sum = "";
             for (MethodInvocationInfo invocation : stack) {
@@ -163,7 +164,8 @@
                     }
                 }
                 UriBuilder ub = UriBuilder.fromPath(sum);
-                uris.add(ub.build().normalize().getPath());
+                objects.addAll(invocation.getTemplateValues());
+                uris.add(ub.build(objects.toArray()).normalize().getPath());
             }
             return uris;
         }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java Thu Jan 29 18:59:50 2009
@@ -67,7 +67,7 @@
         try {
             processRequest(message, originalAddress);
         } catch (RuntimeException ex) {
-            Response excResponse = JAXRSUtils.convertFaultToResponse(ex, originalAddress);
+            Response excResponse = JAXRSUtils.convertFaultToResponse(ex, originalAddress, message);
             if (excResponse == null) {
                 ProviderFactory.getInstance(originalAddress).clearThreadLocalProxies();
                 throw ex;

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/MethodInvocationInfo.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/MethodInvocationInfo.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/MethodInvocationInfo.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/MethodInvocationInfo.java Thu Jan 29 18:59:50 2009
@@ -18,17 +18,23 @@
  */
 package org.apache.cxf.jaxrs.model;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
- * A pair of {@link OperationResourceInfo} representing a resource method being invoked 
- * and actual {@link Class} of the object this method is invoked upon.
+ * A triple of {@link OperationResourceInfo} representing a resource method being invoked, 
+ * actual {@link Class} of the object this method is invoked upon, and a list of template variable values
+ * matched during the selection of this method
  */
 public class MethodInvocationInfo {
     private OperationResourceInfo ori;
     private Class<?> realClass;
+    private List<String> templateValues;
     
-    public MethodInvocationInfo(OperationResourceInfo ori, Class<?> realClass) {
+    public MethodInvocationInfo(OperationResourceInfo ori, Class<?> realClass, List<String> templateValues) {
         this.ori = ori;
         this.realClass = realClass;
+        this.templateValues = Collections.unmodifiableList(templateValues);
     }
     
     public OperationResourceInfo getMethodInfo() {
@@ -38,4 +44,8 @@
     public Class<?> getRealClass() {
         return realClass;
     }
+    
+    public List<String> getTemplateValues() {
+        return templateValues;
+    }
 }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java Thu Jan 29 18:59:50 2009
@@ -19,9 +19,11 @@
 
 package org.apache.cxf.jaxrs.model;
 
-
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -33,23 +35,22 @@
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 
 public final class URITemplate {
-    
+
     public static final String TEMPLATE_PARAMETERS = "jaxrs.template.parameters";
     public static final String LIMITED_REGEX_SUFFIX = "(/.*)?";
     public static final String UNLIMITED_REGEX_SUFFIX = "(/)?";
     public static final String FINAL_MATCH_GROUP = "FINAL_MATCH_GROUP";
-    
+
     /**
      * The regular expression for matching URI templates and names.
      */
-    private static final Pattern TEMPLATE_NAMES_PATTERN = 
-        Pattern.compile("\\{(\\w[-\\w\\.]*)(\\:(.+?))?\\}");
+    private static final Pattern TEMPLATE_NAMES_PATTERN = Pattern.compile("\\{(\\w[-\\w\\.]*)(\\:(.+?))?\\}");
 
     private static final String DEFAULT_PATH_VARIABLE_REGEX = "([^/]+?)";
     private static final String PATH_UNLIMITED_VARIABLE_REGEX = "(.*?)";
         
     private static final String CHARACTERS_TO_ESCAPE = ".";
-    
+
     private final String template;
     private final List<String> templateVariables = new ArrayList<String>();
     private final List<String> customTemplateVariables = new ArrayList<String>();
@@ -63,16 +64,16 @@
     public URITemplate(String theTemplate, boolean limited) {
         
         this.template = theTemplate;
-        
+
         StringBuilder literalChars = new StringBuilder();
         StringBuilder patternBuilder = new StringBuilder();
-        
+
         // compute a regular expression from URI template
         Matcher matcher = TEMPLATE_NAMES_PATTERN.matcher(template);
         int i = 0;
         while (matcher.find()) {
             templateVariables.add(matcher.group(1).trim());
-            
+
             String substr = escapeCharacters(template.substring(i, matcher.start()));
             literalChars.append(substr);
             patternBuilder.append(substr);
@@ -88,42 +89,42 @@
                 } else {
                     patternBuilder.append(DEFAULT_PATH_VARIABLE_REGEX);
                 }
-            } 
+            }
         }
         String substr = escapeCharacters(template.substring(i, template.length()));
         literalChars.append(substr);
         patternBuilder.append(substr);
 
         literals = literalChars.toString();
-        
+
         int endPos = patternBuilder.length() - 1;
         boolean endsWithSlash = (endPos >= 0) ? patternBuilder.charAt(endPos) == '/' : false;
         if (endsWithSlash) {
             patternBuilder.deleteCharAt(endPos);
         }
         patternBuilder.append(limited ? LIMITED_REGEX_SUFFIX : UNLIMITED_REGEX_SUFFIX);
-        
+
         templateRegexPattern = Pattern.compile(patternBuilder.toString());
     }
 
     public String getLiteralChars() {
         return literals;
     }
-    
+
     public String getValue() {
         return template;
     }
-    
-    public int getNumberOfGroups() {
-        return templateVariables.size();
-    }
-    
-    public int getNumberOfGroupsWithCustomExpression() {
-        return customTemplateVariables.size();
+
+    public List<String> getVariables() {
+        return Collections.unmodifiableList(templateVariables);
+    }
+
+    public List<String> getCustomVariables() {
+        return Collections.unmodifiableList(customTemplateVariables);
     }
-    
+
     private static String escapeCharacters(String expression) {
-        
+
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < expression.length(); i++) {
             char ch = expression.charAt(i);
@@ -131,11 +132,11 @@
         }
         return sb.toString();
     }
-    
+
     private static boolean isReservedCharacter(char ch) {
         return CHARACTERS_TO_ESCAPE.indexOf(ch) != -1;
     }
-    
+
     public boolean match(String uri, MultivaluedMap<String, String> templateVariableToValue) {
 
         if (uri == null) {
@@ -180,46 +181,124 @@
         }
 
         // The right hand side value, might be used to further resolve sub-resources.
-        
+
         String finalGroup = m.group(i);
         templateVariableToValue.putSingle(FINAL_MATCH_GROUP, finalGroup == null ? "/" : finalGroup);
-        
 
         return true;
     }
-    
-    public static URITemplate createTemplate(ClassResourceInfo cri,
-                                             Path path) {
-        
+
+    /**
+     * Substitutes template variables with listed values. List of values is counterpart for
+     * {@link #getVariables() list of variables}. When list of value is shorter than variables substitution
+     * is partial. When variable has pattern, value must fit to pattern, otherwise
+     * {@link IllegalArgumentException} is thrown.
+     * <p>
+     * Example1: for template "/{a}/{b}/{a}" {@link #getVariables()} returns "[a, b, a]"; providing here list
+     * of value "[foo, bar, baz]" results with "/foo/bar/baz".
+     * <p>
+     * Example2: for template "/{a}/{b}/{a}" providing list of values "[foo]" results with "/foo/{b}/{a}".
+     * 
+     * @param values values for variables
+     * @return template with bound variables.
+     * @throws IllegalArgumentException when values is null, any value does not match pattern etc.
+     */
+    public String substitute(List<String> values) throws IllegalArgumentException {
+        if (values == null) {
+            throw new IllegalArgumentException("values is null");
+        }
+        Matcher m = TEMPLATE_NAMES_PATTERN.matcher(template);
+        Iterator<String> valIter = values.iterator();
+        StringBuffer sb = new StringBuffer();
+        while (m.find() && valIter.hasNext()) {
+            String value = valIter.next();
+            String varPattern = m.group(2);
+            if (varPattern != null) {
+                // variable has pattern, matching formats e.g.
+                // for "{a:\d\d}" variable value must have two digits etc.
+                Pattern p = Pattern.compile(varPattern);
+                if (!p.matcher(":" + value).matches()) {
+                    throw new IllegalArgumentException("Value '" + value + "' does not match variable "
+                                                       + m.group());
+                }
+            }
+            m.appendReplacement(sb, value);
+        }
+        m.appendTail(sb);
+        return sb.toString();
+    }
+
+    /**
+     * Substitutes template variables with mapped values. Variables are mapped to values; if not all variables
+     * are bound result will still contain variables. Note that all variables with the same name are replaced
+     * by one value.
+     * <p>
+     * Example: for template "/{a}/{b}/{a}" {@link #getVariables()} returns "[a, b, a]"; providing here
+     * mapping "[a: foo, b: bar]" results with "/foo/bar/foo" (full substitution) and for mapping "[b: baz]"
+     * result is "{a}/baz/{a}" (partial substitution).
+     * 
+     * @param valuesMap map variables to their values; on each value Object.toString() is called.
+     * @return template with bound variables.
+     * @throws IllegalArgumentException when size of list of values differs from list of variables or list
+     *                 contains nulls.
+     */
+    public String substitute(Map<String, ? extends Object> valuesMap) throws IllegalArgumentException {
+        if (valuesMap == null) {
+            throw new IllegalArgumentException("valuesMap is null");
+        }
+        Matcher m = TEMPLATE_NAMES_PATTERN.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            Object value = valuesMap.get(m.group(1));
+            if (value == null) {
+                continue;
+            }
+            String sval = value.toString();
+            String varPattern = m.group(2);
+            if (varPattern != null) {
+                Pattern p = Pattern.compile(varPattern);
+                if (!p.matcher(":" + sval).matches()) {
+                    throw new IllegalArgumentException("Value '" + sval + "' does not match variable "
+                                                       + m.group());
+                }
+            }
+            m.appendReplacement(sb, sval);
+        }
+        m.appendTail(sb);
+        return sb.toString();
+    }
+
+    public static URITemplate createTemplate(ClassResourceInfo cri, Path path) {
+
         if (path == null) {
             return new URITemplate("/");
         }
-        
+
         String pathValue = path.value();
         if (!pathValue.startsWith("/")) {
             pathValue = "/" + pathValue;
         }
-        
+
         return new URITemplate(pathValue, path.limited());
     }
-    
+
     public static int compareTemplates(URITemplate t1, URITemplate t2) {
         String l1 = t1.getLiteralChars();
         String l2 = t2.getLiteralChars();
         if (!l1.equals(l2)) {
-            // descending order 
-            return l1.length() < l2.length() ? 1 : -1; 
+            // descending order
+            return l1.length() < l2.length() ? 1 : -1;
         }
-        
-        int g1 = t1.getNumberOfGroups();
-        int g2 = t2.getNumberOfGroups();
-        // descending order 
+
+        int g1 = t1.templateVariables.size();
+        int g2 = t2.templateVariables.size();
+        // descending order
         int result = g1 < g2 ? 1 : g1 > g2 ? -1 : 0;
         if (result == 0) {
-            int gCustom1 = t1.getNumberOfGroupsWithCustomExpression();
-            int gCustom2 = t2.getNumberOfGroupsWithCustomExpression();
+            int gCustom1 = t1.customTemplateVariables.size();
+            int gCustom2 = t2.customTemplateVariables.size();
             if (gCustom1 != gCustom2) {
-                // descending order 
+                // descending order
                 return gCustom1 < gCustom2 ? 1 : -1;
             }
         }

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Thu Jan 29 18:59:50 2009
@@ -90,7 +90,6 @@
 import org.apache.cxf.jaxrs.provider.AbstractConfigurableProvider;
 import org.apache.cxf.jaxrs.provider.ProviderFactory;
 import org.apache.cxf.message.Message;
-import org.apache.cxf.message.MessageImpl;
 import org.apache.cxf.transport.http.AbstractHTTPDestination;
 
 public final class JAXRSUtils {
@@ -893,11 +892,10 @@
     }
     
     @SuppressWarnings("unchecked")
-    public static Response convertFaultToResponse(Throwable ex, String baseAddress) {
+    public static Response convertFaultToResponse(Throwable ex, String baseAddress, Message inMessage) {
         
         ExceptionMapper mapper = 
-            ProviderFactory.getInstance(baseAddress).createExceptionMapper(ex.getClass(),
-                                                                new MessageImpl());
+            ProviderFactory.getInstance(baseAddress).createExceptionMapper(ex.getClass(), inMessage);
         if (mapper != null) {
             Response excResponse = mapper.toResponse(ex);
             if (excResponse != null) {

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java Thu Jan 29 18:59:50 2009
@@ -21,6 +21,9 @@
 
 import java.lang.reflect.Method;
 import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.cxf.jaxrs.resources.Book;
 import org.apache.cxf.jaxrs.resources.BookStore;
@@ -31,13 +34,70 @@
 
 public class UriBuilderImplTest extends Assert {
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testCtorNull() throws Exception {
+        new UriBuilderImpl(null);
+    }
+
+    @Test
+    public void testCtorAndBuild() throws Exception {
+        URI uri = new URI("http://foo/bar/baz?query=1#fragment");
+        URI newUri = new UriBuilderImpl(uri).build();
+        assertEquals("URI is not built correctly", uri, newUri);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUriNull() throws Exception {
+        new UriBuilderImpl().uri(null);
+    }
+
     @Test
     public void testUri() throws Exception {
         URI uri = new URI("http://foo/bar/baz?query=1#fragment");
         URI newUri = new UriBuilderImpl().uri(uri).build();
-        assertEquals("URI is not built correctly", newUri, uri);
+        assertEquals("URI is not built correctly", uri, newUri);
+    }
+
+    @Test
+    public void testBuildValues() throws Exception {
+        URI uri = new URI("http://zzz");
+        URI newUri = new UriBuilderImpl(uri).path("/{b}/{a}/{b}").build("foo", "bar", "baz");
+        assertEquals("URI is not built correctly", new URI("http://zzz/foo/bar/foo"), newUri);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuildMissingValues() throws Exception {
+        URI uri = new URI("http://zzz");
+        new UriBuilderImpl(uri).path("/{b}/{a}/{b}").build("foo");
     }
 
+    
+    @Test
+    public void testBuildValueWithBrackets() throws Exception {
+        URI uri = new URI("http://zzz");
+        URI newUri = new UriBuilderImpl(uri).path("/{a}").build("{foo}");
+        assertEquals("URI is not built correctly", new URI("http://zzz/%7Bfoo%7D"), newUri);
+    }
+    
+    @Test
+    public void testBuildValuesPct() throws Exception {
+        URI uri = new URI("http://zzz");
+        URI newUri = new UriBuilderImpl(uri).path("/{a}").build("foo%25/bar%");
+        assertEquals("URI is not built correctly", new URI("http://zzz/foo%2525/bar%25"), newUri);
+    }
+
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuildFromMapMissingValues() throws Exception {
+        URI uri = new URI("http://zzz");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("b", "foo");
+        Map<String, String> immutable = Collections.unmodifiableMap(map);
+        new UriBuilderImpl(uri).path("/{b}/{a}/{b}").build(immutable);
+    }
+
+    
+    
     @Test
     public void testAddPath() throws Exception {
         URI uri = new URI("http://foo/bar");
@@ -55,10 +115,24 @@
     }
 
     @Test
+    public void testAddPathSlashes2() throws Exception {
+        URI uri = new URI("http://foo/");
+        URI newUri = new UriBuilderImpl().uri(uri).path("/bar///baz").path("blah//").build();
+        assertEquals("URI is not built correctly", new URI("http://foo/bar/baz/blah/"), newUri);
+    }
+
+    @Test
+    public void testAddPathSlashes3() throws Exception {
+        URI uri = new URI("http://foo/");
+        URI newUri = new UriBuilderImpl().uri(uri).path("/bar/").path("").path("baz").build();
+        assertEquals("URI is not built correctly", new URI("http://foo/bar/baz"), newUri);
+    }
+
+    @Test
     public void testAddPathClass() throws Exception {
         URI uri = new URI("http://foo/");
-        URI newUri = new UriBuilderImpl().uri(uri).path(BookStore.class).path("bar").build();
-        assertEquals("URI is not built correctly", new URI("http://foo/bookstore/bar"), newUri);
+        URI newUri = new UriBuilderImpl().uri(uri).path(BookStore.class).path("/").build();
+        assertEquals("URI is not built correctly", new URI("http://foo/bookstore/"), newUri);
     }
 
     @Test(expected = IllegalArgumentException.class)

Modified: cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java (original)
+++ cxf/branches/2.1.x-fixes/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/URITemplateTest.java Thu Jan 29 18:59:50 2009
@@ -18,10 +18,15 @@
  */
 package org.apache.cxf.jaxrs.model;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.jaxrs.impl.MetadataMap;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -50,69 +55,69 @@
     public void testMatchBasic() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{id}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/123/", values);
         assertTrue(match);
         String value = values.getFirst("id");
         assertEquals("123", value);
     }
-    
+
     @Test
     public void testMatchWithMatrixAndTemplate() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{id}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/123;123456/", values);
         assertTrue(match);
         String value = values.getFirst("id");
         assertEquals("123;123456", value);
     }
-    
+
     @Test
     public void testMatchWithMatrixOnClearPath1() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{id}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers;123456/123/", values);
         assertTrue(match);
         String value = values.getFirst("id");
         assertEquals("123", value);
     }
-    
+
     @Test
     public void testMatchWithMatrixOnClearPath2() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{id}/orders/{order}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         assertTrue(uriTemplate.match("/customers;123456/123/orders;456/3", values));
         assertEquals("123", values.getFirst("id"));
         assertEquals("3", values.getFirst("order"));
     }
-    
+
     @Test
     public void testMatchWithMatrixOnClearPath3() throws Exception {
         URITemplate uriTemplate = new URITemplate("/{id}/customers/");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/123/customers;123456/", values);
         assertTrue(match);
         String value = values.getFirst("id");
         assertEquals("123", value);
     }
-    
+
     @Test
     public void testMatchWithMatrixOnClearPath4() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         assertTrue(uriTemplate.match("/customers;123456/123/orders;456/3", values));
     }
-    
+
     @Test
     public void testMatchBasicTwoParametersVariation1() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/{name}/{department}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/john/CS", values);
         assertTrue(match);
         String name = values.getFirst("name");
@@ -120,111 +125,111 @@
         assertEquals("john", name);
         assertEquals("CS", department);
     }
-    
+
     @Test
     public void testMatchBasicTwoParametersVariation2() throws Exception {
         URITemplate uriTemplate = new URITemplate("/customers/name/{name}/dep/{department}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/name/john/dep/CS", values);
         assertTrue(match);
         String name = values.getFirst("name");
         String department = values.getFirst("department");
         assertEquals("john", name);
         assertEquals("CS", department);
-    }    
-    
+    }
+
     @Test
     public void testURITemplateWithSubResource() throws Exception {
-        //So "/customers" is the URITemplate for the root resource class
+        // So "/customers" is the URITemplate for the root resource class
         URITemplate uriTemplate = new URITemplate("/customers");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/123", values);
         assertTrue(match);
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/123", subResourcePath);
     }
-        
+
     @Test
     public void testURITemplateWithSubResourceVariation2() throws Exception {
-        //So "/customers" is the URITemplate for the root resource class
+        // So "/customers" is the URITemplate for the root resource class
         URITemplate uriTemplate = new URITemplate("/customers");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/customers/name/john/dep/CS", values);
         assertTrue(match);
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/name/john/dep/CS", subResourcePath);
     }
-        
+
     @Test
-    /* Test a sub-resource locator method like this
-     * @HttpMethod("GET") @UriTemplate("/books/{bookId}/") 
-     * public Book getBook(@UriParam("bookId") String id)
+    /*
+     * Test a sub-resource locator method like this @HttpMethod("GET") @UriTemplate("/books/{bookId}/") public
+     * Book getBook(@UriParam("bookId") String id)
      */
     public void testURITemplateWithSubResourceVariation3() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId}/");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertTrue(match);
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/chapter/1", subResourcePath);
     }
-    
+
     @Test
     public void testBasicCustomExpression() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:[^/]+?}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertTrue(match);
         assertEquals("123", values.getFirst("bookId"));
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/chapter/1", subResourcePath);
     }
-    
+
     @Test
     public void testBasicCustomExpression2() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:123}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertTrue(match);
         assertEquals("123", values.getFirst("bookId"));
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/chapter/1", subResourcePath);
     }
-    
+
     @Test
     public void testBasicCustomExpression3() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:\\d\\d\\d}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertTrue(match);
         assertEquals("123", values.getFirst("bookId"));
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/chapter/1", subResourcePath);
     }
-    
+
     @Test
     public void testEscaping() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/a.db");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         assertTrue(uriTemplate.match("/books/a.db", values));
         assertFalse(uriTemplate.match("/books/adbc", values));
         assertFalse(uriTemplate.match("/books/acdb", values));
 
     }
-    
+
     @Test
     public void testBasicCustomExpression4() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:...\\.}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         assertTrue(uriTemplate.match("/books/123.", values));
         assertEquals("123.", values.getFirst("bookId"));
         values.clear();
@@ -233,12 +238,12 @@
         assertFalse(uriTemplate.match("/books/abcd", values));
         assertFalse(uriTemplate.match("/books/abc", values));
     }
-    
+
     @Test
     public void testMultipleExpression2() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:123}/chapter/{id}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertTrue(match);
         assertEquals("123", values.getFirst("bookId"));
@@ -246,16 +251,16 @@
         String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
         assertEquals("/", subResourcePath);
     }
-    
+
     @Test
     public void testFailCustomExpression() throws Exception {
         URITemplate uriTemplate = new URITemplate("/books/{bookId:124}");
         MultivaluedMap<String, String> values = new MetadataMap<String, String>();
-        
+
         boolean match = uriTemplate.match("/books/123/chapter/1", values);
         assertFalse(match);
     }
-    
+
     @Test
     public void testBaseTail1() {
         URITemplate uriTemplate = new URITemplate("/{base:base.+}/{tail}");
@@ -265,7 +270,7 @@
         assertEquals("base1", values.getFirst("base"));
         assertEquals("tails", values.getFirst("tail"));
     }
-    
+
     @Test
     public void testBaseTail2() {
         URITemplate uriTemplate = new URITemplate("/{base:.+base}/{tail}");
@@ -276,7 +281,7 @@
         assertEquals("1base", values.getFirst("base"));
         assertEquals("tails", values.getFirst("tail"));
     }
-    
+
     @Test
     public void testBaseTail3() {
         URITemplate uriTemplate = new URITemplate("/{base:base.+suffix}/{tail}");
@@ -287,4 +292,100 @@
         assertEquals("base1suffix", values.getFirst("base"));
         assertEquals("tails", values.getFirst("tail"));
     }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSubstituteListNull() throws Exception {
+        new URITemplate("anything").substitute((List<String>)null);
+    }
+
+    @Test
+    public void testSubstituteList() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{b:\\d\\d}/{c}");
+        List<String> list = Arrays.asList("foo", "99", "baz");
+        assertEquals("Wrong substitution", "/foo/foo/99/baz", ut.substitute(list));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSubstituteListWrongPattern() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{b:\\d\\d}");
+        List<String> list = Arrays.asList("foo", "not-two-digits");
+        ut.substitute(list);
+    }
+
+    @Test
+    public void testSubstituteListSameVars() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{a}/{a}");
+        List<String> list = Arrays.asList("bar", "baz", "blah");
+        assertEquals("Wrong substitution", "/foo/bar/baz/blah", ut.substitute(list));
+    }
+    
+    @Test
+    public void testSubstituteListIncomplete() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{c}/{b}");
+        List<String> list = Arrays.asList("bar", "baz");
+        assertEquals("Wrong substitution", "/foo/bar/baz/{b}", ut.substitute(list));
+    }
+
+    @Test
+    public void testSubstituteListExceeding() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{b}");
+        List<String> list = Arrays.asList("bar", "baz", "blah");
+        assertEquals("Wrong substitution", "/foo/bar/baz", ut.substitute(list));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSubstituteMapNull() throws Exception {
+        new URITemplate("anything").substitute((Map<String, String>)null);
+    }
+
+    @Test
+    public void testSubstituteMap() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{b:\\d\\d}/{c}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("c", "foo");
+        map.put("b", "11");
+        map.put("a", "bar");
+        assertEquals("Wrong substitution", "/foo/bar/11/foo", ut.substitute(map));
+    }
+
+    @Test
+    public void testSubstituteMapSameVars() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{a}/{a}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("a", "bar");
+        assertEquals("Wrong substitution", "/foo/bar/bar/bar", ut.substitute(map));
+    }
+
+    @Test
+    public void testSubstituteMapIncomplete() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{b}/{a:\\d}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("b", "bar");
+        assertEquals("Wrong substitution", "/foo/{a}/bar/{a:\\d}", ut.substitute(map));
+    }
+
+    @Test
+    public void testSubstituteMapSameVarWithPattern() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{a:\\d}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("a", "0");
+        assertEquals("Wrong substitution", "/foo/0/0", ut.substitute(map));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSubstituteMapSameVarWithPatternFail() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}/{a:\\d}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("a", "not-a-digit");
+        ut.substitute(map);
+    }
+
+    @Test
+    public void testSubstituteMapExceeding() throws Exception {
+        URITemplate ut = new URITemplate("/foo/{a}");
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("b", "baz");
+        map.put("a", "blah");
+        assertEquals("Wrong substitution", "/foo/blah", ut.substitute(map));
+    }
 }

Modified: cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=738961&r1=738960&r2=738961&view=diff
==============================================================================
--- cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/branches/2.1.x-fixes/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Thu Jan 29 18:59:50 2009
@@ -704,9 +704,9 @@
 
     @Test
     public void testUriInfoMatchedUrisDecode() throws Exception {
-        String expected = "[/bookstore/booksubresource/{bookId}/, "
-                          + "/bookstore/booksubresource/{bookId}/chapters/sub/{chapterid}/, "
-                          + "/bookstore/booksubresource/{bookId}/chapters/sub/{chapterid}/matched!uris]";
+        String expected = "[/bookstore/booksubresource/123/, "
+                          + "/bookstore/booksubresource/123/chapters/sub/1/, "
+                          + "/bookstore/booksubresource/123/chapters/sub/1/matched!uris]";
         getAndCompare("http://localhost:9080/bookstore/"
                       + "booksubresource/123/chapters/sub/1/matched%21uris?decode=true", 
                       expected, 
@@ -716,9 +716,9 @@
     @Test
     public void testUriInfoMatchedUrisNoDecode() throws Exception {
         //note '%21' instead of '!'
-        String expected = "[/bookstore/booksubresource/{bookId}/, "
-            + "/bookstore/booksubresource/{bookId}/chapters/sub/{chapterid}/, "
-            + "/bookstore/booksubresource/{bookId}/chapters/sub/{chapterid}/matched%21uris]";
+        String expected = "[/bookstore/booksubresource/123/, "
+            + "/bookstore/booksubresource/123/chapters/sub/1/, "
+            + "/bookstore/booksubresource/123/chapters/sub/1/matched%21uris]";
         getAndCompare("http://localhost:9080/bookstore/"
                       + "booksubresource/123/chapters/sub/1/matched%21uris?decode=false", 
                       expected,



Mime
View raw message