Index: src/main/java/org/jboss/resteasy/client/core/ClientProxy.java =================================================================== --- src/main/java/org/jboss/resteasy/client/core/ClientProxy.java (revision 1417) +++ src/main/java/org/jboss/resteasy/client/core/ClientProxy.java (working copy) @@ -10,10 +10,10 @@ */ public class ClientProxy implements InvocationHandler { - private Map methodMap; + private Map methodMap; private Class clazz; - public ClientProxy(Map methodMap) + public ClientProxy(Map methodMap) { this.methodMap = methodMap; } @@ -36,7 +36,7 @@ // transactional Resources to a Collection, and it calls equals and // hashCode. - ClientInvoker clientInvoker = methodMap.get(method); + Invoker clientInvoker = methodMap.get(method); if (clientInvoker == null) { if (method.getName().equals("equals")) @@ -58,8 +58,9 @@ else if (method.getName().equals("applyClientInvokerModifier")) { ClientInvokerModifier modifier = (ClientInvokerModifier) args[0]; - for (ClientInvoker invoker : methodMap.values()) - modifier.modify(invoker); + for (Invoker invoker : methodMap.values()) + if(invoker instanceof ClientInvoker) + modifier.modify((ClientInvoker)invoker); return null; } Index: src/main/java/org/jboss/resteasy/client/core/SubResourceInvoker.java =================================================================== --- src/main/java/org/jboss/resteasy/client/core/SubResourceInvoker.java (revision 0) +++ src/main/java/org/jboss/resteasy/client/core/SubResourceInvoker.java (revision 0) @@ -0,0 +1,61 @@ +package org.jboss.resteasy.client.core; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URI; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jboss.resteasy.client.ClientExecutor; +import org.jboss.resteasy.client.ProxyFactory; +import org.jboss.resteasy.client.core.extractors.EntityExtractorFactory; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +public class SubResourceInvoker implements Invoker +{ + final ResteasyProviderFactory providerFactory; + final ClientExecutor executor; + final EntityExtractorFactory extractorFactory; + final Class iface; + final String base; + final String format; + + public SubResourceInvoker(URI uri, Method method, ResteasyProviderFactory providerFactory, ClientExecutor executor, EntityExtractorFactory extractorFactory) + { + String base = uri.toString(); + if(!base.endsWith("/")) + base = base + "/"; + this.base = base; + this.iface = method.getReturnType(); + this.providerFactory = providerFactory; + this.executor = executor; + this.extractorFactory = extractorFactory; + String path = method.getAnnotation(Path.class).value(); + if(path.startsWith("/")) + path = path.substring(1); + Annotation[][] params = method.getParameterAnnotations(); + int index = 1; + for(Annotation[] param : params) + { + for(Annotation a : param) + { + if(a instanceof PathParam) + { + String name = ((PathParam)a).value(); + path = path.replace("{" + name + "}", "%" + index + "$s"); + break; + } + } + index++; + } + this.format = path; + } + + @Override + public Object invoke(Object[] args) + { + String path = String.format(format, args); + return ProxyFactory.create(iface, ProxyFactory.createUri(base + path), executor, providerFactory, extractorFactory); + } +} Index: src/main/java/org/jboss/resteasy/client/core/Invoker.java =================================================================== --- src/main/java/org/jboss/resteasy/client/core/Invoker.java (revision 0) +++ src/main/java/org/jboss/resteasy/client/core/Invoker.java (revision 0) @@ -0,0 +1,6 @@ +package org.jboss.resteasy.client.core; + +public interface Invoker +{ + public Object invoke(Object[] args); +} Index: src/main/java/org/jboss/resteasy/client/core/ClientInvoker.java =================================================================== --- src/main/java/org/jboss/resteasy/client/core/ClientInvoker.java (revision 1417) +++ src/main/java/org/jboss/resteasy/client/core/ClientInvoker.java (working copy) @@ -27,7 +27,7 @@ * @version $Revision: 1 $ */ @SuppressWarnings("unchecked") -public class ClientInvoker extends ClientInterceptorRepositoryImpl +public class ClientInvoker extends ClientInterceptorRepositoryImpl implements Invoker { protected ResteasyProviderFactory providerFactory; protected String httpMethod; Index: src/main/java/org/jboss/resteasy/client/ProxyFactory.java =================================================================== --- src/main/java/org/jboss/resteasy/client/ProxyFactory.java (revision 1417) +++ src/main/java/org/jboss/resteasy/client/ProxyFactory.java (working copy) @@ -1,8 +1,20 @@ package org.jboss.resteasy.client; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.Path; + import org.jboss.resteasy.client.core.ClientInvoker; import org.jboss.resteasy.client.core.ClientInvokerInterceptorFactory; import org.jboss.resteasy.client.core.ClientProxy; +import org.jboss.resteasy.client.core.Invoker; +import org.jboss.resteasy.client.core.SubResourceInvoker; import org.jboss.resteasy.client.core.extractors.DefaultEntityExtractorFactory; import org.jboss.resteasy.client.core.extractors.EntityExtractorFactory; import org.jboss.resteasy.client.core.marshallers.ResteasyClientProxy; @@ -10,14 +22,6 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.util.IsHttpMethod; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - /** * @author Bill Burke * @version $Revision: 1 $ @@ -73,7 +77,7 @@ public static T create(Class clazz, URI baseUri, ClientExecutor executor, ResteasyProviderFactory providerFactory, EntityExtractorFactory extractorFactory, Map requestAttributes) { - HashMap methodMap = new HashMap(); + HashMap methodMap = new HashMap(); if (providerFactory instanceof ProviderFactoryDelegate) { @@ -82,8 +86,17 @@ for (Method method : clazz.getMethods()) { - ClientInvoker invoker = createClientInvoker(clazz, method, baseUri, executor, + Invoker invoker; + Set httpMethods = IsHttpMethod.getHttpMethods(method); + if(httpMethods == null || httpMethods.size() == 0 && method.isAnnotationPresent(Path.class) && method.getReturnType().isInterface()) + { + invoker = new SubResourceInvoker(baseUri, method, providerFactory, executor, extractorFactory); + } + else + { + invoker = createClientInvoker(clazz, method, baseUri, executor, providerFactory, extractorFactory, requestAttributes); + } methodMap.put(method, invoker); }