Example app for experimenting with Swagger annotations.
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/6ea66856 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/6ea66856 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/6ea66856 Branch: refs/heads/two-dot-o-dev Commit: 6ea668560f1bcbfb3ab55e4c2a3b61e6b67f5adb Parents: 54f61dc Author: Dave Johnson <[email protected]> Authored: Wed Sep 16 16:07:42 2015 -0400 Committer: Dave Johnson <[email protected]> Committed: Wed Sep 16 16:07:42 2015 -0400 ---------------------------------------------------------------------- docs/jersey2skeleton/README.md | 9 + docs/jersey2skeleton/pom.xml | 387 +++++++++++++++++++ .../usergrid/testapp/AbstractResource.java | 51 +++ .../apache/usergrid/testapp/ApiResponse.java | 52 +++ .../org/apache/usergrid/testapp/Entity.java | 55 +++ .../usergrid/testapp/ManagementResource.java | 56 +++ .../usergrid/testapp/OrganizationResource.java | 64 +++ .../usergrid/testapp/OrganizationsResource.java | 76 ++++ .../apache/usergrid/testapp/StatusResource.java | 34 ++ .../java/org/apache/usergrid/testapp/User.java | 28 ++ .../src/main/resources/applicationContext.xml | 28 ++ .../main/resources/jersey2skeleton-context.xml | 28 ++ .../src/main/webapp/WEB-INF/web.xml | 95 +++++ .../usergrid/testapp/AvailablePortFinder.java | 208 ++++++++++ .../usergrid/testapp/OrganizationTest.java | 127 ++++++ .../org/apache/usergrid/testapp/TomcatMain.java | 57 +++ .../apache/usergrid/testapp/TomcatRuntime.java | 185 +++++++++ .../src/test/resources/log4j.properties | 31 ++ .../src/test/resources/logging.properties | 26 ++ docs/jersey2skeleton/templates/markdown.hbs | 108 ++++++ docs/jersey2skeleton/templates/operation.hbs | 73 ++++ docs/jersey2skeleton/templates/security.hbs | 88 +++++ .../templates/strapdown.html.hbs | 10 + 23 files changed, 1876 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/README.md ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/README.md b/docs/jersey2skeleton/README.md new file mode 100644 index 0000000..f0115f1 --- /dev/null +++ b/docs/jersey2skeleton/README.md @@ -0,0 +1,9 @@ +# jersey2skeleton + +This is a minimal example project designed to mimic how Usergrid uses Jersey 2. + +Goal is to determine correct way to use Jersey and Swagger annotations to automatically +generate Swagger from Usergrid's Java code. + +Current status: cannot determine correct combination of annotations to get the correct +Swagger generated for the /management and /management/organizations end-points. http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/pom.xml ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/pom.xml b/docs/jersey2skeleton/pom.xml new file mode 100644 index 0000000..dfeede5 --- /dev/null +++ b/docs/jersey2skeleton/pom.xml @@ -0,0 +1,387 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <!-- based on Usergrid's REST POM --> + + <!-- Jersey 2 project with Spring wiring and Jackson for JSON processing --> + + <groupId>org.apache.usergrid</groupId> + <artifactId>jersey2skeleton</artifactId> + <version>1.0-SNAPSHOT</version> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <finalName>ROOT</finalName> + + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + <includes> + <include>**/*.xml</include> + <include>**/*.json</include> + </includes> + </resource> + </resources> + + <testResources> + <testResource> + <directory>src/test/resources</directory> + <filtering>true</filtering> + <includes> + <include>**/*</include> + </includes> + </testResource> + </testResources> + + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.3</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + <optimize>true</optimize> + <showDeprecation>true</showDeprecation> + <debug>true</debug> + <encoding>UTF-8</encoding> + <showWarnings>true</showWarnings> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.18.1</version> + <configuration> + <systemPropertyVariables> + <storage-config>${basedir}/src/test/conf</storage-config> + <target.directory>${project.build.directory}</target.directory> + </systemPropertyVariables> + <parallel>methods</parallel> + <forkCount>1</forkCount> + <threadCount>1</threadCount> + <useSystemClassLoader>false</useSystemClassLoader> + <reuseForks>true</reuseForks> + <argLine>-Dwebapp.directory=${basedir}/src/main/webapp + -Djava.util.logging.config.file=${basedir}/src/test/resources/logging.properties + </argLine> + <includes> + <include>**/*Test.java</include> + </includes> + </configuration> + + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit4</artifactId> + <version>2.18.1</version> + </dependency> + </dependencies> + </plugin> + + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>2.6</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.6</version> + <configuration> + <finalName>${project.artifactId}-${project.version}</finalName> + </configuration> + <executions> + <execution> + <id>make-a-jar</id> + <phase>package</phase> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <classifier>classes</classifier> + </configuration> + </execution> + <execution> + <id>jsp-jar-execution</id> + <phase>package</phase> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <classifier>compiled-jsp</classifier> + <classesDirectory>${project.build.directory}/jsp-source</classesDirectory> + </configuration> + </execution> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>com.github.kongchen</groupId> + <artifactId>swagger-maven-plugin</artifactId> + <version>3.1.0</version> + <configuration> + <apiSources> + <apiSource> + <springmvc>false</springmvc> + <locations>org.apache.usergrid.testapp</locations> + <info> + <title>Test Docs</title> + <version>v1</version> + <description>Testing the Swagger Maven plugin</description> + <license> + <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> + <name>Apache 2.0</name> + </license> + </info> + <templatePath>${basedir}/templates/strapdown.html.hbs</templatePath> + <outputPath>${basedir}/target/swagger-docs/document.html</outputPath> + <swaggerDirectory>${basedir}/target/swagger-docs</swaggerDirectory> + </apiSource> + </apiSources> + </configuration> + <executions> + <execution> + <phase>compile</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + + </build> + + <dependencies> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + <version>3.1.0</version> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>jstl</artifactId> + <version>1.2</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.connectors</groupId> + <artifactId>jersey-apache-connector</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.ext</groupId> + <artifactId>jersey-mvc-jsp</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-multipart</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.ext</groupId> + <artifactId>jersey-spring3</artifactId> + <version>2.21</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.jaxrs</groupId> + <artifactId>jackson-jaxrs-json-provider</artifactId> + <version>2.4.4</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + <version>3.2.3.RELEASE</version> + </dependency> + + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>1.5.0</version> + </dependency> + + <!-- need Spring 4 to take full advantage of Java 8 features, but Jersey 2 doesn't support it? + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>4.2.0.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <version>4.2.0.RELEASE</version> + </dependency> + --> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.5.3</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>2.5.0</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.5.3</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.12</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.7.12</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + <version>1.7.12</version> + </dependency> + + + <!-- scope: test --> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.test-framework</groupId> + <artifactId>jersey-test-framework-core</artifactId> + <version>2.21</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.test-framework.providers</groupId> + <artifactId>jersey-test-framework-provider-external</artifactId> + <version>2.21</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.6</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>17.0</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-core</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jasper</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jasper-el</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-servlet-api</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jsp-api</artifactId> + <scope>test</scope> + <version>7.0.64</version> + </dependency> + + </dependencies> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/AbstractResource.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/AbstractResource.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/AbstractResource.java new file mode 100644 index 0000000..cca3629 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/AbstractResource.java @@ -0,0 +1,51 @@ +/* + * 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.usergrid.testapp; + +import javax.ws.rs.container.ResourceContext; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.UriInfo; +import javax.xml.ws.spi.http.HttpContext; + + +public class AbstractResource { + + @Context + protected UriInfo uriInfo; + + @Context + protected HttpContext hc; + + @Context + protected ResourceContext resourceContext; + + private AbstractResource parent; + + public <T extends AbstractResource> T getSubResource(Class<T> t) { + T subResource = resourceContext.getResource(t); + subResource.setParent(this); + return subResource; + } + + public void setParent(AbstractResource parent) { + this.parent = parent; + } + + public AbstractResource getParent() { + return parent; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ApiResponse.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ApiResponse.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ApiResponse.java new file mode 100644 index 0000000..042bd53 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ApiResponse.java @@ -0,0 +1,52 @@ +/* + * 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.usergrid.testapp; + +import io.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + + +@XmlRootElement(name = "ApiResponse") +public class ApiResponse { + private String content; + private List<Entity> entities; + + public ApiResponse() { + } + + @XmlElement(name = "content") + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @XmlElement(name = "entities") + @ApiModelProperty(value = "Entities contained in response.") + public List<Entity> getEntities() { + return entities; + } + + public void setEntities(List<Entity> entities) { + this.entities = entities; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/Entity.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/Entity.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/Entity.java new file mode 100644 index 0000000..f765320 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/Entity.java @@ -0,0 +1,55 @@ +/* + * 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.usergrid.testapp; + +import javax.xml.bind.annotation.XmlElement; +import java.util.UUID; + + +//@XmlRootElement(name="Entity") +public class Entity { + private UUID id; + private String type; + private String name; + + //@XmlElement(name="id") + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + //@XmlElement(name="type") + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + //@XmlElement(name="name") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ManagementResource.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ManagementResource.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ManagementResource.java new file mode 100644 index 0000000..b857d55 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/ManagementResource.java @@ -0,0 +1,56 @@ +/* + * 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.usergrid.testapp; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + + +@Api(value="/management", description = "Access to management information.") +@Path("/management") +@Component +@Scope( "singleton" ) +@Produces({ + MediaType.APPLICATION_JSON, + "application/javascript", + "application/x-javascript", + "text/ecmascript", + "application/ecmascript", + "text/jscript" +}) +public class ManagementResource extends AbstractResource { + + @GET + @Path("status") + @ApiOperation(value = "Status of management service") + public String getStatus() { + return "OK"; + } + + @Path( "organizations" ) + public OrganizationsResource getOrganizations() { + return getSubResource( OrganizationsResource.class ); + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationResource.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationResource.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationResource.java new file mode 100644 index 0000000..de58f2a --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationResource.java @@ -0,0 +1,64 @@ +/* + * 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.usergrid.testapp; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import java.util.Collections; +import java.util.UUID; + + +@Component +@Scope( "singleton" ) +@Produces({ + MediaType.APPLICATION_JSON, + "application/javascript", + "application/x-javascript", + "text/ecmascript", + "application/ecmascript", + "text/jscript" +}) +public class OrganizationResource extends AbstractResource { + private String id; + + public OrganizationResource() { + } + + public void init( String id ) { + this.id = id; + } + + @GET + public ApiResponse getOrganization() { + Entity org = new Entity(); + org.setName( "org:" + id ); + org.setId( UUID.randomUUID() ); + org.setType( "organization" ); + ApiResponse response = new ApiResponse(); + response.setContent( "organization:" + id ); + response.setEntities( Collections.singletonList( org )); + return response; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationsResource.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationsResource.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationsResource.java new file mode 100644 index 0000000..9c2d5bd --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/OrganizationsResource.java @@ -0,0 +1,76 @@ +/* + * 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.usergrid.testapp; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import jersey.repackaged.com.google.common.collect.Lists; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import java.util.UUID; + + +@Api(value="/management/organizations", description = "Access to organizations.", tags="management") +@Path("/management/organizations") +@Component +@Scope("singleton") +@Produces({ + MediaType.APPLICATION_JSON, + "application/javascript", + "application/x-javascript", + "text/ecmascript", + "application/ecmascript", + "text/jscript" +}) +public class OrganizationsResource extends AbstractResource { + + @Path("/{id}") + @ApiOperation(value = "Get organization by id.", response=ApiResponse.class) + public OrganizationResource getOrganizationById(@PathParam("id") String id) { + OrganizationResource or = getSubResource( OrganizationResource.class ); + or.init(id); + return or; + } + + @GET + @ApiOperation(value = "Get organizations.", response=ApiResponse.class) + public ApiResponse getOrganizations() { + + Entity org1 = new Entity(); + org1.setId( UUID.randomUUID() ); + org1.setName( "org1" ); + org1.setType( "organization" ); + + Entity org2 = new Entity(); + org2.setId( UUID.randomUUID() ); + org2.setName( "org2" ); + org2.setType( "organization" ); + + ApiResponse response = new ApiResponse(); + response.setContent( "All Organizations" ); + response.setEntities( Lists.newArrayList( org1, org2 ) ); + + return response; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/StatusResource.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/StatusResource.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/StatusResource.java new file mode 100644 index 0000000..f537a01 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/StatusResource.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.usergrid.testapp; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Api(value="/status", description = "Status end-point.") +@Path("status") +public class StatusResource { + + @GET + @ApiOperation(value = "Status of webapp.") + public String getStatus() { + return "good"; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/User.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/User.java b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/User.java new file mode 100644 index 0000000..5e24f51 --- /dev/null +++ b/docs/jersey2skeleton/src/main/java/org/apache/usergrid/testapp/User.java @@ -0,0 +1,28 @@ +/* + * 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.usergrid.testapp; + +import javax.xml.bind.annotation.XmlRootElement; + + +//@XmlRootElement(name="User") +public class User extends Entity { + public User() { + super(); + setType("user"); + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/resources/applicationContext.xml ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/resources/applicationContext.xml b/docs/jersey2skeleton/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..2b877b1 --- /dev/null +++ b/docs/jersey2skeleton/src/main/resources/applicationContext.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" + xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> + + <context:component-scan base-package="org.apache.usergrid.testapp" /> + +</beans> http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/resources/jersey2skeleton-context.xml ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/resources/jersey2skeleton-context.xml b/docs/jersey2skeleton/src/main/resources/jersey2skeleton-context.xml new file mode 100644 index 0000000..2b877b1 --- /dev/null +++ b/docs/jersey2skeleton/src/main/resources/jersey2skeleton-context.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" + xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> + + <context:component-scan base-package="org.apache.usergrid.testapp" /> + +</beans> http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/main/webapp/WEB-INF/web.xml b/docs/jersey2skeleton/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..d005b3a --- /dev/null +++ b/docs/jersey2skeleton/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> + + <display-name>Jersey Skeleton app</display-name> + + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>classpath:/jersey2skeleton-context.xml</param-value> + </context-param> + + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + + <listener> + <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> + </listener> + + <filter> + <filter-name>jersey2skeleton</filter-name> + <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class> + + <init-param> + <param-name>jersey.config.servlet.filter.contextPath</param-name> + <param-value>/</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.provider.packages</param-name> + <param-value>org.apache.usergrid.testapp</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.provider.scanning.recursive</param-name> + <param-value>true</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.provider.classnames</param-name> + <param-value> + org.apache.usergrid.testapp.SecuredResourceFilterFactory, + org.glassfish.jersey.server.mvc.jsp.JspMvcFeature, + org.glassfish.jersey.media.multipart.MultiPartFeature + + <!-- TODO: someday use @PermitAll, @DenyAll, @RolesAllowed --> + <!-- , org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature --> + </param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name> + <param-value>/WEB-INF/jsp</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.wadl.disableWadl</param-name> + <param-value>true</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.servlet.filter.staticContentRegex</param-name> + <param-value>/(((images|css|js|jsp|WEB-INF/jsp)/.*)|(favicon\.ico))</param-value> + </init-param> + + <init-param> + <param-name>jersey.config.server.mediaTypeMappings</param-name> + <param-value>json:application/json,js:application/javascript</param-value> + </init-param> + + </filter> + + <filter-mapping> + <filter-name>jersey2skeleton</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + +</web-app> http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/AvailablePortFinder.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/AvailablePortFinder.java b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/AvailablePortFinder.java new file mode 100644 index 0000000..0a33688 --- /dev/null +++ b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/AvailablePortFinder.java @@ -0,0 +1,208 @@ +/* + * 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.usergrid.testapp; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.TreeSet; + + +/** + * Finds currently available server ports. + * + * @author <a href="http://mina.apache.org">Apache MINA Project</a> + * @see <a href="http://www.iana.org/assignments/port-numbers">IANA.org</a> + */ +public class AvailablePortFinder { + + private static final Logger LOG = LoggerFactory.getLogger( AvailablePortFinder.class ); + /** The minimum number of server port number. */ + public static final int MIN_PORT_NUMBER = 1; + + /** The maximum number of server port number. */ + public static final int MAX_PORT_NUMBER = 49151; + + + /** Creates a new instance. */ + private AvailablePortFinder() { + // Do nothing + } + + + /** + * Returns the {@link Set} of currently available port numbers ({@link Integer}). This method is identical to + * <code>getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER)</code>. + * <p/> + * WARNING: this can take a very long time. + */ + public static Set<Integer> getAvailablePorts() { + return getAvailablePorts( MIN_PORT_NUMBER, MAX_PORT_NUMBER ); + } + + + /** + * Gets an available port, selected by the system. + * + * @throws NoSuchElementException if there are no ports available + */ + public static int getNextAvailable() { + ServerSocket serverSocket = null; + + try { + // Here, we simply return an available port found by the system + serverSocket = new ServerSocket( 0 ); + int port = serverSocket.getLocalPort(); + + // Don't forget to close the socket... + serverSocket.close(); + + return port; + } + catch ( IOException ioe ) { + throw new NoSuchElementException( ioe.getMessage() ); + } + } + + + /** + * Gets the next available port starting at a port. + * + * @param fromPort the port to scan for availability + * + * @throws NoSuchElementException if there are no ports available + */ + public static int getNextAvailable( int fromPort ) { + if ( fromPort < MIN_PORT_NUMBER || fromPort > MAX_PORT_NUMBER ) { + throw new IllegalArgumentException( "Invalid start port: " + fromPort ); + } + + for ( int i = fromPort; i <= MAX_PORT_NUMBER; i++ ) { + if ( available( i ) ) { + return i; + } + } + + throw new NoSuchElementException( "Could not find an available port " + "above " + fromPort ); + } + + + /** + * Checks to see if a specific port is available. + * + * @param port the port to check for availability + */ + public static boolean available( int port ) { + if ( port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER ) { + throw new IllegalArgumentException( "Invalid start port: " + port ); + } + + ServerSocket ss = null; + DatagramSocket ds = null; + + try { + // Jackson: It seems like the code below intends to + // setReuseAddress(true), but that needs to be set before the bind. + // The constructor for the ServerSocket(int) will bind, so not sure + // how it would have been working as intended previously. + + // Changing ServerSocket constructor to use default constructor, + // this would be unbound, then set the socket reuse, and + // call the bind separately + + //ss = new ServerSocket( port ); + ss = new ServerSocket(); + ss.setReuseAddress( true ); + ss.bind(new InetSocketAddress((InetAddress) null, port), 0); + + // Unlike ServerSocket, the default constructor of DatagramSocket + // will bound. To create an unbound DatagramSocket, use null address + //ds = new DatagramSocket( port ); + ds = new DatagramSocket(null); + ds.setReuseAddress( true ); + ds.bind(new InetSocketAddress((InetAddress) null, port)); + LOG.info("port {} available", port); + return true; + } + catch ( IOException e ) { + // Do nothing + } + finally { + if ( ds != null ) { + ds.close(); + } + + if ( ss != null ) { + try { + ss.close(); + } + catch ( IOException e ) { + /* should not be thrown */ + } + } + } + LOG.info("port {} unavailable", port); + return false; + } + + + /** + * Returns the {@link Set} of currently avaliable port numbers ({@link Integer}) between the specified port range. + * + * @throws IllegalArgumentException if port range is not between {@link #MIN_PORT_NUMBER} and {@link + * #MAX_PORT_NUMBER} or <code>fromPort</code> if greater than <code>toPort</code>. + */ + public static Set<Integer> getAvailablePorts( int fromPort, int toPort ) { + if ( fromPort < MIN_PORT_NUMBER || toPort > MAX_PORT_NUMBER || fromPort > toPort ) { + throw new IllegalArgumentException( "Invalid port range: " + fromPort + " ~ " + toPort ); + } + + Set<Integer> result = new TreeSet<Integer>(); + + for ( int i = fromPort; i <= toPort; i++ ) { + ServerSocket s = null; + + try { + s = new ServerSocket( i ); + result.add(i); + } + catch ( IOException e ) { + // Do nothing + } + finally { + if ( s != null ) { + try { + s.close(); + } + catch ( IOException e ) { + /* should not be thrown */ + } + } + } + } + + return result; + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/OrganizationTest.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/OrganizationTest.java b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/OrganizationTest.java new file mode 100644 index 0000000..faaaf95 --- /dev/null +++ b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/OrganizationTest.java @@ -0,0 +1,127 @@ +/* + * 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.usergrid.testapp; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.test.DeploymentContext; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.spi.TestContainer; +import org.glassfish.jersey.test.spi.TestContainerFactory; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.Application; +import java.net.URI; +import java.net.URISyntaxException; + +import static junit.framework.Assert.assertEquals; + + +public class OrganizationTest extends JerseyTest { + private static final Logger logger = LoggerFactory.getLogger( TomcatMain.class ); + + // TomcatRuntime is copied from Usergrid + public static TomcatRuntime tomcatRuntime = TomcatRuntime.getInstance(); + + private static ClientConfig clientConfig = new ClientConfig(); + static { + clientConfig.register( new JacksonFeature() ); + } + + @Override + protected Application configure() { + return new Application(); + } + + @Test + public void testGetManagementStatus() { + + String path = "/management/status"; + logger.info( "***** Testing against URI: {}{}", getBaseUri(), path ); + String responseString = getClient().target( getBaseUri() + path ).request().get( String.class ); + + assertEquals( "OK", responseString ); + } + + @Test + public void testGetOrganizations() { + + String path = "/management/organizations"; + logger.info( "***** Testing against URI: {}{}", getBaseUri(), path ); + ApiResponse response = getClient().target( getBaseUri() + path ).request().get( ApiResponse.class ); + + assertEquals( "All Organizations", response.getContent() ); + assertEquals( 2, response.getEntities().size() ); + } + + @Test + public void testGetOrganization() { + + String path = "/management/organizations/1"; + logger.info( "***** Testing against URI: {}{}", getBaseUri(), path ); + ApiResponse response = getClient().target( getBaseUri() + path ).request().get( ApiResponse.class ); + + assertEquals( "organization:1", response.getContent() ); + assertEquals( 1, response.getEntities().size() ); + } + + // Returns a do-nothing test container, we're using TomcatRuntime instead. + @Override + protected TestContainerFactory getTestContainerFactory() { + final URI baseURI = getBaseUri(); + + return new TestContainerFactory() { + @Override + public TestContainer create(URI uri, DeploymentContext deploymentContext) { + return new TestContainer() { + + @Override + public ClientConfig getClientConfig() { + return clientConfig; + } + + @Override + public URI getBaseUri() { + return baseURI; + } + + @Override + public void start() { + // noop + } + + @Override + public void stop() { + // noop + } + }; + } + }; + + } + + protected URI getBaseUri() { + try { + return new URI("http://localhost:" + tomcatRuntime.getPort()); + } catch (URISyntaxException e) { + throw new RuntimeException("Error determining baseURI", e); + } + } + +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatMain.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatMain.java b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatMain.java new file mode 100644 index 0000000..c0e41ba --- /dev/null +++ b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatMain.java @@ -0,0 +1,57 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed 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.usergrid.testapp; + +import com.google.common.io.Files; +import org.apache.catalina.startup.Tomcat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + + +/** + * Simple wrapper for starting "embedded" Tomcat as it's own process, for testing. + */ +public class TomcatMain { + + private static final Logger log = LoggerFactory.getLogger( TomcatMain.class ); + + public static void main(String[] args) throws Exception { + + String webappsPath = args[0]; + int port = Integer.parseInt( args[1] ); + + File dataDir = Files.createTempDir(); + dataDir.deleteOnExit(); + + Tomcat tomcat = new Tomcat(); + tomcat.setBaseDir(dataDir.getAbsolutePath()); + tomcat.setPort(port); + tomcat.getConnector().setAttribute("maxThreads", "1000"); + tomcat.addWebapp("/", new File(webappsPath).getAbsolutePath()); + + log.info("-----------------------------------------------------------------"); + log.info("Starting Tomcat port {} dir {}", port, webappsPath); + log.info("-----------------------------------------------------------------"); + tomcat.start(); + + while ( true ) { + Thread.sleep(1000); + } + } + +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatRuntime.java ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatRuntime.java b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatRuntime.java new file mode 100644 index 0000000..16bd77f --- /dev/null +++ b/docs/jersey2skeleton/src/test/java/org/apache/usergrid/testapp/TomcatRuntime.java @@ -0,0 +1,185 @@ +/* + * 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.usergrid.testapp; + + +import com.google.common.io.Files; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.startup.Tomcat; +import org.apache.commons.lang.math.RandomUtils; +import org.junit.rules.ExternalResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import java.io.File; + + +/** + * Start and stop embedded Tomcat. + */ +public class TomcatRuntime extends ExternalResource { + private static final Logger log = LoggerFactory.getLogger( TomcatRuntime.class ); + + + private static final String WEBAPP_PATH = System.getProperty("webapp.directory"); + + private static TomcatRuntime instance; + + public final TomcatInstance tomcat; + + + private TomcatRuntime() { + + tomcat = new TomcatInstance( WEBAPP_PATH ); + tomcat.startTomcat(); + + //stop on JVM shutdown + Runtime.getRuntime().addShutdownHook( new Thread() { + @Override + public void run() { + tomcat.stopTomcat(); + } + } ); + } + + + /** + * Get the instance of the tomcat runtime and starts the tomcat singleton. Starts tomcat once per JVM + * @return + */ + public static synchronized TomcatRuntime getInstance() { + if ( instance == null ) { + + + instance = new TomcatRuntime(); + } + + return instance; + } + + + /** + * Get the port tomcat is running on + */ + public int getPort() { + return tomcat.getPort(); + } + + + /** + * Inner class of tomcat runtime + */ + private static class TomcatInstance { + + public static final int THREADS_PERPROC = 25; + + private final String webAppsPath; + + private Tomcat tomcat = null; + private int port; + + private boolean started = false; + + + private TomcatInstance( final String webAppsPath ) {this.webAppsPath = webAppsPath;} + + + /** + * Start the tomcat instance + */ + public void startTomcat() { + try { + + //we don't want to use all our threads, we'll kill the box + final int availableProcessors = Runtime.getRuntime().availableProcessors(); + final int usedProcs = Math.min( 2, availableProcessors ); + final int threads = usedProcs * THREADS_PERPROC; + + + File dataDir = Files.createTempDir(); + dataDir.deleteOnExit(); + + port = AvailablePortFinder.getNextAvailable( 9998 + RandomUtils.nextInt( 10 ) ); + + tomcat = new Tomcat(); + tomcat.setBaseDir( dataDir.getAbsolutePath() ); + tomcat.setPort( port ); + + + tomcat.getConnector().setAttribute( "maxThreads", "" + threads ); + + tomcat.addWebapp( "/", new File( webAppsPath ).getAbsolutePath() ); + + + log.info( "-----------------------------------------------------------------" ); + log.info( "Starting Tomcat embedded port {} dir {}", port, dataDir.getAbsolutePath() ); + log.info( "-----------------------------------------------------------------" ); + tomcat.start(); + + waitForTomcat(); + + } + catch ( Exception e ) { + throw new RuntimeException( "Couldn't start tomcat", e ); + } + } + + + /** + * Stop the embedded tomcat process + */ + public void stopTomcat() { + try { + tomcat.stop(); + } + catch ( LifecycleException e ) { + throw new RuntimeException( "Unable to stop tomcat", e ); + } + } + + + public int getPort() { + return port; + } + + + private void waitForTomcat() throws RuntimeException { + String url = "http://localhost:" + port + "/status"; + int count = 0; + while ( count++ < 30 ) { + try { + Thread.sleep( 1000 ); + Client c = ClientBuilder.newClient(); + WebTarget wr = c.target( url ); + wr.request().get( String.class ); + log.info( "Tomcat is started." ); + started = true; + break; + } + catch ( Exception e ) { + log.info( "Waiting for Tomcat on url {}", url ); + } + } + if ( !started ) { + throw new RuntimeException( "Tomcat process never started." ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/resources/log4j.properties b/docs/jersey2skeleton/src/test/resources/log4j.properties new file mode 100644 index 0000000..8241c0a --- /dev/null +++ b/docs/jersey2skeleton/src/test/resources/log4j.properties @@ -0,0 +1,31 @@ +# 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. + +# for production, you should probably set the root to INFO +# and the pattern to %c instead of %l. (%l is slower.) + +# output messages into a rolling log file as well as stdout +log4j.rootLogger=ERROR,stdout + +# stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +#log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p (%t) %c{1} - %m%n + +log4j.logger.org.glassfish=DEBUG + +log4j.logger.org.apache.usergrid.testapp=DEBUG http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/src/test/resources/logging.properties ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/src/test/resources/logging.properties b/docs/jersey2skeleton/src/test/resources/logging.properties new file mode 100644 index 0000000..f0dcc65 --- /dev/null +++ b/docs/jersey2skeleton/src/test/resources/logging.properties @@ -0,0 +1,26 @@ +# 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. + +# Tweak this file to get more logging out Jersey and other depedencies that use +# Java Logging instead of our preferred SLF4J via Log4j setup. + +handlers = org.slf4j.bridge.SLF4JBridgeHandler + +#All log level details +.level=INFO +org.glassfish.jersey.level=FINE +org.glassfish.jersey.tracing.level=FINE + http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/templates/markdown.hbs ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/templates/markdown.hbs b/docs/jersey2skeleton/templates/markdown.hbs new file mode 100644 index 0000000..546f673 --- /dev/null +++ b/docs/jersey2skeleton/templates/markdown.hbs @@ -0,0 +1,108 @@ +#{{#info}}{{title}} + + +## {{join schemes " | "}}://{{host}}{{basePath}} + + +{{description}} + +{{#contact}} +[**Contact the developer**](mailto:{{email}}) +{{/contact}} + +**Version** {{version}} + +[**Terms of Service**]({{termsOfService}}) + +{{#license}}[**{{name}}**]({{url}}){{/license}} + +{{/info}} + +{{#if consumes}}**Consumes:** {{join consumes ", "}}{{/if}} + +{{#if produces}}**Produces:** {{join produces ", "}}{{/if}} + +{{#if securityDefinitions}} +# Security Definitions +{{/if}} +{{> security}} + +# APIs + +{{#each paths}} +## {{@key}} +{{#this}} +{{#get}} +### GET +{{> operation}} +{{/get}} + +{{#put}} +### PUT +{{> operation}} +{{/put}} + +{{#post}} +### POST + +{{> operation}} + +{{/post}} + +{{#delete}} +### DELETE +{{> operation}} +{{/delete}} + +{{#option}} +### OPTION +{{> operation}} +{{/option}} + +{{#patch}} +### PATCH +{{> operation}} +{{/patch}} + +{{#head}} +### HEAD +{{> operation}} +{{/head}} + +{{/this}} +{{/each}} + +# Definitions +{{#each definitions}} +## <a name="/definitions/{{key}}">{{@key}}</a> + +<table border="1"> + <tr> + <th>name</th> + <th>type</th> + <th>required</th> + <th>description</th> + <th>example</th> + </tr> + {{#each this.properties}} + <tr> + <td>{{@key}}</td> + <td> + {{#ifeq type "array"}} + {{#items.$ref}} + {{type}}[<a href="{{items.$ref}}">{{basename items.$ref}}</a>] + {{/items.$ref}} + {{^items.$ref}}{{type}}[{{items.type}}]{{/items.$ref}} + {{else}} + {{#$ref}}<a href="{{$ref}}">{{basename $ref}}</a>{{/$ref}} + {{^$ref}}{{type}}{{#format}} ({{format}}){{/format}}{{/$ref}} + {{/ifeq}} + </td> + <td>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td> + <td>{{#description}}{{{description}}}{{/description}}{{^description}}-{{/description}}</td> + <td>{{example}}</td> + </tr> + {{/each}} +</table> +{{/each}} + http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/templates/operation.hbs ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/templates/operation.hbs b/docs/jersey2skeleton/templates/operation.hbs new file mode 100644 index 0000000..a581961 --- /dev/null +++ b/docs/jersey2skeleton/templates/operation.hbs @@ -0,0 +1,73 @@ +{{#deprecated}}-deprecated-{{/deprecated}} +<a id="{{operationId}}">{{summary}}</a> + +{{description}} + +{{#if externalDocs.url}}{{externalDocs.description}}. [See external documents for more details]({{externalDocs.url}}) +{{/if}} + +{{#if security}} +#### Security +{{/if}} + +{{#security}} +{{#each this}} +* {{@key}} +{{#this}} * {{this}} +{{/this}} +{{/each}} +{{/security}} + +#### Request + +{{#if consumes}} +**Content-Type: ** {{join consumes ", "}}{{/if}} + +##### Parameters +{{#if parameters}} +<table border="1"> + <tr> + <th>Name</th> + <th>Located in</th> + <th>Required</th> + <th>Description</th> + <th>Default</th> + <th>Schema</th> + </tr> +{{/if}} + +{{#parameters}} +<tr> + <th>{{name}}</th> + <td>{{in}}</td> + <td>{{#if required}}yes{{else}}no{{/if}}</td> + <td>{{description}}{{#if pattern}} (**Pattern**: `{{pattern}}`){{/if}}</td> + <td> - </td> +{{#ifeq in "body"}} + <td> + {{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}} + {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a> {{/schema.$ref}} + </td> +{{else}} + {{#ifeq type "array"}} + <td>Array[{{items.type}}] ({{collectionFormat}})</td> + {{else}} + <td>{{type}} {{#format}}({{format}}){{/format}}</td> + {{/ifeq}} +{{/ifeq}} +</tr> +{{/parameters}} +{{#if parameters}} +</table> +{{/if}} + + +#### Response + +{{#if produces}}**Content-Type: ** {{join produces ", "}}{{/if}} + + +| Status Code | Reason | Response Model | +|-------------|-------------|----------------| +{{#each responses}}| {{@key}} | {{description}} | {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a>{{/schema.$ref}}{{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}}{{^schema}} - {{/schema}}| +{{/each}} http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/templates/security.hbs ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/templates/security.hbs b/docs/jersey2skeleton/templates/security.hbs new file mode 100644 index 0000000..04f86e8 --- /dev/null +++ b/docs/jersey2skeleton/templates/security.hbs @@ -0,0 +1,88 @@ +{{#each securityDefinitions}} +### {{@key}} +{{#this}} +{{#ifeq type "oauth2"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> +{{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> +{{/if}} +{{#if authorizationUrl}} + <tr> + <th>authorizationUrl</th> + <th colspan="2">{{authorizationUrl}}</th> + </tr> +{{/if}} +{{#if flow}} + <tr> + <th>flow</th> + <th colspan="2">{{flow}}</th> + </tr> +{{/if}} +{{#if tokenUrl}} + <tr> + <th>tokenUrl</th> + <th colspan="2">{{tokenUrl}}</th> + </tr> +{{/if}} +{{#if scopes}} + <tr> + <td rowspan="3">scopes</td> +{{#each scopes}} + <td>{{@key}}</td> + <td>{{this}}</td> + </tr> + <tr> +{{/each}} + </tr> +{{/if}} +</table> +{{/ifeq}} +{{#ifeq type "apiKey"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> +{{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> +{{/if}} +{{#if name}} + <tr> + <th>name</th> + <th colspan="2">{{name}}</th> + </tr> +{{/if}} +{{#if in}} + <tr> + <th>in</th> + <th colspan="2">{{in}}</th> + </tr> +{{/if}} +</table> +{{/ifeq}} +{{#ifeq type "basic"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> +{{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> +{{/if}} +</table> +{{/ifeq}} +{{/this}} +{{/each}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/6ea66856/docs/jersey2skeleton/templates/strapdown.html.hbs ---------------------------------------------------------------------- diff --git a/docs/jersey2skeleton/templates/strapdown.html.hbs b/docs/jersey2skeleton/templates/strapdown.html.hbs new file mode 100644 index 0000000..ec02669 --- /dev/null +++ b/docs/jersey2skeleton/templates/strapdown.html.hbs @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<title>API Document</title> + +<xmp theme="united" style="display:none;"> +{{>markdown}} +</xmp> + +<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script> +</html> \ No newline at end of file
