Build Jersey on JDK13 (#4341)

* Able to compile with jdk13;  Added in new doclet

Signed-off-by: Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com>
diff --git a/.gitignore b/.gitignore
index 367c54d..9f7d5b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 # maven noise
 target/
+target-*/
 
 # gradle noise
 .gradle
diff --git a/.travis.yml b/.travis.yml
index de1dd18..7ab7480 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@
 jdk:
   - oraclejdk8
   - openjdk11
+  - openjdk13
 
 cache:
   directories:
diff --git a/ext/wadl-doclet/pom.xml b/ext/wadl-doclet/pom.xml
index c64f88b..d1d4a01 100644
--- a/ext/wadl-doclet/pom.xml
+++ b/ext/wadl-doclet/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Public License v. 2.0, which is available at
@@ -32,6 +32,14 @@
         of resource classes, so that this can be used for extending generated wadl with useful
         documentation.
     </description>
+    
+    <properties>
+        <java.sourceDirectory>${project.basedir}/src/main/java</java.sourceDirectory>
+        <java8_11.build.outputDirectory>${project.basedir}/target</java8_11.build.outputDirectory>
+        <java8_11.sourceDirectory>${project.basedir}/src/main/java8_11</java8_11.sourceDirectory>
+        <java12.build.outputDirectory>${project.basedir}/target-java12</java12.build.outputDirectory>
+        <java12.sourceDirectory>${project.basedir}/src/main/java12</java12.sourceDirectory>
+    </properties>
 
 
     <profiles>
@@ -66,6 +74,134 @@
             </dependencies>
         </profile>
         <profile>
+            <id>jdk1.8_11</id>
+            <activation>
+                <jdk>[1.8,12)</jdk>
+            </activation>
+            <build>
+            	<directory>${java8_11.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java.sourceDirectory}</source>
+                                        <source>${java8_11.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>jdk12+</id>
+            <activation>
+                <jdk>[12,)</jdk>
+            </activation>
+            <build>
+            	<directory>${java12.build.outputDirectory}</directory>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                        	<execution>
+                                <phase>generate-sources</phase>
+                                <goals>
+                                    <goal>add-source</goal>
+                                </goals>
+                                <configuration>
+                                    <sources>
+                                        <source>${java.sourceDirectory}</source>
+                                        <source>${java12.sourceDirectory}</source>
+                                    </sources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <!-- Only multi-release is supported when compiling from higher version to lower -->
+        <profile>
+            <id>copyJDK12FilesToMultiReleaseJar</id>
+            <activation>
+                <file>
+                    <!-- ${java12.build.outputDirectory} does not work here -->
+                    <exists>target-java12/classes/org/glassfish/jersey/wadl/doclet/ResourceDoclet.class</exists>
+                </file>
+                <jdk>[1.8,12)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.felix</groupId>
+                        <artifactId>maven-bundle-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <extensions>true</extensions>
+                        <configuration>
+                            <instructions>
+                                <Multi-Release>true</Multi-Release>
+                            </instructions>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-resources-plugin</artifactId>
+                        <inherited>true</inherited>
+                        <executions>
+                            <execution>
+                                <id>copy-jdk12-classes</id>
+                                <phase>prepare-package</phase>
+                                <goals>
+                                    <goal>copy-resources</goal>
+                                </goals>
+                                <configuration>
+                                    <outputDirectory>${java8_11.build.outputDirectory}/classes/META-INF/versions/12</outputDirectory>
+                                    <resources>
+                                        <resource>
+                                            <directory>${java12.build.outputDirectory}/classes</directory>
+                                        </resource>
+                                    </resources>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>copy-jdk12-sources</id>
+                                <phase>verify</phase>
+                                <configuration>
+                                    <target>
+                                    	<property name="sources-jar" value="${java8_11.build.outputDirectory}/${project.artifactId}-${project.version}-sources.jar"/>
+                                    	<echo>sources-jar: ${sources-jar}</echo>
+                                    	<zip destfile="${sources-jar}" update="true">
+                                    		<zipfileset dir="${java12.sourceDirectory}" prefix="META-INF/versions/12"/>
+										</zip>
+                                    </target>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                    	</executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
             <id>tools.jar</id>
             <activation>
                 <!-- Activation should be done with <file>${java.home}/../lib/tools.jar</file But this is not working with maven as the property is not expansed. -->
@@ -105,4 +241,5 @@
             </resource>
         </resources>
     </build>
+    
 </project>
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocletUtils.java b/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocletUtils.java
new file mode 100644
index 0000000..4dea216
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocletUtils.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import com.sun.org.apache.xml.internal.serialize.OutputFormat;
+import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResourceDocType;
+
+class DocletUtils {
+
+    private static final Logger LOG = Logger.getLogger(DocletUtils.class.getName());
+
+    private static String[] getCDataElements(DocProcessor docProcessor) {
+        String[] original = new String[]{"ns1^commentText", "ns2^commentText", "^commentText" };
+        if (docProcessor == null) {
+            return original;
+        } else {
+            String[] cdataElements = docProcessor.getCDataElements();
+            if (cdataElements == null || cdataElements.length == 0) {
+                return original;
+            } else {
+
+                String[] result = copyOf(original, original.length + cdataElements.length);
+                for (int i = 0; i < cdataElements.length; i++) {
+                    result[original.length + i] = cdataElements[i];
+                }
+                return result;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T, U> T[] copyOf(U[] original, int newLength) {
+        T[] copy = (original.getClass() == Object[].class) ? (T[]) new Object[newLength]
+                : (T[]) Array.newInstance(original.getClass().getComponentType(), newLength);
+        System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
+        return copy;
+    }
+
+    private static XMLSerializer getXMLSerializer(OutputStream os, String[] cdataElements)
+            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+        // configure an OutputFormat to handle CDATA
+        OutputFormat of = new OutputFormat();
+
+        // specify which of your elements you want to be handled as CDATA.
+        // The use of the '^' between the namespaceURI and the localname
+        // seems to be an implementation detail of the xerces code.
+        // When processing xml that doesn't use namespaces, simply omit the
+        // namespace prefix as shown in the third CDataElement below.
+        of.setCDataElements(cdataElements);
+
+        // set any other options you'd like
+        of.setPreserveSpace(true);
+        of.setIndenting(true);
+
+        // create the serializer
+        XMLSerializer serializer = new XMLSerializer(of);
+
+        serializer.setOutputByteStream(os);
+
+        return serializer;
+    }
+
+    private static Class<?>[] getJAXBContextClasses(ResourceDocType result, DocProcessor docProcessor) {
+        Class<?>[] clazzes;
+        if (docProcessor == null) {
+            clazzes = new Class<?>[1];
+        } else {
+            Class<?>[] requiredJaxbContextClasses = docProcessor.getRequiredJaxbContextClasses();
+            if (requiredJaxbContextClasses != null) {
+                clazzes = new Class<?>[1 + requiredJaxbContextClasses.length];
+                for (int i = 0; i < requiredJaxbContextClasses.length; i++) {
+                    clazzes[i + 1] = requiredJaxbContextClasses[i];
+                }
+            } else {
+                clazzes = new Class<?>[1];
+            }
+        }
+        clazzes[0] = result.getClass();
+        return clazzes;
+    }
+
+    static boolean createOutputFile(String filePath, DocProcessor docProcessor, ResourceDocType result) {
+        try (OutputStream out = new BufferedOutputStream(new FileOutputStream(filePath))) {
+            Class<?>[] clazzes = getJAXBContextClasses(result, docProcessor);
+            JAXBContext c = JAXBContext.newInstance(clazzes);
+            Marshaller m = c.createMarshaller();
+            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+            String[] cdataElements = getCDataElements(docProcessor);
+            XMLSerializer serializer = getXMLSerializer(out, cdataElements);
+            m.marshal(result, serializer);
+            LOG.info("Wrote " + result);
+            return true;
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Could not serialize ResourceDoc.", e);
+            return false;
+        }
+    }
+
+    static String getLinkClass(String className, String field) {
+        Object object;
+        try {
+            Field declaredField = Class.forName(className, false, Thread.currentThread()
+                    .getContextClassLoader()).getDeclaredField(field);
+            declaredField.setAccessible(true);
+            object = declaredField.get(null);
+            LOG.log(Level.FINE, "Got object " + object);
+        } catch (final Exception e) {
+            LOG.info("Have classloader: " + ResourceDoclet.class.getClassLoader().getClass());
+            LOG.info("Have thread classloader " + Thread.currentThread().getContextClassLoader().getClass());
+            LOG.info("Have system classloader " + ClassLoader.getSystemClassLoader().getClass());
+            LOG.log(Level.SEVERE, "Could not get field " + className, e);
+            return null;
+        }
+
+        /* marshal the bean to xml
+         */
+        try {
+            JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
+            StringWriter stringWriter = new StringWriter();
+            Marshaller marshaller = jaxbContext.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+            marshaller.marshal(object, stringWriter);
+            String result = stringWriter.getBuffer().toString();
+            LOG.log(Level.FINE, "Got marshalled output:\n" + result);
+            return result;
+        } catch (final Exception e) {
+            LOG.log(Level.SEVERE, "Could serialize bean to xml: " + object, e);
+            return null;
+        }
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessor.java
similarity index 81%
copy from ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java
copy to ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessor.java
index 61d832e..3f10dc8 100644
--- a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,10 +20,9 @@
 import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.MethodDocType;
 import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ParamDocType;
 
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.ParamTag;
-import com.sun.javadoc.Parameter;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
 
 /**
  * A doc processor is handed over javadoc elements so that it can turn this into
@@ -55,33 +54,31 @@
 
     /**
      * Use this method to extend the provided {@link ClassDocType} with the information from
-     * the given {@link ClassDoc}.
+     * the given {@link TypeElement}.
      *
      * @param classDoc     the class javadoc
      * @param classDocType the {@link ClassDocType} to extend. This will later be processed by the
      *                     {@link org.glassfish.jersey.server.wadl.WadlGenerator}s.
      */
-    void processClassDoc(ClassDoc classDoc, ClassDocType classDocType);
+    void processClassDoc(TypeElement classDoc, ClassDocType classDocType);
 
     /**
      * Process the provided methodDoc and add your custom information to the methodDocType.<br>
-     * Use e.g. {@link MethodDocType#getAny()} to store custom elements.
      *
-     * @param methodDoc     the {@link MethodDoc} representing the docs of your method.
+     * @param methodDoc     the {@link ExecutableElement} representing the docs of your method.
      * @param methodDocType the related {@link MethodDocType} that will later be processed by the
      *                      {@link org.glassfish.jersey.server.wadl.WadlGenerator}s.
      */
-    void processMethodDoc(MethodDoc methodDoc, MethodDocType methodDocType);
+    void processMethodDoc(ExecutableElement methodDoc, MethodDocType methodDocType);
 
     /**
      * Use this method to extend the provided {@link ParamDocType} with the information from the
      * given {@link ParamTag} and {@link Parameter}.
      *
-     * @param paramTag     the parameter javadoc
      * @param parameter    the parameter (that is documented or not)
      * @param paramDocType the {@link ParamDocType} to extend. This will later be processed by the
      *                     {@link org.glassfish.jersey.server.wadl.WadlGenerator}s.
      */
-    void processParamTag(ParamTag paramTag, Parameter parameter, ParamDocType paramDocType);
+    void processParamTag(VariableElement parameter, ParamDocType paramDocType);
 
 }
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
similarity index 82%
copy from ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
copy to ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
index 8dec3b5..aa3e28d 100644
--- a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,16 +24,11 @@
 import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.MethodDocType;
 import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ParamDocType;
 
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.ParamTag;
-import com.sun.javadoc.Parameter;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.ExecutableElement;
+import com.sun.source.doctree.ParamTree;
+import javax.lang.model.element.VariableElement;
 
-/**
- * This {@link DocProcessor} wraps multiple {@code DocProcessor}s.
- *
- * @author Martin Grotzke (martin.grotzke at freiheit.com)
- */
 public class DocProcessorWrapper implements DocProcessor {
 
     private final List<DocProcessor> _docProcessors;
@@ -79,14 +74,14 @@
     }
 
     @Override
-    public void processClassDoc(ClassDoc classDoc, ClassDocType classDocType) {
+    public void processClassDoc(TypeElement classDoc, ClassDocType classDocType) {
         for (DocProcessor docProcessor : _docProcessors) {
             docProcessor.processClassDoc(classDoc, classDocType);
         }
     }
 
     @Override
-    public void processMethodDoc(MethodDoc methodDoc,
+    public void processMethodDoc(ExecutableElement methodDoc,
                                  MethodDocType methodDocType) {
         for (DocProcessor docProcessor : _docProcessors) {
             docProcessor.processMethodDoc(methodDoc, methodDocType);
@@ -94,10 +89,10 @@
     }
 
     @Override
-    public void processParamTag(ParamTag paramTag, Parameter parameter,
+    public void processParamTag(VariableElement parameter,
                                 ParamDocType paramDocType) {
         for (DocProcessor docProcessor : _docProcessors) {
-            docProcessor.processParamTag(paramTag, parameter, paramDocType);
+            docProcessor.processParamTag(parameter, paramDocType);
         }
     }
 
diff --git a/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/Loader.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/Loader.java
new file mode 100644
index 0000000..43f2515
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/Loader.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+class Loader extends URLClassLoader {
+
+    public Loader(final String[] paths, final ClassLoader parent) {
+        super(getURLs(paths), parent);
+    }
+
+    Loader(final String[] paths) {
+        super(getURLs(paths));
+    }
+
+    private static URL[] getURLs(final String[] paths) {
+        final List<URL> urls = new ArrayList<>();
+        for (final String path : paths) {
+            try {
+                urls.add(new File(path).toURI().toURL());
+            } catch (final MalformedURLException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return urls.toArray(new URL[urls.size()]);
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionClasspath.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionClasspath.java
new file mode 100644
index 0000000..c11da14
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionClasspath.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import jdk.javadoc.doclet.Doclet.Option;
+
+class OptionClasspath implements Option {
+
+    private final List<String> argNames = Arrays.asList("-classpath");
+    private String[] classpathElements;
+
+    @Override
+    public int getArgumentCount() {
+        return 1;
+    }
+
+    @Override
+    public String getDescription() {
+        return "Specifies classpath split by :";
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.STANDARD;
+    }
+
+    @Override
+    public List<String> getNames() {
+        return argNames;
+    }
+
+    @Override
+    public String getParameters() {
+        return "classpath";
+    }
+
+    @Override
+    public boolean process(String option, List<String> arguments) {
+        classpathElements =  arguments.get(0).split(File.pathSeparator);
+        return true;
+    }
+
+    public String[] getClasspathElements() {
+        return classpathElements;
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionDocprocessor.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionDocprocessor.java
new file mode 100644
index 0000000..1372e8e
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionDocprocessor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import java.util.Arrays;
+import java.util.List;
+
+import jdk.javadoc.doclet.Doclet.Option;
+
+class OptionDocprocessor implements Option {
+
+    private final List<String> argNames = Arrays.asList("-processors");
+    private String[] docProcessors = new String[0];
+
+    @Override
+    public int getArgumentCount() {
+        return 1;
+    }
+
+    @Override
+    public String getDescription() {
+        return "Specifies the document processors split by :";
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.STANDARD;
+    }
+
+    @Override
+    public List<String> getNames() {
+        return argNames;
+    }
+
+    @Override
+    public String getParameters() {
+        return "processors";
+    }
+
+    @Override
+    public boolean process(String option, List<String> arguments) {
+        if (!arguments.isEmpty()) {
+            docProcessors = arguments.get(0).split(":");
+        }
+        return true;
+    }
+
+    public String[] getDocProcessors() {
+        return docProcessors;
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionOutput.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionOutput.java
new file mode 100644
index 0000000..822d275
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/OptionOutput.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import java.util.Arrays;
+import java.util.List;
+
+import jdk.javadoc.doclet.Doclet.Option;
+
+class OptionOutput implements Option {
+
+    private final List<String> argNames = Arrays.asList("-output");
+    private String value;
+
+    @Override
+    public int getArgumentCount() {
+        return 1;
+    }
+
+    @Override
+    public String getDescription() {
+        return "Specifies the output for resourcedoc.xml";
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.STANDARD;
+    }
+
+    @Override
+    public List<String> getNames() {
+        return argNames;
+    }
+
+    @Override
+    public String getParameters() {
+        return "output";
+    }
+
+    @Override
+    public boolean process(String option, List<String> arguments) {
+        value = arguments.get(0);
+        return true;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
new file mode 100644
index 0000000..944413f
--- /dev/null
+++ b/ext/wadl-doclet/src/main/java12/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.wadl.doclet;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.util.DocTrees;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.Diagnostic.Kind;
+import javax.xml.namespace.QName;
+
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.AnnotationDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ClassDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.MethodDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.NamedValueType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ParamDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.RepresentationDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.RequestDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResourceDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResponseDocType;
+import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.WadlParamType;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+
+/**
+ * Creates a resourcedoc XML file.
+ * <p/>
+ * <p>
+ * The ResourceDoc file contains the javadoc documentation of resource classes,
+ * so that this can be used for extending generated wadl with useful
+ * documentation.
+ * </p>
+ *
+ * @author <a href="mailto:jorge.bescos.gascon@oracle.com">Jorge Bescos
+ *         Gascon</a>
+ */
+public class ResourceDoclet implements Doclet {
+
+    private static final Logger LOG = Logger.getLogger(ResourceDoclet.class.getName());
+    private static final Pattern PATTERN_RESPONSE_REPRESENTATION = Pattern.compile("@response\\.representation\\.([\\d]+)\\..*");
+    private static final Pattern PATTERN_INLINE_TAG = Pattern
+            .compile("(?!\\{)[\\w\\?\\!\\#\\<\\>\\.\\ \\/\\:\\\\-\\{\\}]+(?=\\})");
+    private static final String COMA = ", ";
+    private static final String EMPTY = "";
+    private static final String SPACE = " ";
+    private final OptionOutput optionOutput = new OptionOutput();
+    private final OptionClasspath optionClasspath = new OptionClasspath();
+    private final OptionDocprocessor optionDocprocessor = new OptionDocprocessor();
+
+    @Override
+    public void init(Locale locale, Reporter reporter) {
+        reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
+    }
+
+    private String getComments(DocCommentTree docCommentTree) {
+        if (docCommentTree != null) {
+            StringBuilder body = new StringBuilder();
+            docCommentTree.getFullBody().forEach(doc -> body.append(doc.toString()));
+            return body.toString();
+        } else {
+            return EMPTY;
+        }
+    }
+
+    private Map<DocTree.Kind, Map<String, String>> getTags(DocCommentTree docCommentTree) {
+        Map<DocTree.Kind, Map<String, String>> tags = new HashMap<>();
+        if (docCommentTree != null) {
+            for (DocTree tag : docCommentTree.getBlockTags()) {
+                Map<String, String> tagsInKind = tags.get(tag.getKind());
+                if (tagsInKind == null) {
+                    tagsInKind = new HashMap<>();
+                    tags.put(tag.getKind(), tagsInKind);
+                }
+                String[] kindValuePair = getTagPair(tag.toString());
+                if (tag.getKind() == DocTree.Kind.PARAM) {
+                    // Adds the parameter name and description
+                    String[] paramValuePair = getTagPair(kindValuePair[1]);
+                    tagsInKind.put(paramValuePair[0], paramValuePair[1]);
+                } else {
+                    // Adds the @tag name and description
+                    tagsInKind.put(kindValuePair[0], kindValuePair[1]);
+                }
+            }
+        }
+        return tags;
+    }
+
+    private String[] getTagPair(String tag) {
+        String[] pair = tag.split(SPACE, 2);
+        if (pair.length != 2) {
+            pair = new String[]{pair[0], null};
+        }
+        return pair;
+    }
+
+    @Override
+    public boolean run(DocletEnvironment docEnv) {
+        boolean success = true;
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        try {
+            ClassLoader ncl = new Loader(optionClasspath.getClasspathElements(), ResourceDoclet.class.getClassLoader());
+            Thread.currentThread().setContextClassLoader(ncl);
+            DocProcessorWrapper docProcessor = new DocProcessorWrapper();
+            if (optionDocprocessor.getDocProcessors().length != 0) {
+                try {
+                    Class<?> clazz = Class.forName(optionDocprocessor.getDocProcessors()[0], true,
+                            Thread.currentThread().getContextClassLoader());
+                    Class<? extends DocProcessor> dpClazz = clazz.asSubclass(DocProcessor.class);
+                    docProcessor.add((DocProcessor) dpClazz.getDeclaredConstructors()[0].newInstance());
+                } catch (Exception e) {
+                    LOG.log(Level.SEVERE,
+                            "Could not load docProcessors " + Arrays.asList(optionDocprocessor.getDocProcessors()), e);
+                }
+            }
+            ResourceDocType result = new ResourceDocType();
+            for (TypeElement element : ElementFilter.typesIn(docEnv.getIncludedElements())) {
+                DocTrees docTrees = docEnv.getDocTrees();
+                DocCommentTree docCommentTree = docTrees.getDocCommentTree(element);
+                if (docCommentTree != null) {
+                    ClassDocType classDocType = new ClassDocType();
+                    classDocType.setClassName(element.getQualifiedName().toString());
+                    classDocType.setCommentText(getComments(docCommentTree));
+                    docProcessor.processClassDoc(element, classDocType);
+                    for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
+                        Map<DocTree.Kind, Map<String, String>> tags = getTags(docTrees.getDocCommentTree(method));
+                        MethodTree methodTree = docTrees.getTree(method);
+                        MethodDocType methodDocType = new MethodDocType();
+                        methodDocType.setMethodName(methodTree.getName().toString());
+                        methodDocType.setCommentText(getComments(docTrees.getDocCommentTree(method)));
+                        getTags(docTrees.getDocCommentTree(method));
+                        StringBuilder arguments = new StringBuilder("(");
+                        Map<String, String> paramTags = tags.get(DocTree.Kind.PARAM);
+                        for (VariableElement parameter : method.getParameters()) {
+                            ParamDocType paramDocType = buildParamDocType(parameter, paramTags);
+                            arguments.append(parameter.asType()).append(COMA);
+                            if (paramDocType != null) {
+                                methodDocType.getParamDocs().add(paramDocType);
+                                docProcessor.processParamTag(parameter, paramDocType);
+                            }
+                        }
+                        // Remove last comma if there are parameters
+                        if (arguments.length() != 1) {
+                            arguments.delete(arguments.length() - COMA.length(), arguments.length());
+                        }
+                        arguments.append(")");
+                        methodDocType.setMethodSignature(arguments.toString());
+                        docProcessor.processMethodDoc(method, methodDocType);
+                        methodDocType.setRequestDoc(buildRequestDocType(tags));
+                        methodDocType.setResponseDoc(buildResponseDocType(tags));
+                        classDocType.getMethodDocs().add(methodDocType);
+                    }
+                    result.getDocs().add(classDocType);
+                    success = DocletUtils.createOutputFile(optionOutput.getValue(), docProcessor, result);
+                    
+                }
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(cl);
+        }
+        return success;
+    }
+
+    private ParamDocType buildParamDocType(VariableElement parameter, Map<String, String> paramTags) {
+        if (paramTags != null) {
+            ParamDocType paramDocType = new ParamDocType();
+            paramDocType.setParamName(parameter.getSimpleName().toString());
+            paramDocType.setCommentText(paramTags.get(paramDocType.getParamName()));
+            for (AnnotationMirror annotation : parameter.getAnnotationMirrors()) {
+                AnnotationDocType annotationDocType = new AnnotationDocType();
+                annotationDocType.setAnnotationTypeName(annotation.getAnnotationType().toString());
+                for (Entry<? extends ExecutableElement, ? extends AnnotationValue> pair : annotation.getElementValues()
+                        .entrySet()) {
+                    NamedValueType namedValueType = new NamedValueType();
+                    namedValueType.setName(pair.getKey().getSimpleName().toString());
+                    namedValueType.setValue(pair.getValue().getValue().toString());
+                    annotationDocType.getAttributeDocs().add(namedValueType);
+                }
+                paramDocType.getAnnotationDocs().add(annotationDocType);
+            }
+            return paramDocType;
+        }
+        return null;
+    }
+
+    private RequestDocType buildRequestDocType(Map<DocTree.Kind, Map<String, String>> tags) {
+        Map<String, String> customTags = tags.get(DocTree.Kind.UNKNOWN_BLOCK_TAG);
+        if (customTags != null) {
+            RequestDocType requestDoc = new RequestDocType();
+            RepresentationDocType representationDoc = new RepresentationDocType();
+            String qname = customTags.get("@request.representation.qname");
+            String example = customTags.get("@request.representation.example");
+            if (qname != null) {
+                representationDoc.setElement(QName.valueOf(qname));
+            }
+            if (example != null) {
+                representationDoc.setExample(getSerializedExample(example));
+            }
+            if (qname != null || example != null) {
+                requestDoc.setRepresentationDoc(representationDoc);
+                return requestDoc;
+            }
+        }
+        return null;
+    }
+
+    private ResponseDocType buildResponseDocType(Map<DocTree.Kind, Map<String, String>> tags) {
+        ResponseDocType responseDoc = new ResponseDocType();
+        Map<String, String> returnDoc = tags.get(DocTree.Kind.RETURN);
+        if (returnDoc != null) {
+            responseDoc.setReturnDoc(returnDoc.get("@return"));
+        }
+        Map<String, String> customTags = tags.get(DocTree.Kind.UNKNOWN_BLOCK_TAG);
+        if (customTags != null) {
+            String responseParam = customTags.remove("@response.param");
+            if (responseParam != null) {
+                Matcher matcher = PATTERN_INLINE_TAG.matcher(responseParam);
+                WadlParamType wadlParam = new WadlParamType();
+                while (matcher.find()) {
+                    String group = matcher.group();
+                    String[] pair = getTagPair(group);
+                    switch (pair[0]) {
+                    case "name":
+                        wadlParam.setName(pair[1]);
+                        break;
+                    case "style":
+                        wadlParam.setStyle(pair[1]);
+                        break;
+                    case "type":
+                        wadlParam.setType(QName.valueOf(pair[1]));
+                        break;
+                    case "doc":
+                        wadlParam.setDoc(pair[1]);
+                        break;
+                    default:
+                        LOG.warning("Unknown inline tag of @response.param: @" + pair[0] + " (value: " + pair[1] + ")");
+                        break;
+                    }
+                }
+                responseDoc.getWadlParams().add(wadlParam);
+            }
+            Map<Long, RepresentationDocType> groupedRepresentationDocType = new HashMap<>();
+            for (Entry<String, String> entry : customTags.entrySet()) {
+                if (entry.getKey().startsWith("@response.representation")) {
+                    String[] keySplit = entry.getKey().split("\\.");
+                    long httpCode = Long.parseLong(keySplit[2]);
+                    RepresentationDocType representationDoc = groupedRepresentationDocType.get(httpCode);
+                    if (representationDoc == null) {
+                        representationDoc = new RepresentationDocType();
+                        representationDoc.setStatus(httpCode);
+                        groupedRepresentationDocType.put(httpCode, representationDoc);
+                    }
+                    if ("qname".equals(keySplit[3])) {
+                        representationDoc.setElement(QName.valueOf(entry.getValue()));
+                    } else if ("mediaType".equals(keySplit[3])) {
+                        representationDoc.setMediaType(entry.getValue());
+                    } else if ("example".equals(getSerializedExample(keySplit[3]))) {
+                        representationDoc.setExample(getSerializedExample(entry.getValue()));
+                    } else if ("doc".equals(keySplit[3])) {
+                        representationDoc.setDoc(entry.getValue());
+                    } else {
+                        LOG.warning("Unknown response representation tag " + entry.getKey());
+                    }
+                }
+            }
+            responseDoc.getRepresentations().addAll(groupedRepresentationDocType.values());
+        }
+        return responseDoc;
+    }
+
+    @Override
+    public String getName() {
+        return getClass().getCanonicalName();
+    }
+
+    @Override
+    public Set<? extends Option> getSupportedOptions() {
+        return new HashSet<>(Arrays.asList(optionOutput, optionClasspath, optionDocprocessor));
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private String getSerializedExample(String tag) {
+        if (tag != null) {
+            Matcher matcher = PATTERN_INLINE_TAG.matcher(tag);
+            while (matcher.find()) {
+                String group = matcher.group();
+                String[] pair = getTagPair(group);
+                if ("link".equals(pair[0])) {
+                    String[] classAndField = pair[1].split("#");
+                    return DocletUtils.getLinkClass(classAndField[0], classAndField[1]);
+                } else {
+                    return pair[1];
+                }
+            }
+        }
+        return tag;
+    }
+
+}
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessor.java
similarity index 98%
rename from ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java
rename to ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessor.java
index 61d832e..962b065 100644
--- a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessor.java
+++ b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
similarity index 98%
rename from ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
rename to ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
index 8dec3b5..e982e84 100644
--- a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
+++ b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/DocProcessorWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
similarity index 78%
rename from ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
rename to ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
index a6b472d..b19eb11 100644
--- a/ext/wadl-doclet/src/main/java/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
+++ b/ext/wadl-doclet/src/main/java8_11/org/glassfish/jersey/wadl/doclet/ResourceDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -96,6 +96,7 @@
      * @return true if no exception is thrown.
      */
     public static boolean start(final RootDoc root) {
+        boolean success = true;
         final String output = getOptionArg(root.options(), OPTION_OUTPUT);
 
         final String classpath = getOptionArg(root.options(), OPTION_CLASSPATH);
@@ -151,104 +152,12 @@
                 result.getDocs().add(classDocType);
             }
 
-            try {
-                final Class<?>[] clazzes = getJAXBContextClasses(result, docProcessor);
-                final JAXBContext c = JAXBContext.newInstance(clazzes);
-                final Marshaller m = c.createMarshaller();
-                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-                final OutputStream out = new BufferedOutputStream(new FileOutputStream(output));
-
-                final String[] cdataElements = getCDataElements(docProcessor);
-                final XMLSerializer serializer = getXMLSerializer(out, cdataElements);
-
-                m.marshal(result, serializer);
-                out.close();
-
-                LOG.info("Wrote " + output);
-
-            } catch (final Exception e) {
-                LOG.log(Level.SEVERE, "Could not serialize ResourceDoc.", e);
-                return false;
-            }
+            success = DocletUtils.createOutputFile(output, docProcessor, result);
         } finally {
             Thread.currentThread().setContextClassLoader(cl);
         }
 
-        return true;
-    }
-
-    private static String[] getCDataElements(final DocProcessor docProcessor) {
-        final String[] original = new String[] {"ns1^commentText", "ns2^commentText", "^commentText"};
-        if (docProcessor == null) {
-            return original;
-        } else {
-            final String[] cdataElements = docProcessor.getCDataElements();
-            if (cdataElements == null || cdataElements.length == 0) {
-                return original;
-            } else {
-
-                final String[] result = copyOf(original, original.length + cdataElements.length);
-                for (int i = 0; i < cdataElements.length; i++) {
-                    result[original.length + i] = cdataElements[i];
-                }
-                return result;
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T, U> T[] copyOf(final U[] original, final int newLength) {
-        final T[] copy = (original.getClass() == Object[].class)
-                ? (T[]) new Object[newLength]
-                : (T[]) Array.newInstance(original.getClass().getComponentType(), newLength);
-        System.arraycopy(original, 0, copy, 0,
-                Math.min(original.length, newLength));
-        return copy;
-    }
-
-    private static Class<?>[] getJAXBContextClasses(
-            final ResourceDocType result, final DocProcessor docProcessor) {
-        final Class<?>[] clazzes;
-        if (docProcessor == null) {
-            clazzes = new Class<?>[1];
-        } else {
-            final Class<?>[] requiredJaxbContextClasses = docProcessor.getRequiredJaxbContextClasses();
-            if (requiredJaxbContextClasses != null) {
-                clazzes = new Class<?>[1 + requiredJaxbContextClasses.length];
-                for (int i = 0; i < requiredJaxbContextClasses.length; i++) {
-                    clazzes[i + 1] = requiredJaxbContextClasses[i];
-                }
-            } else {
-                clazzes = new Class<?>[1];
-            }
-        }
-        clazzes[0] = result.getClass();
-        return clazzes;
-    }
-
-    private static XMLSerializer getXMLSerializer(final OutputStream os, final String[] cdataElements)
-            throws InstantiationException,
-            IllegalAccessException, ClassNotFoundException {
-        // configure an OutputFormat to handle CDATA
-        final OutputFormat of = new OutputFormat();
-
-        // specify which of your elements you want to be handled as CDATA.
-        // The use of the '^' between the namespaceURI and the localname
-        // seems to be an implementation detail of the xerces code.
-        // When processing xml that doesn't use namespaces, simply omit the
-        // namespace prefix as shown in the third CDataElement below.
-        of.setCDataElements(cdataElements);
-
-        // set any other options you'd like
-        of.setPreserveSpace(true);
-        of.setIndenting(true);
-
-        // create the serializer
-        final XMLSerializer serializer = new XMLSerializer(of);
-
-        serializer.setOutputByteStream(os);
-
-        return serializer;
+        return success;
     }
 
     private static void addResponseDoc(final MethodDoc methodDoc,
@@ -479,39 +388,9 @@
 
         /* Get referenced example bean
          */
+        
         final ClassDoc containingClass = referencedMember.containingClass();
-        final Object object;
-        try {
-            final Field declaredField = Class.forName(containingClass.qualifiedName(), false, Thread.currentThread()
-                    .getContextClassLoader()).getDeclaredField(referencedMember.name());
-            if (referencedMember.isFinal()) {
-                declaredField.setAccessible(true);
-            }
-            object = declaredField.get(null);
-            LOG.log(Level.FINE, "Got object " + object);
-        } catch (final Exception e) {
-            LOG.info("Have classloader: " + ResourceDoclet.class.getClassLoader().getClass());
-            LOG.info("Have thread classloader " + Thread.currentThread().getContextClassLoader().getClass());
-            LOG.info("Have system classloader " + ClassLoader.getSystemClassLoader().getClass());
-            LOG.log(Level.SEVERE, "Could not get field " + referencedMember.qualifiedName(), e);
-            return null;
-        }
-
-        /* marshal the bean to xml
-         */
-        try {
-            final JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
-            final StringWriter stringWriter = new StringWriter();
-            final Marshaller marshaller = jaxbContext.createMarshaller();
-            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-            marshaller.marshal(object, stringWriter);
-            final String result = stringWriter.getBuffer().toString();
-            LOG.log(Level.FINE, "Got marshalled output:\n" + result);
-            return result;
-        } catch (final Exception e) {
-            LOG.log(Level.SEVERE, "Could serialize bean to xml: " + object, e);
-            return null;
-        }
+        return DocletUtils.getLinkClass(containingClass.qualifiedName(), referencedMember.name());
     }
 
     private static String print(final Tag tag) {