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 2010/03/09 18:53:56 UTC

svn commit: r921014 [1/2] - in /cxf/trunk: common/common/src/main/java/org/apache/cxf/jaxb/ rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/ rt/frontend/jaxrs/src/main/...

Author: sergeyb
Date: Tue Mar  9 17:53:56 2010
New Revision: 921014

URL: http://svn.apache.org/viewvc?rev=921014&view=rev
Log:
JAXRS : introducing a provider capable of generating and serving the client code

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java   (with props)
Modified:
    cxf/trunk/common/common/src/main/java/org/apache/cxf/jaxb/JAXBUtils.java
    cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/DynamicClientFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerResourceCreatedSpringProviderTest.java
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_providers/WEB-INF/beans.xml

Modified: cxf/trunk/common/common/src/main/java/org/apache/cxf/jaxb/JAXBUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/common/common/src/main/java/org/apache/cxf/jaxb/JAXBUtils.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/common/common/src/main/java/org/apache/cxf/jaxb/JAXBUtils.java (original)
+++ cxf/trunk/common/common/src/main/java/org/apache/cxf/jaxb/JAXBUtils.java Tue Mar  9 17:53:56 2010
@@ -664,6 +664,45 @@ public final class JAXBUtils {
             throw new JAXBException(ex);
         }
     }
+
+    public static SchemaCompiler createSchemaCompilerWithDefaultAllocator(Set<String> allocatorSet) {
+        
+        try {
+            SchemaCompiler compiler = JAXBUtils.createSchemaCompiler();
+            Object allocator = ReflectionInvokationHandler
+                .createProxyWrapper(new DefaultClassNameAllocator(allocatorSet),
+                                JAXBUtils.getParamClass(compiler, "setClassNameAllocator"));
+
+            compiler.setClassNameAllocator(allocator);
+            return compiler;    
+        } catch (JAXBException e1) {
+            throw new IllegalStateException("Unable to create schema compiler", e1);
+        }
+        
+    }
+    
+    public static void logGeneratedClassNames(Logger logger, JCodeModel codeModel) {
+        if (!logger.isLoggable(Level.INFO)) {
+            return;
+        }
+        
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (Iterator<JPackage> itr = codeModel.packages(); itr.hasNext();) {
+            JPackage package1 = itr.next();
+            
+            for (Iterator<JDefinedClass> citr = package1.classes(); citr.hasNext();) {
+                if (!first) {
+                    sb.append(", ");
+                } else {
+                    first = false;
+                }
+                sb.append(citr.next().fullName());
+            }
+        }
+        
+        logger.log(Level.INFO, "Created classes: " + sb.toString());
+    }
     
     public static Object createFileCodeWriter(File f) throws JAXBException {
         try {
@@ -834,6 +873,32 @@ public final class JAXBUtils {
         }
     }
     
+    public static class DefaultClassNameAllocator {
+        private final Set<String> typesClassNames;
+
+        public DefaultClassNameAllocator() {
+            this(new HashSet<String>());
+        }
+        
+        public DefaultClassNameAllocator(Set<String> set) {
+            typesClassNames = set;
+        }
+
+        public String assignClassName(String packageName, String className) {
+            String fullClassName = className;
+            String fullPckClass = packageName + "." + fullClassName;
+            int cnt = 0;
+            while (typesClassNames.contains(fullPckClass)) {
+                cnt++;
+                fullClassName = className + cnt;
+                fullPckClass = packageName + "." + fullClassName;
+            }
+            typesClassNames.add(fullPckClass);
+            return fullClassName;
+        }
+       
+    }
+    
     public static interface SchemaCompiler {
 
         void setErrorListener(Object elForRun);

Modified: cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/DynamicClientFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/DynamicClientFactory.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/DynamicClientFactory.java (original)
+++ cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/endpoint/dynamic/DynamicClientFactory.java Tue Mar  9 17:53:56 2010
@@ -34,7 +34,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
@@ -258,24 +257,15 @@ public class DynamicClientFactory {
         //all SI's should have the same schemas
         Collection<SchemaInfo> schemas = svc.getServiceInfos().get(0).getSchemas();
 
-        SchemaCompiler compiler;
-        try {
-            compiler = JAXBUtils.createSchemaCompiler();
-        } catch (JAXBException e1) {
-            throw new IllegalStateException("Unable to create schema compiler", e1);
-        }
+        SchemaCompiler compiler = 
+            JAXBUtils.createSchemaCompilerWithDefaultAllocator(new HashSet<String>());
+        
         Object elForRun = ReflectionInvokationHandler
             .createProxyWrapper(new InnerErrorListener(wsdlUrl),
                                 JAXBUtils.getParamClass(compiler, "setErrorListener"));
         
         compiler.setErrorListener(elForRun);
         
-        Object allocator = ReflectionInvokationHandler
-            .createProxyWrapper(new ClassNameAllocatorImpl(),
-                                JAXBUtils.getParamClass(compiler, "setClassNameAllocator"));
-
-        compiler.setClassNameAllocator(allocator);
-
         addSchemas(wsdlUrl, schemas, compiler);
         addBindingFiles(bindingFiles, compiler);
         S2JJAXBModel intermediateModel = compiler.bind();
@@ -295,7 +285,7 @@ public class DynamicClientFactory {
             }
             sb.append(jpackage.name());
         }
-        outputDebug(codeModel);
+        JAXBUtils.logGeneratedClassNames(LOG, codeModel);
         
         String packageList = sb.toString();
 
@@ -413,30 +403,6 @@ public class DynamicClientFactory {
         return false;
     }
 
-    private void outputDebug(JCodeModel codeModel) {
-        if (!LOG.isLoggable(Level.INFO)) {
-            return;
-        }
-        
-        StringBuilder sb = new StringBuilder();
-        boolean first = true;
-        for (Iterator<JPackage> itr = codeModel.packages(); itr.hasNext();) {
-            JPackage package1 = itr.next();
-            
-            for (Iterator<JDefinedClass> citr = package1.classes(); citr.hasNext();) {
-                if (!first) {
-                    sb.append(", ");
-                } else {
-                    first = false;
-                }
-                sb.append(citr.next().fullName());
-            }
-        }
-        
-        LOG.log(Level.INFO, "Created classes: " + sb.toString());
-        
-    }
-
     private void addSchemas(String wsdlUrl, Collection<SchemaInfo> schemas, SchemaCompiler compiler) {
         int num = 1;
         for (SchemaInfo schema : schemas) {
@@ -689,26 +655,4 @@ public class DynamicClientFactory {
         this.jaxbContextProperties = jaxbContextProperties;
     }
     
-    
-    
-    public static class ClassNameAllocatorImpl {
-        private final Set<String> typesClassNames = new HashSet<String>();
-
-        public ClassNameAllocatorImpl() {
-        }
-
-        public String assignClassName(String packageName, String className) {
-            String fullClassName = className;
-            String fullPckClass = packageName + "." + fullClassName;
-            int cnt = 0;
-            while (typesClassNames.contains(fullPckClass)) {
-                cnt++;
-                fullClassName = className + cnt;
-                fullPckClass = packageName + "." + fullClassName;
-            }
-            typesClassNames.add(fullPckClass);
-            return fullClassName;
-        }
-       
-    }
 }

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java?rev=921014&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java Tue Mar  9 17:53:56 2010
@@ -0,0 +1,891 @@
+/**
+ * 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.ext.codegen;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXParseException;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.common.util.ReflectionInvokationHandler;
+import org.apache.cxf.common.xmlschema.XmlSchemaConstants;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxb.JAXBUtils;
+import org.apache.cxf.jaxb.JAXBUtils.JCodeModel;
+import org.apache.cxf.jaxb.JAXBUtils.S2JJAXBModel;
+import org.apache.cxf.jaxb.JAXBUtils.SchemaCompiler;
+import org.apache.cxf.jaxrs.ext.RequestHandler;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.ProviderInfo;
+import org.apache.cxf.jaxrs.model.wadl.WadlGenerator;
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.message.Message;
+
+public class CodeGeneratorProvider implements RequestHandler {
+    public static final String CODE_QUERY = "_code";
+    public static final String LANGUAGE_QUERY = "_lang";
+    public static final String OS_QUERY = "_os";
+    public static final String SOURCE_QUERY = "_source";
+    public static final String CODE_TYPE_QUERY = "_codeType";
+    public static final String CODE_TYPE_GRAMMAR = "grammar";
+    public static final String CODE_TYPE_PROXY = "proxy";
+    public static final String CODE_TYPE_WEB = "web";
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(CodeGeneratorProvider.class);
+    private static final Set<String> SUPPORTED_LANGUAGES = new HashSet<String>(
+        Arrays.asList(new String[]{"java"}));
+    
+    private static final String TMPDIR = System.getProperty("java.io.tmpdir");
+    private static final String TAB = "    "; 
+    
+    private static final Map<String, Class<?>> HTTP_METHOD_ANNOTATIONS;
+    private static final Map<String, Class<?>> PARAM_ANNOTATIONS;
+    
+    static {
+        HTTP_METHOD_ANNOTATIONS = new HashMap<String, Class<?>>();
+        HTTP_METHOD_ANNOTATIONS.put("get", GET.class);
+        HTTP_METHOD_ANNOTATIONS.put("put", PUT.class);
+        HTTP_METHOD_ANNOTATIONS.put("post", POST.class);
+        HTTP_METHOD_ANNOTATIONS.put("delete", DELETE.class);
+        HTTP_METHOD_ANNOTATIONS.put("head", HEAD.class);
+        HTTP_METHOD_ANNOTATIONS.put("options", OPTIONS.class);
+        
+        PARAM_ANNOTATIONS = new HashMap<String, Class<?>>();
+        PARAM_ANNOTATIONS.put("template", PathParam.class);
+        PARAM_ANNOTATIONS.put("header", HeaderParam.class);
+        PARAM_ANNOTATIONS.put("query", QueryParam.class);
+        PARAM_ANNOTATIONS.put("matrix", MatrixParam.class);
+    }
+
+    private Comparator<String> importsComparator;
+    private UriInfo ui;
+    private boolean generateInterfaces = true;
+    
+    
+    @Context
+    public void setUriInfo(UriInfo uriInfo) {
+        this.ui = uriInfo;
+    }
+    
+    public Response handleRequest(Message m, ClassResourceInfo resourceClass) {
+        
+        if (!"GET".equals(m.get(Message.HTTP_REQUEST_METHOD))) {
+            return null;
+        }
+        
+        if (ui.getQueryParameters().containsKey(SOURCE_QUERY)) {
+            synchronized (this) { 
+                return getSource(new File(TMPDIR, getStem(resourceClass, "zip")));
+            }
+        }
+        
+        String codeQuery = ui.getQueryParameters().getFirst(CODE_QUERY);
+        if (codeQuery == null) {
+            return null;
+        }
+        
+        String language = ui.getQueryParameters().getFirst(LANGUAGE_QUERY);
+        if (language != null && !SUPPORTED_LANGUAGES.contains(language)) {
+            return Response.noContent().entity("Unsupported language" + language).type("text/plain").build();
+        }
+        return doHandleRequest(m, resourceClass);
+    }
+    
+    protected Response doHandleRequest(Message m, ClassResourceInfo resourceClass) { 
+        synchronized (this) {
+            File zipDir = new File(TMPDIR, getStem(resourceClass, "zip"));
+            Response r = getLink(zipDir, m);
+            if (r != null) {
+                return r;
+            }
+            
+            File srcDir = new File(TMPDIR, getStem(resourceClass, "src"));
+            if (!srcDir.exists() && !srcDir.mkdir()) {
+                throw new IllegalStateException("Unable to create working directory " + srcDir.getPath());
+            }
+            String codeType = ui.getQueryParameters().getFirst(CODE_TYPE_QUERY);
+            try {
+                String wadl = getWadl(m, resourceClass);
+                if (wadl == null) {
+                    LOG.warning("WADL for " 
+                         + (resourceClass != null ? resourceClass.getServiceClass().getName() 
+                             : "this service")
+                         + " can not be loaded");
+                    return Response.noContent().build();
+                }
+                generateSource(wadl, srcDir, codeType);
+                zipSource(srcDir, zipDir);
+                return getLink(zipDir, m);
+            } catch (Exception ex) {
+                LOG.warning("Code can not be generated for " 
+                            + resourceClass != null ? resourceClass.getServiceClass().getName() 
+                                : "this service");
+                FileUtils.removeDir(zipDir);
+                return Response.noContent().build();
+            } finally {
+                FileUtils.removeDir(srcDir);
+            }
+        }
+    }
+    
+    private void zipSource(File srcDir, File zipDir) throws Exception {
+        if (!zipDir.exists()) {
+            zipDir.mkdir();
+        }
+        String pathSep = getPathSep();
+        File zipFile = new File(zipDir.getAbsolutePath(), "src.zip");
+        zipFile.createNewFile();
+        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
+        List<File> srcFiles = FileUtils.getFilesRecurse(srcDir, ".+\\.java$");
+        for (File f : srcFiles) {
+            String entryName = f.getAbsolutePath().substring(srcDir.getAbsolutePath().length() + 1);
+            entryName = entryName.replace(".", pathSep).replace(pathSep + "java", ".java");
+            zos.putNextEntry(new ZipEntry(entryName));
+            IOUtils.copy(new FileInputStream(f), zos);
+        }
+        zos.close();
+    }
+    
+    private String getLineSep() {
+        String os = ui.getQueryParameters().getFirst(OS_QUERY);
+        if (os == null) {
+            return "\r\n";
+        }
+        return "unix".equals(os) ? "\r" : "\r\n";
+    }
+    
+    protected String getPathSep() {
+        String os = ui.getQueryParameters().getFirst(OS_QUERY);
+        if (os == null) {
+            return "\\";
+        }
+        return "unix".equals(os) ? "/" : "\\";
+    }
+    
+    private Response getSource(File zipDir) {
+        if (zipDir.exists()) {
+            File zipFile = new File(zipDir.getAbsolutePath(), "src.zip");
+            if (zipFile.exists()) {
+                try {
+                    return Response.ok().type("application/zip").entity(new FileInputStream(zipFile)).build();
+                } catch (FileNotFoundException ex) {
+                    // should not happen given we've checked it exists
+                    throw new WebApplicationException();
+                }
+            }
+        } 
+        return Response.noContent().build();
+        
+    }
+    
+    private Response getLink(File zipDir, Message m) {
+        if (zipDir.exists() && new File(zipDir.getAbsolutePath(), "src.zip").exists()) {
+            UriBuilder builder = ui.getAbsolutePathBuilder();
+            String link = builder.queryParam(SOURCE_QUERY).build().toString();
+            // TODO : move it into a resource template
+            StringBuilder sb = new StringBuilder();
+            sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
+            sb.append("<head><title>Download the source</title></head>");
+            sb.append("<body>");
+            sb.append("<h1>Link:</h1><br/>");
+            sb.append("<ul>" + "<a href=\"" + link + "\">" + link + "</a>" + "</ul>");
+            sb.append("</body>");
+            sb.append("</html>");
+            m.getExchange().put(JAXRSUtils.IGNORE_MESSAGE_WRITERS, true);
+            return Response.ok().type("application/xhtml+xml").entity(
+                sb.toString()).build();
+        }
+        return null;
+    }
+    
+    public void removeCode(ClassResourceInfo cri) {
+        removeCode(new File(TMPDIR, getStem(cri, "src")));
+        removeCode(new File(TMPDIR, getStem(cri, "zip")));
+    }
+    
+    protected String getStem(ClassResourceInfo cri, String suffix) {
+        if (cri == null) {
+            return "cxf-jaxrs-" + suffix;
+        } else {
+            return "cxf-jaxrs-" + cri.getServiceClass().getName() + "-" + suffix; 
+        }
+    }
+    
+    private static void removeCode(File src) {
+        if (src.exists()) {
+            FileUtils.removeDir(src);
+        }
+    }
+    
+    protected String getWadl(Message m, ClassResourceInfo resourceClass) {
+        m.put(Message.QUERY_STRING, WadlGenerator.WADL_QUERY);
+        
+        List<ProviderInfo<RequestHandler>> shs = ProviderFactory.getInstance(m).getRequestHandlers();
+        // this is actually being tested by ProviderFactory unit tests but just in case
+        // WadlGenerator, the custom or default one, must be the first one
+        if (shs.size() > 0 && shs.get(0).getProvider() instanceof WadlGenerator) {
+            WadlGenerator wg = (WadlGenerator)shs.get(0).getProvider();
+            wg = new WadlGenerator(wg);
+            wg.setAddResourceAndMethodIds(true);
+            Response r = wg.handleRequest(m, resourceClass);
+            return r == null ? null : (String)r.getEntity();
+        }
+        return null;
+    }
+
+    protected void generateSource(String wadl, File srcDir, String codeType) {
+        Element appElement = readWadl(wadl);
+        
+        Set<String> typeClassNames = new HashSet<String>();
+        List<Element> schemaElements = getSchemaElements(appElement);
+        if (!schemaElements.isEmpty()) {
+            // generate classes from schema
+            JCodeModel codeModel = createCodeModel(schemaElements, typeClassNames);
+            if (codeModel != null) {
+                generateClassesFromSchema(codeModel, srcDir);
+            }
+        }
+        
+        if (!CODE_TYPE_GRAMMAR.equals(codeType)) {
+            generateResourceClasses(appElement, schemaElements, typeClassNames, srcDir);
+        }
+    }
+    
+    private void generateResourceClasses(Element appElement, List<Element> schemaElements, 
+                                         Set<String> typeClassNames, File src) {
+        List<Element> resourcesEls = DOMUtils.getChildrenWithName(appElement, 
+            WadlGenerator.WADL_NS, "resources");
+        if (resourcesEls.size() != 1) {
+            throw new IllegalStateException("WADL resources element is missing");
+        }
+        
+        List<Element> resourceEls = DOMUtils.getChildrenWithName(resourcesEls.get(0), 
+            WadlGenerator.WADL_NS, "resource");
+        if (resourceEls.size() == 0) {
+            throw new IllegalStateException("WADL has no resource elements");
+        }
+        
+        GrammarInfo gInfo = getGrammarInfo(appElement, schemaElements);
+        for (Element resource : resourceEls) {
+            writeResourceClass(resource, typeClassNames, gInfo, src);
+        }
+        
+        generateMainClass(resourcesEls.get(0), src);
+        
+    }
+    
+    private GrammarInfo getGrammarInfo(Element appElement, List<Element> schemaElements) {
+        
+        if (schemaElements.isEmpty()) {
+            return null;
+        }
+        
+        Map<String, String> nsMap = new HashMap<String, String>();
+        NamedNodeMap attrMap = appElement.getAttributes();
+        for (int i = 0; i < attrMap.getLength(); i++) {
+            Node node = attrMap.item(i);
+            String nodeName = node.getNodeName();
+            if (nodeName.startsWith("xmlns:")) {
+                String nsValue = node.getNodeValue();
+                nsMap.put(nodeName.substring(6), nsValue);
+            }
+        }
+        Map<String, String> elementTypeMap = new HashMap<String, String>();
+        for (Element schemaEl : schemaElements) {
+            List<Element> elementEls = DOMUtils.getChildrenWithName(schemaEl, 
+                 XmlSchemaConstants.XSD_NAMESPACE_URI, "element");
+            for (Element el : elementEls) {
+                String type = el.getAttribute("type");
+                if (type.length() > 0) {
+                    String[] pair = type.split(":");
+                    elementTypeMap.put(el.getAttribute("name"), pair.length == 1 ? pair[0] : pair[1]);
+                }
+            }
+        }
+        return new GrammarInfo(nsMap, elementTypeMap);
+    }
+    
+    public void generateMainClass(Element resourcesEl, File src) {
+        
+    }
+    
+    private void writeResourceClass(Element rElement, Set<String> typeClassNames, 
+                                    GrammarInfo gInfo, File src) {
+        String resourceId = rElement.getAttribute("id");
+        String path = rElement.getAttribute("path");
+        if (resourceId.length() == 0) {
+            LOG.warning("Resource with path " + path + " can not be mapped to a class");
+            return;
+        }
+        
+        
+        QName qname = JAXRSUtils.convertStringToQName(resourceId);
+        if (getSchemaClassName(PackageUtils.getPackageNameByNameSpaceURI(qname.getNamespaceURI()), 
+                               gInfo, qname.getLocalPart(), typeClassNames) != null) {
+            return; 
+        }
+        
+        StringBuilder sbImports = new StringBuilder();
+        StringBuilder sbCode = new StringBuilder();
+        Set<String> imports = createImports();
+        
+        sbImports.append(getClassComment()).append(getLineSep());
+        sbImports.append("package " + qname.getNamespaceURI())
+            .append(";").append(getLineSep()).append(getLineSep());
+        
+        writeAnnotation(sbCode, imports, Path.class, path, true, false);
+        sbCode.append("public " + getClassType() + " " + qname.getLocalPart() 
+                                       + " {" + getLineSep() + getLineSep());
+        
+        writeMethods(rElement, imports, sbCode, typeClassNames, gInfo);
+        
+        List<Element> childEls = DOMUtils.getChildrenWithName(rElement, 
+            WadlGenerator.WADL_NS, "resource");
+        for (Element childEl : childEls) {
+            if (childEl.getAttribute("id").length() == 0) {
+                writeMethods(childEl, imports, sbCode, typeClassNames, gInfo);
+            } else {
+                writeResourceMethod(childEl, childEl, imports, sbCode, typeClassNames, gInfo);
+            }
+        }
+        sbCode.append("}");
+        writeImports(sbImports, imports);
+        
+        createJavaSourceFile(src, qname, sbCode, sbImports);
+        
+        for (Element subEl : childEls) {
+            String id = subEl.getAttribute("id");
+            if (id.length() > 0 && !resourceId.equals(id) && !id.startsWith("{java")) {
+                writeResourceClass(subEl, typeClassNames, gInfo, src);
+            }
+        }
+    }
+    
+    private String getClassType() {
+        return generateInterfaces ? "interface" : "class";
+    }
+    
+    private String getClassComment() {
+        return "/**"
+            + getLineSep() + " * Generated by Apache CXF"
+            + getLineSep() + "**/";
+    }
+    
+    private void writeMethods(Element rElement,  
+                              Set<String> imports, StringBuilder sbCode, 
+                              Set<String> typeClassNames, GrammarInfo gInfo) {
+        List<Element> methodEls = DOMUtils.getChildrenWithName(rElement, 
+            WadlGenerator.WADL_NS, "method");
+       
+        for (Element methodEl : methodEls) {
+            writeResourceMethod(rElement, methodEl, imports, sbCode, typeClassNames, gInfo);    
+        }
+    }
+    
+    private void writeAnnotation(StringBuilder sbCode, Set<String> imports,
+                                 Class<?> cls, String value, boolean nextLine, boolean addTab) {
+        if (value != null && value.length() == 0) {
+            return;
+        }
+        addImport(imports, cls.getName());
+        sbCode.append("@").append(cls.getSimpleName());
+        if (value != null) {
+            sbCode.append("(\"" + value + "\")");
+        }
+        if (nextLine) {
+            sbCode.append(getLineSep());
+            if (addTab) {
+                sbCode.append(TAB);
+            }
+        }
+    }
+    
+    private void addImport(Set<String> imports, String clsName) {
+        if (imports == null || clsName.startsWith("java.lang")) {
+            return;
+        }
+        if (!imports.contains(clsName)) {
+            imports.add(clsName);
+        }
+    }
+    
+    private void writeImports(StringBuilder sbImports, Set<String> imports) {
+        for (String clsName : imports) {
+            sbImports.append("import " + clsName).append(";").append(getLineSep());
+        }
+    }
+    
+    private void writeResourceMethod(Element resourceEl, Element methodEl, 
+                                     Set<String> imports, StringBuilder sbCode, 
+                                     Set<String> typeClassNames, GrammarInfo gInfo) {
+        String id = methodEl.getAttribute("id");
+        String methodName = methodEl.getAttribute("name");
+        String path = resourceEl.getAttribute("path");
+        if (id.length() == 0) {
+            LOG.warning("Method with path " + path + " can not be mapped to a class method");
+            return;
+        }
+        
+        sbCode.append(TAB);
+        writeAnnotation(sbCode, imports, Path.class, path, true, true);
+        if (methodName.length() > 0) {
+            if (HTTP_METHOD_ANNOTATIONS.containsKey(methodName.toLowerCase())) {
+                writeAnnotation(sbCode, imports, 
+                                HTTP_METHOD_ANNOTATIONS.get(methodName.toLowerCase()), null, true, true);
+            } else {
+                // TODO : write a custom annotation class based on HttpMethod    
+            }
+        }
+        
+        List<Element> responseEls = DOMUtils.getChildrenWithName(methodEl, 
+                                                                 WadlGenerator.WADL_NS, "response");
+        List<Element> requestEls = DOMUtils.getChildrenWithName(methodEl, 
+                                                                WadlGenerator.WADL_NS, "request");
+        
+        if (methodName.length() > 0) {
+            writeFormatAnnotations(requestEls, sbCode, imports, true);
+            writeFormatAnnotations(responseEls, sbCode, imports, false);
+        }
+        if (!generateInterfaces) {
+            sbCode.append("public ");
+        }
+        boolean responseTypeAvailable = true;
+        if (methodName.length() > 0) {
+            responseTypeAvailable = writeResponseType(responseEls, sbCode, imports, typeClassNames, gInfo);
+            sbCode.append(id);
+        } else {
+            QName qname = JAXRSUtils.convertStringToQName(id);
+            String packageName = PackageUtils.getPackageNameByNameSpaceURI(qname.getNamespaceURI());
+            String clsSimpleName = getSchemaClassName(packageName, gInfo, qname.getLocalPart(), 
+                                                      typeClassNames);
+            String localName = clsSimpleName == null ? qname.getLocalPart() 
+                : clsSimpleName.substring(packageName.length() + 1);
+            String parentId = ((Element)resourceEl.getParentNode()).getAttribute("id");
+            writeSubResponseType(id.equals(parentId), clsSimpleName == null ? qname.getNamespaceURI() 
+                : clsSimpleName.substring(0, packageName.length()), localName, sbCode, imports);
+            // TODO : we need to take care of multiple subresource locators with diff @Path
+            // returning the same type; also we might have ids like "{org.apache.cxf}Book#getName" 
+            sbCode.append("get" + localName);
+        }
+        
+        sbCode.append("(");
+        List<Element> inParamElements = new LinkedList<Element>();
+        inParamElements.addAll(DOMUtils.getChildrenWithName(resourceEl, 
+                                                            WadlGenerator.WADL_NS, "param"));
+        boolean form = false;
+        if (requestEls.size() == 1 && inParamElements.size() == 0) {
+            inParamElements.addAll(DOMUtils.getChildrenWithName(requestEls.get(0), 
+                 WadlGenerator.WADL_NS, "param"));
+            addFormParameters(inParamElements, requestEls.get(0));
+            form = true;
+        }
+        writeRequestTypes(requestEls, inParamElements, sbCode, imports, typeClassNames, gInfo,
+                          form);
+        sbCode.append(")");
+        if (generateInterfaces) {
+            sbCode.append(";");
+        } else {
+            generateEmptyMethodBody(sbCode, responseTypeAvailable);
+        }
+        sbCode.append(getLineSep()).append(getLineSep());
+    }
+
+    protected void generateEmptyMethodBody(StringBuilder sbCode, boolean responseTypeAvailable) {
+        sbCode.append(" {");
+        sbCode.append(getLineSep()).append(TAB).append(TAB);
+        sbCode.append("//TODO: implement").append(getLineSep()).append(TAB);
+        if (responseTypeAvailable) {
+            sbCode.append(TAB).append("return null;").append(getLineSep()).append(TAB);
+        }
+        sbCode.append("}");
+    }
+    
+    private void addFormParameters(List<Element> inParamElements, Element requestEl) {
+        List<Element> repElements = 
+            DOMUtils.getChildrenWithName(requestEl, WadlGenerator.WADL_NS, "representation");
+ 
+        if (repElements.size() == 1) {
+            String mediaType = repElements.get(0).getAttribute("mediaType");
+            if (MediaType.APPLICATION_FORM_URLENCODED.equals(mediaType)) { 
+                inParamElements.addAll(DOMUtils.getChildrenWithName(repElements.get(0), 
+                                                                WadlGenerator.WADL_NS, "param"));
+            }
+        }
+    }
+    
+    private boolean writeResponseType(List<Element> responseEls, StringBuilder sbCode,
+                                   Set<String> imports, Set<String> typeClassNames, 
+                                   GrammarInfo gInfo) {
+        List<Element> repElements = responseEls.size() == 1 
+            ? DOMUtils.getChildrenWithName(responseEls.get(0), WadlGenerator.WADL_NS, "representation")
+            : CastUtils.cast(Collections.emptyList(), Element.class);
+        if (repElements.size() == 0) {    
+            sbCode.append("void ");
+            return false;
+        }
+        String elementName = getElementRefName(repElements, typeClassNames, gInfo, imports);
+        if (elementName != null) {
+            sbCode.append(elementName + " ");
+        } else {
+            addImport(imports, Response.class.getName());
+            sbCode.append("Response ");
+        }
+        return true;
+    }
+    
+    private void writeSubResponseType(boolean recursive, String ns, String localName,
+                                      StringBuilder sbCode, Set<String> imports) {
+        if (!recursive && ns.length() > 0) {
+            addImport(imports, ns + "." + localName);
+        }
+        sbCode.append(localName).append(" ");
+    }
+    
+    private void writeRequestTypes(List<Element> requestEls,
+                                   List<Element> inParamEls, 
+                                   StringBuilder sbCode, 
+                                   Set<String> imports, 
+                                   Set<String> typeClassNames, 
+                                   GrammarInfo gInfo,
+                                   boolean form) {
+        
+        String elementName = null;
+        
+        List<Element> repElements = requestEls.size() == 1 
+            ? DOMUtils.getChildrenWithName(requestEls.get(0), WadlGenerator.WADL_NS, "representation")
+            : CastUtils.cast(Collections.emptyList(), Element.class);
+        if (repElements.size() > 0) {    
+            elementName = getElementRefName(repElements, typeClassNames, gInfo, imports);
+        }
+        if (elementName != null) {
+            sbCode.append(elementName).append(" ").append(elementName.toLowerCase());
+            if (inParamEls.size() > 0) {
+                sbCode.append(", ");
+            }
+        } else if (inParamEls.size() == 0) {
+            if (form) {
+                addImport(imports, MultivaluedMap.class.getName());
+                sbCode.append("MultivaluedMap map");
+            }
+            return;
+        }
+        for (int i = 0; i < inParamEls.size(); i++) {
+            Element paramEl = inParamEls.get(i);
+
+            String name = paramEl.getAttribute("name");
+            Class<?> paramAnnotation = form ? FormParam.class 
+                : PARAM_ANNOTATIONS.get(paramEl.getAttribute("style"));
+            writeAnnotation(sbCode, imports, paramAnnotation, name, false, false);
+            String type = getPrimitiveType(paramEl);
+            sbCode.append(" ").append(type).append(" ").append(name.replace('.', '_'));
+            if (i + 1 < inParamEls.size()) {
+                sbCode.append(", ");
+                if (i + 1 >= 4 && ((i + 1) % 4) == 0) {
+                    sbCode.append(getLineSep()).append(TAB).append(TAB).append(TAB).append(TAB);
+                }
+            }
+        }
+    }
+    
+    private String getPrimitiveType(Element paramEl) {
+        String type = paramEl.getAttribute("type");
+        if (type == null) {
+            return "String";
+        }
+        String[] pair = type.split(":");
+        String value = pair.length == 2 ? pair[1] : type;
+        return "string".equals(value) ? "String" : value;
+    }
+    
+    private String getElementRefName(List<Element> repElements, Set<String> typeClassNames,
+                                     GrammarInfo gInfo, Set<String> imports) {
+        String elementRef = null;
+        for (Element el : repElements) {
+            String value = el.getAttribute("element");
+            if (value.length() > 0) {
+                elementRef = value;
+                break;
+            }
+        }
+        if (elementRef != null) {
+            String[] pair = elementRef.split(":");
+            if (pair.length == 2) {
+                String namespace = gInfo != null ? gInfo.getNsMap().get(pair[0]) : null;
+                if (namespace == null) {
+                    return null;
+                }
+                String packageName = PackageUtils.getPackageNameByNameSpaceURI(namespace);
+                String clsName = getSchemaClassName(packageName, gInfo, pair[1], typeClassNames);
+                if (clsName != null) {
+                    addImport(imports, clsName);
+                    return clsName.substring(packageName.length() + 1);
+                }
+            }
+        }
+        return null;
+    }
+    
+    private String getSchemaClassName(String packageName, GrammarInfo gInfo, String localName,
+                                      Set <String> typeClassNames) {
+        String clsName = matchClassName(typeClassNames, packageName, localName);
+        if (clsName == null && gInfo != null) {
+            clsName = matchClassName(typeClassNames, packageName, 
+                                   gInfo.getElementTypeMap().get(localName));
+        }
+        return clsName;
+    }
+    
+    private String matchClassName(Set<String> typeClassNames, String packageName, String localName) {
+        if (localName == null) {
+            return null;
+        }
+        String clsName = packageName + "." + localName;
+        for (String type : typeClassNames) {
+            if (type.toLowerCase().equals(clsName)) {
+                return type;
+            }
+        }
+        return null;
+    }
+    
+    
+    
+    private void writeFormatAnnotations(List<Element> parentEls, StringBuilder sbCode, 
+                                        Set<String> imports, boolean inRep) {
+        List<Element> repElements = parentEls.size() == 1 
+            ? DOMUtils.getChildrenWithName(parentEls.get(0), WadlGenerator.WADL_NS, "representation")
+            : CastUtils.cast(Collections.emptyList(), Element.class);
+        if (repElements.size() == 0) {    
+            return;
+        }
+        Class<?> cls = inRep ? Consumes.class : Produces.class;
+        addImport(imports, cls.getName());
+        sbCode.append("@").append(cls.getSimpleName()).append("(");
+        if (repElements.size() > 1) {
+            sbCode.append("{");
+        }
+        for (int i = 0; i < repElements.size(); i++) {
+            String mediaType = repElements.get(i).getAttribute("mediaType");
+            if (mediaType != null) {
+                sbCode.append("\"" + mediaType + "\"");
+                if (i + 1 < repElements.size()) { 
+                    sbCode.append(", ");
+                }
+            }
+        }
+        if (repElements.size() > 1) {
+            sbCode.append(" }");
+        }
+        sbCode.append(")");
+        sbCode.append(getLineSep()).append(TAB);
+    }
+    
+    private void createJavaSourceFile(File src, QName qname, StringBuilder sbCode, StringBuilder sbImports) {
+        String content = sbImports.toString() + getLineSep() + sbCode.toString();
+        File currentDir = new File(src.getAbsolutePath(), qname.getNamespaceURI());
+        currentDir.mkdirs();
+        File file = new File(currentDir.getAbsolutePath(), qname.getLocalPart() + ".java");
+        
+        try {
+            file.createNewFile();
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(content.getBytes());
+            fos.close();
+        } catch (FileNotFoundException ex) {
+            LOG.warning(file.getAbsolutePath() + " is not found");
+        } catch (IOException ex) {
+            LOG.warning("Problem writing into " + file.getAbsolutePath());
+        }
+    }
+    
+    private Element readWadl(String wadl) {
+        try {
+            Document doc = DOMUtils.readXml(new StringReader(wadl));
+            return doc.getDocumentElement();
+        } catch (Exception ex) {
+            throw new IllegalStateException("Unable to read wadl", ex);
+        }
+    }
+    
+    private void generateClassesFromSchema(JCodeModel codeModel, File src) {
+        try {
+            Object writer = JAXBUtils.createFileCodeWriter(src);
+            codeModel.build(writer);
+        } catch (Exception e) {
+            throw new IllegalStateException("Unable to write generated Java files for schemas: "
+                                            + e.getMessage(), e);
+        }
+        List<File> srcFiles = FileUtils.getFilesRecurse(src, ".+\\.java$");
+        for (File f : srcFiles) {
+            System.out.println(f.getAbsolutePath());
+        }
+    }
+
+    private List<Element> getSchemaElements(Element appElement) {
+        List<Element> grammarEls = DOMUtils.getChildrenWithName(appElement, 
+                                                                WadlGenerator.WADL_NS, "grammars");
+        if (grammarEls.size() != 1) {
+            return null;
+        }
+        
+        List<Element> schemasEls = DOMUtils.getChildrenWithName(grammarEls.get(0), 
+             XmlSchemaConstants.XSD_NAMESPACE_URI, "schema");
+        //TODO : check remote referencs if size() == 0
+        return schemasEls;
+    }
+    
+    private JCodeModel createCodeModel(List<Element> schemaElements, Set<String> type) {
+        
+        SchemaCompiler compiler = createCompiler(type);
+
+        addSchemas(schemaElements, compiler);
+        
+        S2JJAXBModel intermediateModel = compiler.bind();
+        
+        Object elForRun = ReflectionInvokationHandler
+            .createProxyWrapper(new InnerErrorListener(),
+                            JAXBUtils.getParamClass(compiler, "setErrorListener"));
+        
+        JCodeModel codeModel = intermediateModel.generateCode(null, elForRun);
+        JAXBUtils.logGeneratedClassNames(LOG, codeModel);
+        return codeModel;
+    }
+    
+    private SchemaCompiler createCompiler(Set<String> typeClassNames) {
+        return JAXBUtils.createSchemaCompilerWithDefaultAllocator(typeClassNames);
+    }
+    
+    private void addSchemas(List<Element> schemaElements, SchemaCompiler compiler) {
+        
+        for (int i = 0; i < schemaElements.size(); i++) {
+            String key = Integer.toString(i);
+            //For JAXB 2.1.8
+            InputSource is = new InputSource((InputStream)null);
+            is.setSystemId(key);
+            is.setPublicId(key);
+            compiler.getOptions().addGrammar(is);
+    
+            compiler.parseSchema(key, schemaElements.get(i));
+        }
+    }
+    
+    public void setImportsComparator(Comparator<String> importsComparator) {
+        this.importsComparator = importsComparator;
+    }
+
+    private Set<String> createImports() {
+        return importsComparator == null ? new TreeSet<String>() : new TreeSet<String>(importsComparator);
+    }
+
+    public void setGenerateInterfaces(boolean generateInterfaces) {
+        this.generateInterfaces = generateInterfaces;
+    }
+    
+    private static class GrammarInfo {
+        private Map<String, String> nsMap;
+        private Map<String, String> elementTypeMap;
+        
+        public GrammarInfo(Map<String, String> nsMap, Map<String, String> elementTypeMap) {
+            this.nsMap = nsMap;
+            this.elementTypeMap = elementTypeMap; 
+        }
+
+        public Map<String, String> getNsMap() {
+            return nsMap;
+        }
+        
+        public Map<String, String> getElementTypeMap() {
+            return elementTypeMap;
+        }
+    }
+
+    private static class InnerErrorListener {
+
+        public void error(SAXParseException ex) {
+            throw new RuntimeException("Error compiling schema from WADL : "
+                                       + ex.getMessage(), ex);
+        }
+
+        public void fatalError(SAXParseException ex) {
+            throw new RuntimeException("Fatal error compiling schema from WADL : "
+                                       + ex.getMessage(), ex);
+        }
+
+        public void info(SAXParseException ex) {
+            // ignore
+        }
+
+        public void warning(SAXParseException ex) {
+            // ignore
+        }
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProvider.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestPreprocessor.java Tue Mar  9 17:53:56 2010
@@ -30,10 +30,12 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import org.apache.cxf.jaxrs.ext.RequestHandler;
+import org.apache.cxf.jaxrs.ext.codegen.CodeGeneratorProvider;
 import org.apache.cxf.jaxrs.model.ProviderInfo;
 import org.apache.cxf.jaxrs.model.wadl.WadlGenerator;
 import org.apache.cxf.jaxrs.provider.ProviderFactory;
 import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
 import org.apache.cxf.message.Message;
 
 public class RequestPreprocessor {
@@ -75,7 +77,13 @@ public class RequestPreprocessor {
         MultivaluedMap<String, String> queries = u.getQueryParameters();
         handleTypeQuery(m, queries);
         handleMethod(m, queries, new HttpHeadersImpl(m));
-        checkMetadataRequest(m);
+        Response r = checkMetadataRequest(m);
+        if (r == null) {
+            r = checkCodeRequest(m);
+        }
+        if (r != null) {
+            m.getExchange().put(Response.class, r);
+        }
         return new UriInfoImpl(m, null).getPath();
     }
     
@@ -159,7 +167,7 @@ public class RequestPreprocessor {
      * has been selected are handy. Consider implementing this method as part of the QueryHandler,
      * we will need to save the list of ClassResourceInfos on the EndpointInfo though
      */
-    public void checkMetadataRequest(Message m) {
+    public Response checkMetadataRequest(Message m) {
         String query = (String)m.get(Message.QUERY_STRING);
         if (query != null && query.contains(WadlGenerator.WADL_QUERY)) {
             String requestURI = (String)m.get(Message.REQUEST_URI);
@@ -169,12 +177,29 @@ public class RequestPreprocessor {
                 // this is actually being tested by ProviderFactory unit tests but just in case
                 // WadlGenerator, the custom or default one, must be the first one
                 if (shs.size() > 0 && shs.get(0).getProvider() instanceof WadlGenerator) {
-                    Response r = shs.get(0).getProvider().handleRequest(m, null);
-                    if (r != null) {
-                        m.getExchange().put(Response.class, r);
-                    }    
+                    return shs.get(0).getProvider().handleRequest(m, null);
+                }
+            }
+        }
+        return null;
+    }
+    
+    public Response checkCodeRequest(Message m) {
+        String query = (String)m.get(Message.QUERY_STRING);
+        if (query != null && (query.contains(CodeGeneratorProvider.CODE_QUERY) 
+            || query.contains(CodeGeneratorProvider.SOURCE_QUERY))) {
+            String requestURI = (String)m.get(Message.REQUEST_URI);
+            String baseAddress = HttpUtils.getBaseAddress(m);
+            if (baseAddress.equals(requestURI)) {
+                List<ProviderInfo<RequestHandler>> shs = ProviderFactory.getInstance(m).getRequestHandlers();
+                for (ProviderInfo<RequestHandler> provider : shs) {
+                    if (provider.getProvider() instanceof CodeGeneratorProvider) { 
+                        InjectionUtils.injectContextMethods(provider.getProvider(), provider, m);
+                        return provider.getProvider().handleRequest(m, null);
+                    }
                 }
             }
         }
+        return null;
     }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java Tue Mar  9 17:53:56 2010
@@ -503,6 +503,9 @@ public class UriBuilderImpl extends UriB
             }
             list.add(value.toString());
         }
+        if (list.isEmpty()) {
+            list.add("");
+        }
         return list;
     }
 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSInInterceptor.java Tue Mar  9 17:53:56 2010
@@ -180,7 +180,7 @@ public class JAXRSInInterceptor extends 
                 
             }
             InjectionUtils.injectContextFields(sh.getProvider(), sh, message);
-            InjectionUtils.injectContextFields(sh.getProvider(), sh, message);
+            InjectionUtils.injectContextMethods(sh.getProvider(), sh, message);
             Response response = sh.getProvider().handleRequest(message, resource);
             if (response != null) {
                 message.getExchange().put(Response.class, response);

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java Tue Mar  9 17:53:56 2010
@@ -62,6 +62,7 @@ import org.w3c.dom.Node;
 
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PackageUtils;
 import org.apache.cxf.common.util.ReflectionInvokationHandler;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.common.util.XmlSchemaPrimitiveUtils;
@@ -113,6 +114,7 @@ public class WadlGenerator implements Re
     private boolean ignoreMessageWriters = true;
     private boolean singleResourceMultipleMethods = true;
     private boolean useSingleSlashResource;
+    private boolean addResourceAndMethodIds;
     
     private boolean useJaxbContextForQnames = true;
     
@@ -122,6 +124,24 @@ public class WadlGenerator implements Re
     private ElementQNameResolver resolver;
     private List<String> privateAddresses;
     
+    public WadlGenerator() {
+        
+    }
+    
+    public WadlGenerator(WadlGenerator other) {
+        this.wadlNamespace = other.wadlNamespace;
+        this.externalQnamesMap = other.externalQnamesMap;
+        this.externalSchemaLinks = other.externalSchemaLinks;
+        this.externalSchemasCache = other.externalSchemasCache;
+        this.ignoreMessageWriters = other.ignoreMessageWriters;
+        this.privateAddresses = other.privateAddresses;
+        this.resolver = other.resolver;
+        this.addResourceAndMethodIds = other.addResourceAndMethodIds;
+        this.singleResourceMultipleMethods = other.singleResourceMultipleMethods;
+        this.useJaxbContextForQnames = other.useJaxbContextForQnames;
+        this.useSingleSlashResource = other.useSingleSlashResource;
+    }
+    
     public Response handleRequest(Message m, ClassResourceInfo resource) {
         
         if (!"GET".equals(m.get(Message.HTTP_REQUEST_METHOD))) {
@@ -159,8 +179,7 @@ public class WadlGenerator implements Re
         Map<Class<?>, QName> clsMap = new IdentityHashMap<Class<?>, QName>();
         Set<ClassResourceInfo> visitedResources = new HashSet<ClassResourceInfo>();
         for (ClassResourceInfo cri : cris) {
-            String path = cri.getURITemplate().getValue();
-            sbResources.append("<resource path=\"").append(path).append("\">");
+            startResourceTag(sbResources, cri.getServiceClass(), cri.getURITemplate().getValue());
             handleDocs(cri.getServiceClass().getAnnotations(), sbResources);
             handleResource(sbResources, allTypes, qnameResolver, clsMap, cri, visitedResources);
             sbResources.append("</resource>");
@@ -218,8 +237,7 @@ public class WadlGenerator implements Re
                 Class<?> cls = ori.getMethodToInvoke().getReturnType();
                 ClassResourceInfo subcri = cri.findResource(cls, cls);
                 if (subcri != null && !visitedResources.contains(subcri)) {
-                    String path = ori.getURITemplate().getValue();
-                    sb.append("<resource path=\"").append(path).append("\">");
+                    startResourceTag(sb, subcri.getServiceClass(), ori.getURITemplate().getValue());
                     handleDocs(subcri.getServiceClass().getAnnotations(), sb);
                     handlePathAndMatrixParams(sb, ori);
                     handleResource(sb, jaxbTypes, qnameResolver, clsMap, subcri, 
@@ -236,6 +254,30 @@ public class WadlGenerator implements Re
         }
     }
     
+    private void startResourceTag(StringBuilder sb, Class<?> serviceClass, String path) {
+        sb.append("<resource path=\"").append(path).append("\"");
+        if (addResourceAndMethodIds) {
+            QName jaxbQname = null;
+            if (useJaxbContextForQnames) {
+                jaxbQname = getJaxbQName(null, serviceClass, new HashMap<Class<?>, QName>(0));
+            }
+            String pName = jaxbQname == null ? PackageUtils.getPackageName(serviceClass) 
+                : jaxbQname.getNamespaceURI();
+            String localName = jaxbQname == null ? serviceClass.getSimpleName() 
+                : jaxbQname.getLocalPart();
+            sb.append(" id=\"").append("{" + pName + "}" + localName).append("\"");
+        }
+        sb.append(">");
+    }
+    
+    private void startMethodTag(StringBuilder sb, OperationResourceInfo ori) {
+        sb.append("<method name=\"").append(ori.getHttpMethod()).append("\"");
+        if (addResourceAndMethodIds) {
+            sb.append(" id=\"").append(ori.getMethodToInvoke().getName()).append("\"");
+        }
+        sb.append(">");
+    }
+    
     //CHECKSTYLE:OFF
     private boolean handleOperation(StringBuilder sb, Set<Class<?>> jaxbTypes, 
                                  ElementQNameResolver qnameResolver, 
@@ -263,7 +305,7 @@ public class WadlGenerator implements Re
             handlePathAndMatrixParams(sb, ori);
         }
         
-        sb.append("<method name=\"").append(ori.getHttpMethod()).append("\">");
+        startMethodTag(sb, ori);
         handleDocs(ori.getAnnotatedMethod().getAnnotations(), sb);
         if (ori.getMethodToInvoke().getParameterTypes().length != 0) {
             sb.append("<request>");
@@ -342,7 +384,8 @@ public class WadlGenerator implements Re
         } else {
             sb.append("<!-- Dynamic subresource -->");    
         }
-        sb.append("<resource path=\"").append(ori.getURITemplate().getValue()).append("\">");
+        startResourceTag(sb, subcri != null ? subcri.getServiceClass() : Object.class, 
+            ori.getURITemplate().getValue());
         handlePathAndMatrixParams(sb, ori);
         sb.append("</resource>");
     }
@@ -483,7 +526,7 @@ public class WadlGenerator implements Re
                 URITemplate ut1 = op1.getURITemplate();
                 URITemplate ut2 = op2.getURITemplate();
                 int result = ut1.getValue().compareTo(ut2.getValue());
-                if (result == 0) {
+                if (result == 0 && !(sub1 && sub2)) {
                     result = op1.getHttpMethod().compareTo(op2.getHttpMethod());
                 }
                 return result;
@@ -1004,7 +1047,7 @@ public class WadlGenerator implements Re
                 name = type.getAnnotation(XMLName.class);
             }
             if (name != null) {
-                QName qname = convertStringToQName(name.value(), name.prefix());
+                QName qname = JAXRSUtils.convertStringToQName(name.value(), name.prefix());
                 if (qname.getPrefix().length() > 0) {
                     return qname;
                 } else {
@@ -1043,21 +1086,6 @@ public class WadlGenerator implements Re
         
     }
     
-    private QName convertStringToQName(String name, String prefix) {
-        int ind1 = name.indexOf('{');
-        if (ind1 != 0) {
-            return null;
-        }
-        
-        int ind2 = name.indexOf('}');
-        if (ind2 <= ind1 + 1 || ind2 >= name.length() - 1) {
-            return null;
-        }
-        String ns = name.substring(ind1 + 1, ind2);
-        String localName = name.substring(ind2 + 1);
-        return new QName(ns, localName, prefix);
-    }
-
     public void setResolver(ElementQNameResolver resolver) {
         this.resolver = resolver;
     }
@@ -1074,6 +1102,10 @@ public class WadlGenerator implements Re
         return MessageUtils.isTrue(m.getContextualProperty("org.apache.cxf.endpoint.private")); 
     }
     
+    public void setAddResourceAndMethodIds(boolean addResourceAndMethodIds) {
+        this.addResourceAndMethodIds = addResourceAndMethodIds;
+    }
+
     private static class SchemaConverter extends DelegatingXMLStreamWriter {
         private static final String SCHEMA_LOCATION = "schemaLocation";
         private Map<String, String> locsMap;    

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java Tue Mar  9 17:53:56 2010
@@ -164,13 +164,13 @@ public abstract class AbstractJAXBProvid
         if (jaxbElementClassNames != null && jaxbElementClassNames.contains(cls.getName()) 
             || jaxbElementClassMap != null && jaxbElementClassMap.containsKey(cls.getName())) {
             if (jaxbElementClassMap != null) {
-                name = convertStringToQName(jaxbElementClassMap.get(cls.getName()));
+                name = JAXRSUtils.convertStringToQName(jaxbElementClassMap.get(cls.getName()));
             } else {
                 name = getJaxbQName(cls, genericType, obj, false);
             }
         }
         if (name == null && marshalAsJaxbElement) {
-            name = convertStringToQName(cls.getSimpleName());
+            name = JAXRSUtils.convertStringToQName(cls.getSimpleName());
         }
         if (name != null) {
             return new JAXBElement(name, cls, null, obj);
@@ -221,22 +221,7 @@ public abstract class AbstractJAXBProvid
             return getJaxbQName(cls, type, object, pluralName);
         }
             
-        return convertStringToQName(name);
-    }
-    
-    protected static QName convertStringToQName(String name) {
-        int ind1 = name.indexOf('{');
-        if (ind1 != 0) {
-            return new QName(name);
-        }
-        
-        int ind2 = name.indexOf('}');
-        if (ind2 <= ind1 + 1 || ind2 >= name.length() - 1) {
-            return null;
-        }
-        String ns = name.substring(ind1 + 1, ind2);
-        String localName = name.substring(ind2 + 1);
-        return new QName(ns, localName);
+        return JAXRSUtils.convertStringToQName(name);
     }
     
     private String getCollectionWrapperName(Class<?> cls) {
@@ -591,7 +576,7 @@ public abstract class AbstractJAXBProvid
         if (dropEls != null) {
             dropElements = new LinkedHashSet<QName>(dropEls.size());
             for (String val : dropEls) {
-                dropElements.add(convertStringToQName(val));
+                dropElements.add(JAXRSUtils.convertStringToQName(val));
             }
         }
         return dropElements;
@@ -634,8 +619,8 @@ public abstract class AbstractJAXBProvid
                                              Map<String, String> nsMap) {
         if (map != null) {
             for (Map.Entry<String, String> entry : map.entrySet()) {
-                QName lname = convertStringToQName(entry.getKey());
-                QName rname = convertStringToQName(entry.getValue());
+                QName lname = JAXRSUtils.convertStringToQName(entry.getKey());
+                QName rname = JAXRSUtils.convertStringToQName(entry.getValue());
                 elementsMap.put(lname, rname);
                 if (nsMap != null) {
                     nsMap.put(lname.getNamespaceURI(), rname.getNamespaceURI());
@@ -648,8 +633,8 @@ public abstract class AbstractJAXBProvid
                                                Map<QName, QName> elementsMap) {
         if (map != null) {
             for (Map.Entry<String, String> entry : map.entrySet()) {
-                QName lname = convertStringToQName(entry.getKey());
-                QName rname = convertStringToQName(entry.getValue());
+                QName lname = JAXRSUtils.convertStringToQName(entry.getKey());
+                QName rname = JAXRSUtils.convertStringToQName(entry.getValue());
                 elementsMap.put(lname, rname);
             }
         }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Tue Mar  9 17:53:56 2010
@@ -1160,5 +1160,23 @@ public final class JAXRSUtils {
         }
         return new QName(nsURI, type.getSimpleName(), "ns1"); 
     }
+
+    public static QName convertStringToQName(String name) {
+        return convertStringToQName(name, "");
+    }
     
+    public static QName convertStringToQName(String name, String prefix) {
+        int ind1 = name.indexOf('{');
+        if (ind1 != 0) {
+            return new QName(name);
+        }
+        
+        int ind2 = name.indexOf('}');
+        if (ind2 <= ind1 + 1 || ind2 >= name.length() - 1) {
+            return null;
+        }
+        String ns = name.substring(ind1 + 1, ind2);
+        String localName = name.substring(ind2 + 1);
+        return new QName(ns, localName, prefix);
+    }
 }

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java?rev=921014&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java Tue Mar  9 17:53:56 2010
@@ -0,0 +1,336 @@
+/**
+ * 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.ext.codegen;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.cxf.jaxrs.JAXRSServiceImpl;
+import org.apache.cxf.jaxrs.impl.UriInfoImpl;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.wadl.BookStore;
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.Service;
+import org.apache.cxf.service.model.BindingInfo;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.servlet.ServletDestination;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CodeGeneratorProviderTest extends Assert {
+
+    private IMocksControl control;
+    
+    @Before
+    public void setUp() {
+        control = EasyMock.createNiceControl();
+        control.makeThreadSafe(true);
+    }
+    
+    @Test
+    public void testBookStoreAsInterface() throws Exception {
+        generateCodeAndCheck(true, false);
+    }
+    
+    @Test
+    public void testBookStoreAsClass() throws Exception {
+        generateCodeAndCheck(false, false);
+    }
+    
+    @Test
+    public void testBookStoreTypesOnly() throws Exception {
+        generateCodeAndCheck(false, true);
+    }
+    
+    private void generateCodeAndCheck(boolean generateInterfaces, boolean typesOnly) throws Exception {
+        CodeGeneratorProvider cgp = new CodeGeneratorProvider();
+        cgp.setGenerateInterfaces(generateInterfaces);
+        
+        ClassResourceInfo cri = 
+            ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+        
+        String query = CodeGeneratorProvider.CODE_QUERY + "&_os=" + getOs();
+        if (typesOnly) {
+            query += "&_codeType=grammar";
+        }
+        Message m = mockMessage("http://localhost:8080/baz", "/bar", query, null);
+        try {
+            cgp.removeCode(cri);
+            cgp.setUriInfo(new UriInfoImpl(m, null));
+            cgp.handleRequest(m, cri);
+            
+            String tmpdir = System.getProperty("java.io.tmpdir");
+            File classes = new File(tmpdir, cgp.getStem(cri, "classes"));
+            if (!classes.mkdir()) {
+                fail();
+            }
+            File unzippedSrc = new File(tmpdir, cgp.getStem(cri, "unzip"));
+            if (!unzippedSrc.mkdir()) {
+                fail();
+            }
+            File zipDir = new File(tmpdir, cgp.getStem(cri, "zip"));
+            try {             
+                compileSrc(classes, unzippedSrc, new FileInputStream(new File(zipDir, "src.zip")));
+                verifyClasses(classes, typesOnly);
+            } finally {
+                FileUtils.removeDir(classes);
+                FileUtils.removeDir(unzippedSrc);
+            }
+        } finally {
+            cgp.removeCode(cri);
+        }
+    }
+    
+    private void verifyClasses(File classesDir, boolean typesOnly) {
+        List<File> clsFiles = FileUtils.getFilesRecurse(classesDir, ".+\\.class$");
+        assertEquals(typesOnly ? 5 : 7, clsFiles.size());
+        assertTrue(checkContains(clsFiles, "superbooks.Book.class"));
+        assertTrue(checkContains(clsFiles, "superbooks.Book2.class"));
+        assertTrue(checkContains(clsFiles, "superbooks.Chapter.class"));
+        assertTrue(checkContains(clsFiles, "superbooks.ObjectFactory.class"));
+        assertTrue(checkContains(clsFiles, "superbooks.package-info.class"));
+        if (!typesOnly) {
+            assertTrue(checkContains(clsFiles, "org.apache.cxf.jaxrs.model.wadl.FormInterface.class"));
+            assertTrue(checkContains(clsFiles, "org.apache.cxf.jaxrs.model.wadl.BookStore.class"));
+        }
+    }
+    
+    private boolean checkContains(List<File> clsFiles, String name) {
+        
+        for (File f : clsFiles) {
+            if (f.getAbsolutePath().replace(getPathSep(), ".").endsWith(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    private String getPathSep() {
+        String os = System.getProperty("os.name");
+        if (os.toLowerCase().contains("win")) {
+            return "\\";
+        } else {
+            return "/";
+        }
+    }
+    
+    private String getOs() {
+        String os = System.getProperty("os.name");
+        if (os.toLowerCase().contains("win")) {
+            return "win";
+        } else {
+            return "unix";
+        }
+    }
+    
+    private void compileSrc(File classes, File unzippedSrc, InputStream zipFile) throws Exception {
+        unzip(zipFile, unzippedSrc);
+        StringBuilder classPath = new StringBuilder();
+        try {
+            setupClasspath(classPath, this.getClass().getClassLoader());
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+        
+        List<File> srcFiles = FileUtils.getFilesRecurse(unzippedSrc, ".+\\.java$"); 
+        if (!compileJavaSrc(classPath.toString(), srcFiles, classes.toString())) {
+            fail("Could not compile classes");
+        }
+    }
+
+    private void unzip(InputStream fin, File unzippedSrc) throws Exception {
+        ZipInputStream zin = new ZipInputStream(fin);
+        ZipEntry ze = null;
+        while ((ze = zin.getNextEntry()) != null) {
+            String entryName = ze.getName();
+            int index = entryName.lastIndexOf(System.getProperty("file.separator"));
+            File packageDir = new File(unzippedSrc, entryName.substring(0, index));
+            packageDir.mkdirs();
+            FileOutputStream fout = new FileOutputStream(
+                                        new File(packageDir, entryName.substring(index + 1)));
+            for (int c = zin.read(); c != -1; c = zin.read()) {
+                fout.write(c);
+            }
+            zin.closeEntry();
+            fout.close();
+        }
+        zin.close();
+    }
+    
+    protected boolean compileJavaSrc(String classPath, List<File> srcList, String dest) {
+        String[] javacCommand = new String[srcList.size() + 7];
+        
+        javacCommand[0] = "javac";
+        javacCommand[1] = "-classpath";
+        javacCommand[2] = classPath;        
+        javacCommand[3] = "-d";
+        javacCommand[4] = dest;
+        javacCommand[5] = "-target";
+        javacCommand[6] = "1.5";
+        
+        int i = 7;
+        for (File f : srcList) {
+            javacCommand[i++] = f.getAbsolutePath();            
+        }
+        org.apache.cxf.common.util.Compiler javaCompiler 
+            = new org.apache.cxf.common.util.Compiler();
+        
+        return javaCompiler.internalCompile(javacCommand, 7); 
+    }
+    
+    static void setupClasspath(StringBuilder classPath, ClassLoader classLoader)
+        throws URISyntaxException, IOException {
+        
+        ClassLoader scl = ClassLoader.getSystemClassLoader();        
+        ClassLoader tcl = classLoader;
+        do {
+            if (tcl instanceof URLClassLoader) {
+                URL[] urls = ((URLClassLoader)tcl).getURLs();
+                if (urls == null) {
+                    urls = new URL[0];
+                }
+                for (URL url : urls) {
+                    if (url.getProtocol().startsWith("file")) {
+                        File file;
+                        if (url.toURI().getPath() == null) {
+                            continue;
+                        }
+                        try { 
+                            file = new File(url.toURI().getPath()); 
+                        } catch (URISyntaxException urise) { 
+                            if (url.getPath() == null) {
+                                continue;
+                            }
+                            file = new File(url.getPath()); 
+                        } 
+    
+                        if (file.exists()) { 
+                            classPath.append(file.getAbsolutePath()) 
+                                .append(System 
+                                        .getProperty("path.separator")); 
+    
+                            if (file.getName().endsWith(".jar")) { 
+                                addClasspathFromManifest(classPath, file); 
+                            }                         
+                        }     
+                    }
+                }
+            }
+            tcl = tcl.getParent();
+            if (null == tcl) {
+                break;
+            }
+        } while(!tcl.equals(scl.getParent()));
+    }
+
+    static void addClasspathFromManifest(StringBuilder classPath, File file) 
+        throws URISyntaxException, IOException {
+        
+        JarFile jar = new JarFile(file);
+        Attributes attr = null;
+        if (jar.getManifest() != null) {
+            attr = jar.getManifest().getMainAttributes();
+        }
+        if (attr != null) {
+            String cp = attr.getValue("Class-Path");
+            while (cp != null) {
+                String fileName = cp;
+                int idx = fileName.indexOf(' ');
+                if (idx != -1) {
+                    fileName = fileName.substring(0, idx);
+                    cp =  cp.substring(idx + 1).trim();
+                } else {
+                    cp = null;
+                }
+                URI uri = new URI(fileName);
+                File f2;
+                if (uri.isAbsolute()) {
+                    f2 = new File(uri);
+                } else {
+                    f2 = new File(file, fileName);
+                }
+                if (f2.exists()) {
+                    classPath.append(f2.getAbsolutePath());
+                    classPath.append(System.getProperty("path.separator"));
+                }
+            }
+        }         
+    }
+    
+    private Message mockMessage(String baseAddress, String pathInfo, String query,
+                                List<ClassResourceInfo> cris) {
+        Message m = new MessageImpl();
+        Exchange e = new ExchangeImpl();
+        e.put(Service.class, new JAXRSServiceImpl(cris));
+        
+        m.setExchange(e);
+        control.reset();
+        ServletDestination d = control.createMock(ServletDestination.class);
+        
+        EndpointInfo epr = new EndpointInfo();
+        epr.setAddress(baseAddress);
+        
+        epr.setProperty("org.apache.cxf.http.case_insensitive_queries", "false");
+        epr.setProperty("org.apache.cxf.endpoint.private", "false");
+        
+        BindingInfo bi = control.createMock(BindingInfo.class);
+        bi.getProperties();
+        EasyMock.expectLastCall().andReturn(new HashMap<String, Object>()).anyTimes();
+        epr.setBinding(bi);
+        
+        d.getEndpointInfo();
+        EasyMock.expectLastCall().andReturn(epr).anyTimes();
+        e.setDestination(d);
+        m.put(Message.REQUEST_URI, pathInfo);
+        m.put(Message.QUERY_STRING, query);
+        m.put(Message.HTTP_REQUEST_METHOD, "GET");
+        Endpoint endpoint = control.createMock(Endpoint.class);
+        e.put(Endpoint.class, endpoint);
+        endpoint.get(ProviderFactory.class.getName());
+        EasyMock.expectLastCall().andReturn(ProviderFactory.getSharedInstance());
+        endpoint.getEndpointInfo();
+        EasyMock.expectLastCall().andReturn(epr).anyTimes();
+        control.replay();
+        return m;
+    }
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/codegen/CodeGeneratorProviderTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java Tue Mar  9 17:53:56 2010
@@ -150,6 +150,20 @@ public class UriBuilderImplTest extends 
     }
     
     @Test
+    public void testQueryWithNoValue() throws Exception {
+        URI uri = new URI("http://bar");
+        URI newUri = new UriBuilderImpl(uri).queryParam("q").build();   
+        assertEquals("URI is not built correctly", "http://bar?q", newUri.toString());
+    }
+    
+    @Test
+    public void testMatrixWithNoValue() throws Exception {
+        URI uri = new URI("http://bar/foo");
+        URI newUri = new UriBuilderImpl(uri).matrixParam("q").build();   
+        assertEquals("URI is not built correctly", "http://bar/foo;q", newUri.toString());
+    }
+    
+    @Test
     public void testSchemeSpecificPart() throws Exception {
         URI uri = new URI("http://bar");
         URI newUri = new UriBuilderImpl(uri).scheme("https").schemeSpecificPart("//localhost:8080/foo/bar")

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookStore.java Tue Mar  9 17:53:56 2010
@@ -102,6 +102,11 @@ public class BookStore {
         return new Chapter(1);
     }
     
+    @Path("form")
+    public FormInterface getForm() {
+        return new Book(1);
+    }
+    
     @Path("itself")
     public BookStore getItself() {
         return this;

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java?rev=921014&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java Tue Mar  9 17:53:56 2010
@@ -0,0 +1,34 @@
+/**
+ * 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.model.wadl;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MultivaluedMap;
+
+public interface FormInterface {
+    @Path("/form1")
+    @POST
+    void form1(MultivaluedMap map);
+    
+    @Path("/form2")
+    @POST
+    void form2(@FormParam("field1") String f1, @FormParam("field2") String f2);
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/FormInterface.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java Tue Mar  9 17:53:56 2010
@@ -329,13 +329,14 @@ public class WadlGeneratorTest extends A
         
         List<Element> resourceEls = DOMUtils.getChildrenWithName(resource, 
                                          WadlGenerator.WADL_NS, "resource");
-        assertEquals(6, resourceEls.size());        
+        assertEquals(7, resourceEls.size());        
         assertEquals("/book2", resourceEls.get(0).getAttribute("path"));
         assertEquals("/books/{bookid}", resourceEls.get(1).getAttribute("path"));
         assertEquals("/chapter", resourceEls.get(2).getAttribute("path"));
         assertEquals("/books/{bookid}", resourceEls.get(3).getAttribute("path"));
         assertEquals("/booksubresource", resourceEls.get(4).getAttribute("path"));
-        assertEquals("/itself", resourceEls.get(5).getAttribute("path"));
+        assertEquals("/form", resourceEls.get(5).getAttribute("path"));
+        assertEquals("/itself", resourceEls.get(6).getAttribute("path"));
         
         // verify root resource starting with "/"
         // must have a single template parameter

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java?rev=921014&r1=921013&r2=921014&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/jaxb/Book.java Tue Mar  9 17:53:56 2010
@@ -18,9 +18,7 @@
  */
 package org.apache.cxf.jaxrs.model.wadl.jaxb;
 
-import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -31,12 +29,13 @@ import javax.xml.bind.annotation.XmlType
 
 import org.apache.cxf.jaxrs.ext.Description;
 import org.apache.cxf.jaxrs.ext.xml.XMLName;
+import org.apache.cxf.jaxrs.model.wadl.FormInterface;
 
 @XmlRootElement(name = "thebook", namespace = "http://superbooks")
 @XmlType(name = "book", namespace = "http://superbooks")
 @Description("Book subresource")
 @XMLName(value = "{http://books}thesuperbook", prefix = "p1")
-public class Book {
+public class Book implements FormInterface {
 
     private int id;
     @XmlElement(name = "thechapter", namespace = "http://superbooks")
@@ -70,14 +69,10 @@ public class Book {
         return chapter;
     }
     
-    @Path("/form1")
-    @POST
     public void form1(MultivaluedMap map) {
     }
     
-    @Path("/form2")
-    @POST
-    public void form2(@FormParam("field1") String f1, @FormParam("field2") String f2) {
+    public void form2(String f1, String f2) {
     }
     
 }