Browse Source

[MRM-1683] Automatic generation of REST Api documentation.

display doc in the webapp !

git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1394516 13f79535-47bb-0310-9956-ffa450edef68
tags/archiva-1.4-M4
Olivier Lamy 11 years ago
parent
commit
258f098ae6

+ 1
- 1
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/pom.xml View File

@@ -171,7 +171,7 @@
</execution>
</executions>
<configuration>
<docsDir>${project.build.outputDirectory}/docs</docsDir>
<docsDir>${project.build.outputDirectory}/rest-docs-archiva-rest-api</docsDir>
<configFile>src/enunciate/enunciate.xml</configFile>
<compileDebug>${enunciate.debug}</compileDebug>
</configuration>

+ 6
- 0
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml View File

@@ -97,6 +97,12 @@
<artifactId>archiva-maven2-model</artifactId>
</dependency>

<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.1</version>
</dependency>

<dependency>
<groupId>org.apache.archiva.redback</groupId>
<artifactId>redback-authorization-api</artifactId>

+ 91
- 0
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/docs/RestDocsServlet.java View File

@@ -0,0 +1,91 @@
package org.apache.archiva.rest.docs;
/*
* 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.
*/

import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

/**
* @author Olivier Lamy
* @since 1.4-M4
*/
public class RestDocsServlet
extends HttpServlet
{
private Logger logger = LoggerFactory.getLogger( getClass() );

@Override
protected void doGet( HttpServletRequest req, HttpServletResponse resp )
throws ServletException, IOException
{

logger.debug( "docs request to path: {}", req.getPathInfo() );

String path = StringUtils.removeStart( req.getPathInfo(), "/" );
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( path );

String startPath = StringUtils.substringBefore( path, "/" );

// replace all links !!
Document document = Jsoup.parse( is, "UTF-8", "" );

Element body = document.body().child( 0 );

Elements links = body.select( "a[href]" );

for ( Iterator<Element> elementIterator = links.iterator(); elementIterator.hasNext(); )
{
Element link = elementIterator.next();
//link.attr( "onclick", "loadRestDocs('" + startPath + "\',\'"+ "rest-docs/" + startPath + "/" + link.attr( "href" ) + "\');" );
link.attr( "href", "#" + startPath + "/" + link.attr( "href" ) );

}

Elements codes = body.select( "code" );

for ( Iterator<Element> elementIterator = codes.iterator(); elementIterator.hasNext(); )
{
Element code = elementIterator.next();
code.attr( "class", code.attr( "class" ) + " nice-code" );
}

//res.appendChild( body.child( 1 ) );

Document res = new Document( "" );
res.appendChild( body.select( "div[id=main]" ).first() );

resp.getOutputStream().write( res.outerHtml().getBytes() );

//IOUtils.copy( is, resp.getOutputStream() );
//super.doGet( req, resp );
}
}

+ 10
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/WEB-INF/web.xml View File

@@ -79,6 +79,11 @@
<load-on-startup>1</load-on-startup>
</servlet>

<servlet>
<servlet-name>RestDocumentation</servlet-name>
<servlet-class>org.apache.archiva.rest.docs.RestDocsServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>


<servlet>
@@ -92,6 +97,11 @@
<servlet-name>RssFeedServlet</servlet-name>
<url-pattern>/feeds/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RestDocumentation</servlet-name>
<url-pattern>/rest-docs/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>RepositoryServlet</servlet-name>

+ 15
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/css/archiva.css View File

@@ -160,4 +160,19 @@ footer {

.cursor-hand:hover {
cursor: pointer;
}


code {
background: none repeat scroll 0 0 #EEEEEE;
border: 1px solid #DDDDDD;
color: #555555;
display: block;
font: 1.1em "Lucida Sans Unicode",serif;
margin-bottom: 12px;
max-height: 300px;
overflow: auto;
padding: 8px 10px;
white-space: pre;
vertical-align: baseline;
}

+ 2
- 2
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/index.html View File

@@ -21,7 +21,7 @@

<html>
<head>
<link rel="stylesheet" href="css/prettify.css"/>
<link rel="stylesheet" href="css/jquery.fileupload-ui.css"/>
<link rel="stylesheet" href="css/jqueryFileTree.css"/>
<link rel="stylesheet" href="css/chosen-0.9.8.css"/>
@@ -29,7 +29,7 @@
<link rel="stylesheet" href="css/bootstrap.2.1.1.css">
<link rel="stylesheet" href="css/archiva.css">
<link rel="shortcut icon" href="favicon.ico"/>
<link rel="stylesheet" href="css/prettify.css"/>

<script type="text/javascript" src="js/jquery-1.8.1.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.23.custom.min.js"></script>

+ 1
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/archiva/archiva.js View File

@@ -94,6 +94,7 @@ $.ajax({
"archiva.artifacts-management": "archiva/artifacts-management",
"archiva.search": "archiva/search",
"archiva.proxy-connectors-rules": "archiva/proxy-connectors-rules",
"archiva.docs": "archiva/docs",
"archiva.main": "archiva/main"
}
});

+ 74
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/archiva/docs.js View File

@@ -0,0 +1,74 @@
/*
* 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.
*/
define("archiva.docs",["jquery","i18n","jquery.tmpl","bootstrap"], function() {

displayRestDocs=function(){
$.log("displayRestDocs");
screenChange();
$("#main-content" ).html($("#rest_docs").tmpl());
}

goToArchivaRestDoc=function(target){
$("#main-content" ).html(mediumSpinnerImg());
$.ajax({
url:"rest-docs/rest-docs-archiva-rest-api/"+target,
type:"get",
dataType: "html",
success: function(data){
$("#main-content" ).html($("#rest_docs").tmpl());
$("#main-content" ).find("#rest_docs_content" ).html(data);
prettyPrint();
}
});
}

displayArchivaRestDocs=function(){
$.log("displayArchivaRestDocs");
$("#main-content" ).html(mediumSpinnerImg());
$.ajax({
url:"rest-docs/rest-docs-archiva-rest-api/index.html",
type:"get",
dataType: "html",
success: function(data){
$("#main-content" ).html($("#rest_docs").tmpl());
$("#main-content" ).find("#rest_docs_content" ).html(data);
}
});
}

loadRestDocs=function(docType, fullPath){
$.log("loadRestDocs:"+docType+","+fullPath);
//if (docType=='rest-docs-archiva-rest-api'){
$.ajax({
url:fullPath,
type:"get",
dataType: "html",
success: function(data){
$("#main-content" ).find("#rest_docs_content" ).html(data);
prettyPrint();
}
});
//}
}

displayUsersDocs=function(){
$.log("displayUsersDocs");
}

});

+ 4
- 2
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/archiva/main-tmpl.js View File

@@ -21,15 +21,17 @@ require(['jquery',"jquery.tmpl",'i18n',"utils","text!templates/archiva/menu.html
"text!templates/archiva/modal.html",
"text!templates/archiva/repositories.html",
"text!templates/archiva/search.html",
"text!templates/archiva/general-admin.html"],
"text!templates/archiva/general-admin.html",
"text!templates/archiva/docs.html"],
function(jquery,jqueryTmpl,i18n,utils,menu,generics,modal,repositories,
search,general_admin) {
search,general_admin,docs) {
loadArchivaTemplate=function(){
var htmlFragment=$("#html-fragments");
// template loading
htmlFragment.append(menu);
htmlFragment.append(generics);
$.tmpl( modal ).appendTo(htmlFragment);
$.tmpl( docs ).appendTo(htmlFragment);
htmlFragment.append(repositories);
htmlFragment.append(search);
htmlFragment.append(general_admin);

+ 15
- 2
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/archiva/main.js View File

@@ -20,7 +20,7 @@ define("archiva.main",["jquery","jquery.ui","sammy","jquery.tmpl",'i18n',"jquery
"jquery.validate","jquery.json","knockout","redback.templates","archiva.templates",
"redback.roles","redback","archiva.general-admin","archiva.repositories",
"archiva.network-proxies","archiva.proxy-connectors","archiva.repository-groups","archiva.artifacts-management",
"archiva.proxy-connectors-rules"],
"archiva.proxy-connectors-rules","archiva.docs"],
function(jquery,ui,sammy,tmpl) {

/**
@@ -195,6 +195,13 @@ function(jquery,ui,sammy,tmpl) {
{ text : $.i18n.prop('menu.users.manage') , id: "menu-users-list-a", href: "#users" , redback: "{permissions: ['archiva-manage-users']}", func: function(){displayUsersGrid()}},
{ text : $.i18n.prop('menu.users.roles') , id: "menu-roles-list-a", href: "#roles" , redback: "{permissions: ['archiva-manage-users']}", func: function(){displayRolesGrid()}}
];

this.docsMenuItems = [
{ text : $.i18n.prop('menu.docs') , id: null},
{ text : $.i18n.prop('menu.docs.rest') , id: "menu-docs-rest-list-a", href: "#docs-rest", func: function(){displayRestDocs()}},
{ text : $.i18n.prop('menu.docs.users') , id: "menu-docs-users-list-a", href: "#docs-users" , func: function(){displayUsersDocs()}}
];

this.activeMenuId = ko.observable();
window.sammyArchivaApplication = Sammy(function () {
@@ -616,7 +623,7 @@ function(jquery,ui,sammy,tmpl) {
var folder = this.params.folder;
self.activeMenuId(folder);
var baseItems = self.artifactMenuItems?self.artifactMenuItems:[];
ko.utils.arrayFirst(baseItems.concat(self.usersMenuItems, self.administrationMenuItems), function(p) {
ko.utils.arrayFirst(baseItems.concat(self.usersMenuItems, self.administrationMenuItems,self.docsMenuItems), function(p) {
if ( p.href == "#"+self.activeMenuId()) {
screenChange();
p.func();
@@ -624,6 +631,12 @@ function(jquery,ui,sammy,tmpl) {
});
});

this.get("#rest-docs-archiva-rest-api/:target",function(){
var target=this.params.target;
$.log("archiva-rest-docs, target:"+target);
goToArchivaRestDoc(target);
});

});
};


+ 37
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/templates/archiva/docs.html View File

@@ -0,0 +1,37 @@
<!--
~ 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.
-->

<script id="rest_docs" type="text/html">
<div>
<div class="page-header">
<div><b>${$.i18n.prop('docs.rest.header')}</b></div>
</div>
<div id="docs_rest_choice">
<ul>
<li><a onclick="displayArchivaRestDocs();">Archiva Rest Api Docs</a></li>
</ul>
</div>
</div>
<div id="rest_docs_content">
</div>
</script>

<script id="users_docs" type="text/html">
rest docs
</script>

+ 11
- 0
archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/templates/archiva/menu.html View File

@@ -52,6 +52,17 @@
<!-- /ko -->
</ul>

<ul class="nav nav-list" data-bind="foreach: docsMenuItems">
<!-- ko ifnot: id -->
<li class="nav-header archiva-nav-header" data-bind="text: text"></li>
<!-- /ko -->
<!-- ko if: id -->
<li data-bind='redbackP: $data.redback, css: { active: $data.href == "#"+$root.activeMenuId() }'>
<a data-bind="text: text, attr: { id: id, href: href}"></a>
</li>
<!-- /ko -->
</ul>

</div>
</script>


Loading…
Cancel
Save