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 2013/12/27 19:10:38 UTC
svn commit: r1553709 - in /cxf/trunk/rt/rs/description/src:
main/java/org/apache/cxf/jaxrs/model/wadl/
test/java/org/apache/cxf/jaxrs/model/wadl/
test/java/org/apache/cxf/jaxrs/model/wadl/petstore/ test/resources/javadocs/
Author: sergeyb
Date: Fri Dec 27 18:10:38 2013
New Revision: 1553709
URL: http://svn.apache.org/r1553709
Log:
[CXF-5353] Initial attempt at scraping Java docs from HTML
Added:
cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java (with props)
cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java (with props)
cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java (with props)
cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/
cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java (with props)
cxf/trunk/rt/rs/description/src/test/resources/javadocs/
cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc16.jar (with props)
cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc17.jar (with props)
Modified:
cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
Added: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java?rev=1553709&view=auto
==============================================================================
--- cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java (added)
+++ cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java Fri Dec 27 18:10:38 2013
@@ -0,0 +1,29 @@
+/**
+ * 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 org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+
+public interface DocumentationProvider {
+ String getClassDoc(ClassResourceInfo cri);
+ String getMethodDoc(OperationResourceInfo ori);
+ String getMethodResponseDoc(OperationResourceInfo ori);
+ String getMethodParameterDoc(OperationResourceInfo ori, int paramIndex);
+}
Propchange: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/DocumentationProvider.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java?rev=1553709&view=auto
==============================================================================
--- cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java (added)
+++ cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java Fri Dec 27 18:10:38 2013
@@ -0,0 +1,301 @@
+/**
+ * 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 java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+
+public class JavaDocProvider implements DocumentationProvider {
+ public static final double JAVA_VERSION = getVersion();
+ public static final double JAVA_VERSION_16 = 1.6D;
+
+ private ClassLoader javaDocLoader;
+ private ConcurrentHashMap<String, ClassDocs> docs = new ConcurrentHashMap<String, ClassDocs>();
+
+ public JavaDocProvider(URL javaDocUrl) {
+ if (javaDocUrl == null) {
+ throw new IllegalArgumentException("URL is null");
+ }
+ javaDocLoader = new URLClassLoader(new URL[]{javaDocUrl});
+ }
+
+ public JavaDocProvider(String path) throws Exception {
+ this(BusFactory.getDefaultBus(), path);
+ }
+
+ public JavaDocProvider(Bus bus, String path) throws Exception {
+ this(ResourceUtils.getResourceURL(path, bus));
+ }
+
+ private static double getVersion() {
+ String version = System.getProperty("java.version");
+ try {
+ return Double.parseDouble(version.substring(0, 3));
+ } catch (Exception ex) {
+ return JAVA_VERSION_16;
+ }
+ }
+
+ public String getClassDoc(ClassResourceInfo cri) {
+ try {
+ ClassDocs doc = getClassDocInternal(cri);
+ if (doc == null) {
+ return null;
+ }
+ return doc.getClassInfo();
+ } catch (Exception ex) {
+ // ignore
+ }
+ return null;
+ }
+
+ public String getMethodDoc(OperationResourceInfo ori) {
+ try {
+ MethodDocs doc = getOperationDocInternal(ori);
+ if (doc == null) {
+ return null;
+ }
+ return doc.getMethodInfo();
+ } catch (Exception ex) {
+ // ignore
+ }
+ return null;
+ }
+
+ public String getMethodResponseDoc(OperationResourceInfo ori) {
+ try {
+ MethodDocs doc = getOperationDocInternal(ori);
+ if (doc == null) {
+ return null;
+ }
+ return doc.getResponseInfo();
+ } catch (Exception ex) {
+ // ignore
+ }
+ return null;
+ }
+
+ public String getMethodParameterDoc(OperationResourceInfo ori, int paramIndex) {
+ try {
+ MethodDocs doc = getOperationDocInternal(ori);
+ if (doc == null) {
+ return null;
+ }
+ List<String> params = doc.getParamInfo();
+ if (paramIndex < params.size()) {
+ return params.get(paramIndex);
+ } else {
+ return null;
+ }
+ } catch (Exception ex) {
+ // ignore
+ }
+ return null;
+ }
+
+ private ClassDocs getClassDocInternal(ClassResourceInfo cri) throws Exception {
+ String resource = cri.getServiceClass().getName().replace(".", "/") + ".html";
+ ClassDocs classDocs = docs.get(resource);
+ if (classDocs == null) {
+ InputStream resourceStream = javaDocLoader.getResourceAsStream(resource);
+ if (resourceStream != null) {
+ String doc = IOUtils.readStringFromStream(resourceStream);
+
+ String classMarker = "Class " + cri.getServiceClass().getSimpleName();
+ int index = doc.indexOf(classMarker);
+ if (index != -1) {
+ String classInfoTag = getClassInfoTag();
+ String classInfo = getJavaDocText(doc, classInfoTag,
+ "Method Summary", index + classMarker.length());
+ classDocs = new ClassDocs(doc, classInfo);
+ docs.putIfAbsent(resource, classDocs);
+ }
+ }
+ }
+ return classDocs;
+ }
+
+
+ private MethodDocs getOperationDocInternal(OperationResourceInfo ori) throws Exception {
+ ClassDocs classDoc = getClassDocInternal(ori.getClassResourceInfo());
+ if (classDoc == null) {
+ return null;
+ }
+ String methodName = ori.getMethodToInvoke().getName();
+ MethodDocs mDocs = classDoc.getMethodDocs(methodName);
+ if (mDocs == null) {
+ String operLink = getOperLink();
+ String operMarker = operLink + methodName + "(";
+ int operMarkerIndex = classDoc.getClassDoc().indexOf(operMarker);
+ if (operMarkerIndex == -1) {
+ return null;
+ }
+ String operDoc = classDoc.getClassDoc().substring(operMarkerIndex + operMarker.length());
+ String operInfoTag = getOperInfoTag();
+ String operInfo = getJavaDocText(operDoc, operInfoTag, operLink, 0);
+ String responseInfo = null;
+ List<String> paramDocs = new LinkedList<String>();
+ if (!StringUtils.isEmpty(operInfo)) {
+ int returnsIndex = operDoc.indexOf("Returns:", operLink.length());
+ int nextOpIndex = operDoc.indexOf(operLink);
+ if (returnsIndex != -1 && (nextOpIndex > returnsIndex || nextOpIndex == -1)) {
+ responseInfo = getJavaDocText(operDoc, getResponseMarker(), operLink, returnsIndex + 8);
+ }
+
+ int paramIndex = operDoc.indexOf("Parameters:");
+ if (paramIndex != -1 && (nextOpIndex == -1 || paramIndex < nextOpIndex)) {
+ String paramString = returnsIndex == -1 ? operDoc.substring(paramIndex)
+ : operDoc.substring(paramIndex, returnsIndex);
+
+ String codeTag = getCodeTag();
+
+ int codeIndex = paramString.indexOf(codeTag);
+ while (codeIndex != -1) {
+ int next = paramString.indexOf("<", codeIndex + 7);
+ if (next == -1) {
+ next = paramString.length();
+ }
+ String param = paramString.substring(codeIndex + 7, next).trim();
+ if (param.startsWith("-")) {
+ param = param.substring(1).trim();
+ }
+ paramDocs.add(param);
+ if (next == paramString.length()) {
+ break;
+ } else {
+ codeIndex = next + 1;
+ }
+ codeIndex = paramString.indexOf(codeTag, codeIndex);
+ }
+
+ }
+ }
+ mDocs = new MethodDocs(operInfo, paramDocs, responseInfo);
+ classDoc.addMethodDocs(methodName, mDocs);
+ }
+
+ return mDocs;
+ }
+
+
+
+ private String getJavaDocText(String doc, String tag, String notAfterTag, int index) {
+ int tagIndex = doc.indexOf(tag, index);
+ if (tagIndex != -1) {
+ int notAfterIndex = doc.indexOf(notAfterTag, index);
+ if (notAfterIndex == -1 || notAfterIndex > tagIndex) {
+ int nextIndex = doc.indexOf("<", tagIndex + tag.length());
+ if (nextIndex != -1) {
+ return doc.substring(tagIndex + tag.length(), nextIndex).trim();
+ }
+ }
+ }
+ return null;
+ }
+
+ protected String getClassInfoTag() {
+ if (JAVA_VERSION == JAVA_VERSION_16) {
+ return "<P>";
+ } else {
+ return "<div class=\"block\">";
+ }
+ }
+ protected String getOperInfoTag() {
+ if (JAVA_VERSION == JAVA_VERSION_16) {
+ return "<DD>";
+ } else {
+ return "<div class=\"block\">";
+ }
+ }
+ protected String getOperLink() {
+ String operLink = "<A NAME=\"";
+ return JAVA_VERSION == JAVA_VERSION_16 ? operLink : operLink.toLowerCase();
+ }
+
+ protected String getResponseMarker() {
+ String tag = "<DD>";
+ return JAVA_VERSION == JAVA_VERSION_16 ? tag : tag.toLowerCase();
+ }
+
+ protected String getCodeTag() {
+ String tag = "</CODE>";
+ return JAVA_VERSION == JAVA_VERSION_16 ? tag : tag.toLowerCase();
+ }
+ private static class ClassDocs {
+ private String classDoc;
+ private String classInfo;
+ private ConcurrentHashMap<String, MethodDocs> mdocs = new ConcurrentHashMap<String, MethodDocs>();
+ public ClassDocs(String classDoc, String classInfo) {
+ this.classDoc = classDoc;
+ this.classInfo = classInfo;
+ }
+
+ public String getClassDoc() {
+ return classDoc;
+ }
+
+ public String getClassInfo() {
+ return classInfo;
+ }
+
+ public MethodDocs getMethodDocs(String name) {
+ return mdocs.get(name);
+ }
+
+ public void addMethodDocs(String name, MethodDocs doc) {
+ mdocs.putIfAbsent(name, doc);
+ }
+ }
+
+ private static class MethodDocs {
+ private String methodInfo;
+ private List<String> paramInfo = new LinkedList<String>();
+ private String responseInfo;
+ public MethodDocs(String methodInfo, List<String> paramInfo, String responseInfo) {
+ this.methodInfo = methodInfo;
+ this.paramInfo = paramInfo;
+ this.responseInfo = responseInfo;
+ }
+
+ public String getMethodInfo() {
+ return methodInfo;
+ }
+
+ public List<String> getParamInfo() {
+ return paramInfo;
+ }
+
+ public String getResponseInfo() {
+ return responseInfo;
+ }
+ }
+}
Propchange: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProvider.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java?rev=1553709&r1=1553708&r2=1553709&view=diff
==============================================================================
--- cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java (original)
+++ cxf/trunk/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java Fri Dec 27 18:10:38 2013
@@ -154,6 +154,7 @@ public class WadlGenerator implements Co
private String nsPrefix = DEFAULT_NS_PREFIX;
private MediaType defaultMediaType = DEFAULT_MEDIA_TYPE;
private Bus bus;
+ private DocumentationProvider docProvider;
public WadlGenerator() {
}
@@ -246,6 +247,8 @@ public class WadlGenerator implements Co
}
if (description != null) {
handleDocs(new Annotation[] {description}, sbResources, DocTarget.RESOURCE, true, isJson);
+ } else {
+ handleClassJavaDocs(cri, sbResources);
}
handleResource(sbResources, allTypes, qnameResolver, clsMap, cri, visitedResources, isJson);
sbResources.append("</resource>");
@@ -470,22 +473,24 @@ public class WadlGenerator implements Co
}
sb.append("<resource path=\"").append(getPath(path)).append("\">");
handleDocs(anns, sb, DocTarget.RESOURCE, false, isJson);
- handlePathAndMatrixClassParams(sb, classParams, isJson);
+ handlePathAndMatrixClassParams(ori, sb, classParams, isJson);
handlePathAndMatrixParams(sb, ori, isJson);
} else if (index == 0) {
- handlePathAndMatrixClassParams(sb, classParams, isJson);
+ handlePathAndMatrixClassParams(ori, sb, classParams, isJson);
handlePathAndMatrixParams(sb, ori, isJson);
}
startMethodTag(sb, ori);
- handleDocs(anns, sb, DocTarget.METHOD, true, isJson);
+ if (!handleDocs(anns, sb, DocTarget.METHOD, true, isJson)) {
+ handleOperJavaDocs(ori, sb);
+ }
if (getMethod(ori).getParameterTypes().length != 0 || classParams.size() != 0) {
sb.append("<request>");
handleDocs(anns, sb, DocTarget.REQUEST, false, isJson);
boolean isForm = isFormRequest(ori);
- doHandleClassParams(sb, classParams, isJson, ParameterType.QUERY, ParameterType.HEADER);
+ doHandleClassParams(ori, sb, classParams, isJson, ParameterType.QUERY, ParameterType.HEADER);
for (Parameter p : ori.getParameters()) {
if (isForm && p.getType() == ParameterType.REQUEST_BODY) {
continue;
@@ -574,13 +579,18 @@ public class WadlGenerator implements Co
sb.append("</resource>");
}
- protected void handlePathAndMatrixClassParams(StringBuilder sb, Map<Parameter, Object> params,
+ protected void handlePathAndMatrixClassParams(OperationResourceInfo ori,
+ StringBuilder sb,
+ Map<Parameter, Object> params,
boolean isJson) {
- doHandleClassParams(sb, params, isJson, ParameterType.PATH);
- doHandleClassParams(sb, params, isJson, ParameterType.MATRIX);
+ doHandleClassParams(ori, sb, params, isJson, ParameterType.PATH);
+ doHandleClassParams(ori, sb, params, isJson, ParameterType.MATRIX);
}
- protected void doHandleClassParams(StringBuilder sb, Map<Parameter, Object> params, boolean isJson,
+ protected void doHandleClassParams(OperationResourceInfo ori,
+ StringBuilder sb,
+ Map<Parameter, Object> params,
+ boolean isJson,
ParameterType... pType) {
Set<ParameterType> pTypes = new LinkedHashSet<ParameterType>(Arrays.asList(pType));
for (Map.Entry<Parameter, Object> entry : params.entrySet()) {
@@ -593,7 +603,7 @@ public class WadlGenerator implements Co
? ((Method)obj).getGenericParameterTypes()[0] : ((Field)obj).getGenericType();
Annotation[] ann = obj instanceof Method
? ((Method)obj).getParameterAnnotations()[0] : ((Field)obj).getAnnotations();
- doWriteParam(sb, pm, cls, type, pm.getName(), ann, isJson);
+ doWriteParam(ori, sb, pm, cls, type, pm.getName(), ann, isJson);
}
}
}
@@ -647,17 +657,28 @@ public class WadlGenerator implements Co
Method method = getMethod(ori);
Class<?> type = method.getParameterTypes()[pm.getIndex()];
if (!"".equals(pm.getName())) {
- doWriteParam(sb, pm, type, method.getGenericParameterTypes()[pm.getIndex()], pm.getName(),
- method.getParameterAnnotations()[pm.getIndex()], isJson);
+ doWriteParam(ori,
+ sb,
+ pm,
+ type,
+ method.getGenericParameterTypes()[pm.getIndex()],
+ pm.getName(),
+ method.getParameterAnnotations()[pm.getIndex()],
+ isJson);
} else {
List<Class<?>> parentBeanClasses = new LinkedList<Class<?>>();
parentBeanClasses.add(type);
- doWriteBeanParam(sb, type, pm, null, parentBeanClasses, isJson);
+ doWriteBeanParam(ori, sb, type, pm, null, parentBeanClasses, isJson);
}
}
- private void doWriteBeanParam(StringBuilder sb, Class<?> type, Parameter pm, String parentName,
- List<Class<?>> parentBeanClasses, boolean isJson) {
+ private void doWriteBeanParam(OperationResourceInfo ori,
+ StringBuilder sb,
+ Class<?> type,
+ Parameter pm,
+ String parentName,
+ List<Class<?>> parentBeanClasses,
+ boolean isJson) {
Map<Parameter, Class<?>> pms = InjectionUtils.getParametersFromBeanClass(type, pm.getType(), true);
for (Map.Entry<Parameter, Class<?>> entry : pms.entrySet()) {
String name = entry.getKey().getName();
@@ -667,16 +688,23 @@ public class WadlGenerator implements Co
Class<?> paramCls = entry.getValue();
boolean isPrimitive = InjectionUtils.isPrimitive(paramCls) || paramCls.isEnum();
if (isPrimitive || InjectionUtils.isSupportedCollectionOrArray(paramCls)) {
- doWriteParam(sb, entry.getKey(), paramCls, paramCls, name, new Annotation[] {}, isJson);
+ doWriteParam(ori, sb, entry.getKey(), paramCls, paramCls, name, new Annotation[] {}, isJson);
} else if (!parentBeanClasses.contains(paramCls)) {
parentBeanClasses.add(paramCls);
- doWriteBeanParam(sb, paramCls, entry.getKey(), name, parentBeanClasses, isJson);
+ doWriteBeanParam(ori, sb, paramCls, entry.getKey(), name, parentBeanClasses, isJson);
}
}
}
-
- protected void doWriteParam(StringBuilder sb, Parameter pm, Class<?> type, Type genericType,
- String paramName, Annotation[] anns, boolean isJson) {
+ //CHECKSTYLE:OFF
+ protected void doWriteParam(OperationResourceInfo ori,
+ StringBuilder sb,
+ Parameter pm,
+ Class<?> type,
+ Type genericType,
+ String paramName,
+ Annotation[] anns,
+ boolean isJson) {
+ //CHECKSTYLE:ON
ParameterType pType = pm.getType();
boolean isForm = isFormParameter(pm, type, anns);
if (paramName == null && isForm) {
@@ -718,7 +746,7 @@ public class WadlGenerator implements Co
setEnumOptions(sb, type);
sb.append("</param>");
} else {
- addDocsAndCloseElement(sb, anns, "param", DocTarget.PARAM, true, isJson);
+ addDocsAndCloseElement(ori, pm.getIndex(), sb, anns, "param", DocTarget.PARAM, true, isJson);
}
}
@@ -736,12 +764,26 @@ public class WadlGenerator implements Co
// ignore
}
}
-
- private void addDocsAndCloseElement(StringBuilder sb, Annotation[] anns, String elementName,
- String category, boolean allowDefault, boolean isJson) {
- if (isDocAvailable(anns)) {
+ //CHECKSTYLE:OFF
+ private void addDocsAndCloseElement(OperationResourceInfo ori,
+ int paramIndex,
+ StringBuilder sb,
+ Annotation[] anns,
+ String elementName,
+ String category,
+ boolean allowDefault,
+ boolean isJson) {
+ //CHECKSTYLE:ON
+ boolean docAnnAvailable = isDocAvailable(anns);
+ if (docAnnAvailable || (ori != null && docProvider != null)) {
sb.append(">");
- handleDocs(anns, sb, category, allowDefault, isJson);
+ if (docAnnAvailable) {
+ handleDocs(anns, sb, category, allowDefault, isJson);
+ } else if (category == DocTarget.RETURN) {
+ handleOperResponseJavaDocs(ori, sb);
+ } else if (category == DocTarget.PARAM) {
+ handleOperParamJavaDocs(ori, paramIndex, sb);
+ }
sb.append("</" + elementName + ">");
} else {
sb.append("/>");
@@ -781,9 +823,10 @@ public class WadlGenerator implements Co
boolean allowDefault = true;
String docCategory;
Annotation[] anns;
+ int inParamIndex = -1;
if (inbound) {
- int index = getRequestBodyParam(ori).getIndex();
- anns = opMethod.getParameterAnnotations()[index];
+ inParamIndex = getRequestBodyParam(ori).getIndex();
+ anns = opMethod.getParameterAnnotations()[inParamIndex];
if (!isDocAvailable(anns)) {
anns = opMethod.getAnnotations();
}
@@ -797,7 +840,7 @@ public class WadlGenerator implements Co
sb.append(">");
Parameter p = inbound ? getRequestBodyParam(ori) : new Parameter(ParameterType.REQUEST_BODY,
0, "result");
- doWriteParam(sb, p, type, type, p.getName() == null ? "request" : p.getName(), anns, isJson);
+ doWriteParam(ori, sb, p, type, type, p.getName() == null ? "request" : p.getName(), anns, isJson);
sb.append("</representation>");
} else {
boolean isCollection = InjectionUtils.isSupportedCollectionOrArray(type);
@@ -817,7 +860,8 @@ public class WadlGenerator implements Co
generateQName(sb, qnameResolver, clsMap, theActualType, isCollection,
getBodyAnnotations(ori, inbound));
}
- addDocsAndCloseElement(sb, anns, "representation", docCategory, allowDefault, isJson);
+ addDocsAndCloseElement(ori, inParamIndex, sb, anns, "representation",
+ docCategory, allowDefault, isJson);
}
}
@@ -1379,13 +1423,49 @@ public class WadlGenerator implements Co
}
}
- protected void handleDocs(Annotation[] anns, StringBuilder sb, String category, boolean allowDefault,
- boolean isJson) {
+ protected void handleClassJavaDocs(ClassResourceInfo cri, StringBuilder sb) {
+ if (docProvider != null) {
+ addProvidedDocs(sb, docProvider.getClassDoc(cri));
+ }
+ }
+
+ protected void handleOperJavaDocs(OperationResourceInfo ori, StringBuilder sb) {
+ if (docProvider != null) {
+ addProvidedDocs(sb, docProvider.getMethodDoc(ori));
+ }
+ }
+
+ protected void handleOperResponseJavaDocs(OperationResourceInfo ori, StringBuilder sb) {
+ if (docProvider != null) {
+ addProvidedDocs(sb, docProvider.getMethodResponseDoc(ori));
+ }
+ }
+
+ protected void handleOperParamJavaDocs(OperationResourceInfo ori,
+ int paramIndex,
+ StringBuilder sb) {
+ if (docProvider != null) {
+ addProvidedDocs(sb, docProvider.getMethodParameterDoc(ori, paramIndex));
+ }
+ }
+
+ private void addProvidedDocs(StringBuilder sb, String text) {
+ if (!StringUtils.isEmpty(text)) {
+ sb.append("<doc>");
+ sb.append(xmlEncodeIfNeeded(text));
+ sb.append("</doc>");
+ }
+ }
+
+ protected boolean handleDocs(Annotation[] anns,
+ StringBuilder sb,
+ String category,
+ boolean allowDefault,
+ boolean isJson) {
for (Annotation a : anns) {
if (a.annotationType() == Descriptions.class) {
Descriptions ds = (Descriptions)a;
- handleDocs(ds.value(), sb, category, allowDefault, isJson);
- return;
+ return handleDocs(ds.value(), sb, category, allowDefault, isJson);
}
if (a.annotationType() == Description.class) {
Description d = (Description)a;
@@ -1420,8 +1500,10 @@ public class WadlGenerator implements Co
}
}
sb.append("</doc>");
+ return true;
}
}
+ return false;
}
private String getNamespace() {
@@ -1792,6 +1874,14 @@ public class WadlGenerator implements Co
public void setCheckAbsolutePathSlash(boolean checkAbsolutePathSlash) {
this.checkAbsolutePathSlash = checkAbsolutePathSlash;
}
+
+ public void setJavaDocPath(String path) throws Exception {
+ docProvider = new JavaDocProvider(bus == null ? BusFactory.getDefaultBus() : bus, path);
+ }
+
+ public void setDocumentationProvider(DocumentationProvider p) {
+ docProvider = p;
+ }
private static class SchemaConverter extends DelegatingXMLStreamWriter {
private static final String SCHEMA_LOCATION = "schemaLocation";
Added: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java?rev=1553709&view=auto
==============================================================================
--- cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java (added)
+++ cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java Fri Dec 27 18:10:38 2013
@@ -0,0 +1,81 @@
+/**
+ * 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 org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.model.wadl.petstore.PetStore;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JavaDocProviderTest extends Assert {
+
+ @Test
+ public void testJava6Docs() throws Exception {
+ if (JavaDocProvider.JAVA_VERSION == JavaDocProvider.JAVA_VERSION_16) {
+ doTestJavaDocs("classpath:/javadocs/pet-store-javadoc16.jar");
+ }
+ }
+
+ @Test
+ public void testJava7Docs() throws Exception {
+ if (JavaDocProvider.JAVA_VERSION != JavaDocProvider.JAVA_VERSION_16) {
+ //doTestJavaDocs("classpath:/javadocs/pet-store-javadoc17.jar");
+ }
+ }
+
+ private void doTestJavaDocs(String path) throws Exception {
+ JavaDocProvider p = new JavaDocProvider(path);
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(PetStore.class, PetStore.class, true, true);
+ String classDoc = p.getClassDoc(cri);
+ assertEquals("The Pet Store", classDoc);
+
+ boolean getStatusTested = false;
+ boolean noDocsTested = false;
+ for (OperationResourceInfo ori : cri.getMethodDispatcher().getOperationResourceInfos()) {
+ if ("getStatus".equals(ori.getMethodToInvoke().getName())) {
+ testGetStatusJavaDocs(p, ori);
+ getStatusTested = true;
+ } else {
+ testOperWithNoJavaDocs(p, ori);
+ noDocsTested = true;
+ }
+ }
+ assertTrue(getStatusTested);
+ assertTrue(noDocsTested);
+ assertTrue(true);
+ }
+
+ private void testOperWithNoJavaDocs(JavaDocProvider p, OperationResourceInfo ori) {
+ assertTrue(StringUtils.isEmpty(p.getMethodDoc(ori)));
+ assertTrue(StringUtils.isEmpty(p.getMethodResponseDoc(ori)));
+ }
+
+ private void testGetStatusJavaDocs(JavaDocProvider p, OperationResourceInfo ori) {
+ assertEquals("Return Pet Status", p.getMethodDoc(ori));
+ assertEquals("status", p.getMethodResponseDoc(ori));
+ assertEquals("the pet id", p.getMethodParameterDoc(ori, 0));
+ assertEquals("the query", p.getMethodParameterDoc(ori, 1));
+ }
+
+}
Propchange: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/JavaDocProviderTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java?rev=1553709&view=auto
==============================================================================
--- cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java (added)
+++ cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java Fri Dec 27 18:10:38 2013
@@ -0,0 +1,100 @@
+/**
+ * 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.petstore;
+
+import javax.ws.rs.Consumes;
+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;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * The Pet Store
+ */
+@Path("/")
+public class PetStore {
+
+ public static final String CLOSED = "The Pet Store is closed";
+
+ public PetStore() {
+ }
+
+ @GET
+ @Produces("text/plain")
+ public Response getBaseStatus() throws Exception {
+
+ return Response.ok(CLOSED).build();
+ }
+
+ /**
+ * Return Pet Status
+ * @param petId the pet id
+ * @param query the query
+ * @return status
+ * @throws Exception
+ */
+ @GET
+ @Path("/petstore/pets/{petId}/")
+ @Produces("text/xml")
+ public Response getStatus(@PathParam("petId") String petId,
+ @QueryParam("query") String query) throws Exception {
+
+ return Response.ok(CLOSED).build();
+ }
+
+
+ @GET
+ @Path("/petstore/jaxb/status/")
+ @Produces("text/xml")
+ public PetStoreStatus getJaxbStatus() {
+
+ return new PetStoreStatus();
+ }
+
+
+ @GET
+ @POST
+ @Path("/petstore/pets/")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces("text/xml")
+ public Response updateStatus(MultivaluedMap<String, String> params) throws Exception {
+ return Response.ok(params.getFirst("status")).build();
+ }
+
+ @XmlType(name = "status", namespace = "http://pets")
+ public static class PetStoreStatus {
+ private String status = PetStore.CLOSED;
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ }
+}
Propchange: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/petstore/PetStore.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc16.jar
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc16.jar?rev=1553709&view=auto
==============================================================================
Binary file - no diff available.
Propchange: cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc16.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc17.jar
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc17.jar?rev=1553709&view=auto
==============================================================================
Binary file - no diff available.
Propchange: cxf/trunk/rt/rs/description/src/test/resources/javadocs/pet-store-javadoc17.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream