diff --git a/bin/java-undertow-petstore-server.sh b/bin/java-undertow-petstore-server.sh new file mode 100755 index 00000000000..9e949909f4d --- /dev/null +++ b/bin/java-undertow-petstore-server.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/undertow -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l undertow -o samples/server/petstore/undertow" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/UndertowCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/UndertowCodegen.java new file mode 100644 index 00000000000..b212e42a316 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/UndertowCodegen.java @@ -0,0 +1,219 @@ +package io.swagger.codegen.languages; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.codegen.*; +import io.swagger.models.Operation; +import io.swagger.models.Swagger; +import io.swagger.util.Json; +import io.swagger.util.Yaml; +import org.apache.commons.lang3.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; + +public class UndertowCodegen extends AbstractJavaCodegen { + + private static final Logger LOGGER = LoggerFactory.getLogger(UndertowCodegen.class); + + protected String title = "Swagger Undertow Server"; + protected String implFolder = "src/main/java"; + public UndertowCodegen() { + super(); + + sourceFolder = "src/main/java"; + apiTestTemplateFiles.clear(); // TODO: add test template + embeddedTemplateDir = templateDir = "undertow"; + invokerPackage = "io.swagger.handler"; + artifactId = "swagger-undertow-server"; + dateLibrary = "legacy"; //TODO: add joda support + + // clear model and api doc template as this codegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); + + + apiPackage = System.getProperty("swagger.codegen.undertow.apipackage", "io.swagger.handler"); + modelPackage = System.getProperty("swagger.codegen.undertow.modelpackage", "io.swagger.model"); + + additionalProperties.put("title", title); + } + + @Override + public CodegenType getTag() { + return CodegenType.SERVER; + } + + @Override + public String getName() { + return "undertow"; + } + + @Override + public String getHelp() { + return "Generates a Java Undertow Server application."; + } + + @Override + public void processOpts() { + super.processOpts(); + + apiTemplateFiles.remove("api.mustache"); + + writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml")); + writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md")); + + // keep the yaml in config folder for framework validation. + supportingFiles.add(new SupportingFile("swagger.mustache", ("src.main.resources.config").replace(".", java.io.File.separator), "swagger.json")); + supportingFiles.add(new SupportingFile("handler.mustache", ("src.main.java.io.swagger.handler").replace(".", java.io.File.separator), "PathHandlerProvider.java")); + supportingFiles.add(new SupportingFile("service.mustache", ("src.main.resources.META-INF.services").replace(".", java.io.File.separator), "com.networknt.server.HandlerProvider")); + + // configuration files + supportingFiles.add(new SupportingFile("server.json", ("src.main.resources.config").replace(".", java.io.File.separator), "server.json")); + supportingFiles.add(new SupportingFile("security.json", ("src.main.resources.config").replace(".", java.io.File.separator), "security.json")); + supportingFiles.add(new SupportingFile("primary.crt", ("src.main.resources.config.oauth").replace(".", java.io.File.separator), "primary.crt")); + + } + + /* + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath == "") { + basePath = "default"; + } else { + if (co.path.startsWith("/" + basePath)) { + co.path = co.path.substring(("/" + basePath).length()); + } + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + */ + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (CodegenOperation operation : ops) { + if (operation.returnType == null) { + operation.returnType = "Void"; + } else if (operation.returnType.startsWith("List")) { + String rt = operation.returnType; + int end = rt.lastIndexOf(">"); + if (end > 0) { + operation.returnType = rt.substring("List<".length(), end); + operation.returnContainer = "List"; + } + } else if (operation.returnType.startsWith("Map")) { + String rt = operation.returnType; + int end = rt.lastIndexOf(">"); + if (end > 0) { + operation.returnType = rt.substring("Map<".length(), end); + operation.returnContainer = "Map"; + } + } else if (operation.returnType.startsWith("Set")) { + String rt = operation.returnType; + int end = rt.lastIndexOf(">"); + if (end > 0) { + operation.returnType = rt.substring("Set<".length(), end); + operation.returnContainer = "Set"; + } + } + } + } + return objs; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + + //Add imports for Jackson + if(!BooleanUtils.toBoolean(model.isEnum)) { + model.imports.add("JsonProperty"); + + if(BooleanUtils.toBoolean(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + //Add imports for Jackson + List> imports = (List>)objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + public String apiFilename(String templateName, String tag) { + String result = super.apiFilename(templateName, tag); + + if ( templateName.endsWith("api.mustache") ) { + int ix = result.indexOf(sourceFolder); + String beg = result.substring(0, ix); + String end = result.substring(ix + sourceFolder.length()); + new java.io.File(beg + implFolder).mkdirs(); + result = beg + implFolder + end; + } + return result; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + Swagger swagger = (Swagger)objs.get("swagger"); + System.out.println("swagger" + swagger.toString()); + if(swagger != null) { + try { + //objs.put("swagger-json", Json.mapper().writeValueAsString(swagger)); + objs.put("swagger-json", Json.pretty().writeValueAsString(swagger)); + } catch (JsonProcessingException e) { + LOGGER.error(e.getMessage(), e); + } + } + return super.postProcessSupportingFileData(objs); + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultHandler"; + } + name = name.replaceAll("[^a-zA-Z0-9]+", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + return camelize(name)+ "Handler"; + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 764b4b26b53..3c3a092efe0 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -52,3 +52,5 @@ io.swagger.codegen.languages.HaskellServantCodegen io.swagger.codegen.languages.LumenServerCodegen io.swagger.codegen.languages.GoServerCodegen io.swagger.codegen.languages.ErlangServerCodegen +io.swagger.codegen.languages.UndertowCodegen + diff --git a/modules/swagger-codegen/src/main/resources/undertow/README.mustache b/modules/swagger-codegen/src/main/resources/undertow/README.mustache new file mode 100644 index 00000000000..9f1e36dd163 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/README.mustache @@ -0,0 +1,28 @@ +# Swagger Undertow Server + +## Start server + +Run with + +``` +mvn package exec:exec +`` + +## Test + +By default, all endpoints are protected by OAuth jwt token verifier. It can be turned off with config change through for development. + + +In order to access the server, there is a long lived token below issued by my +oauth2 server [undertow-server-oauth2](https://github.com/networknt/undertow-server-oauth2) + +``` +Bearer eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ1cm46Y29tOm5ldHdvcmtudDpvYXV0aDI6djEiLCJhdWQiOiJ1cm46Y29tLm5ldHdvcmtudCIsImV4cCI6MTc4ODEzMjczNSwianRpIjoiNWtyM2ZWOHJaelBZNEJrSnNYZzFpQSIsImlhdCI6MTQ3Mjc3MjczNSwibmJmIjoxNDcyNzcyNjE1LCJ2ZXJzaW9uIjoiMS4wIiwidXNlcl9pZCI6InN0ZXZlIiwidXNlcl90eXBlIjoiRU1QTE9ZRUUiLCJjbGllbnRfaWQiOiJkZGNhZjBiYS0xMTMxLTIyMzItMzMxMy1kNmYyNzUzZjI1ZGMiLCJzY29wZSI6WyJhcGkuciIsImFwaS53Il19.gteJiy1uao8HLeWRljpZxHWUgQfofwmnFP-zv3EPUyXjyCOy3xclnfeTnTE39j8PgBwdFASPcDLLk1YfZJbsU6pLlmYXLtdpHDBsVmIRuch6LFPCVQ3JdqSQVci59OhSK0bBThGWqCD3UzDI_OnX4IVCAahcT9Bu94m5u_H_JNmwDf1XaP3Lt4I34buYMuRD9stchsnZi-tuIRkL13FARm1XA9aPZUMUXFdedBWDXo1zMREQ_qCJXOpaZDJM9Im0rIkq9wTEVU00pbRp_Vcdya3dfkFteBMHiwFVt6VNQaco5BXURDAIzXidwQxNEbX1ek03wra8AIani65ZK7fy_w +``` + +Postman is the best tool to test REST APIs + +Add "Authorization" header with value as above token and a dummy message will return from the generated stub. + + + diff --git a/modules/swagger-codegen/src/main/resources/undertow/bodyParams.mustache b/modules/swagger-codegen/src/main/resources/undertow/bodyParams.mustache new file mode 100644 index 00000000000..c7d1abfe527 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/enumClass.mustache b/modules/swagger-codegen/src/main/resources/undertow/enumClass.mustache new file mode 100644 index 00000000000..0867107d993 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/enumClass.mustache @@ -0,0 +1,17 @@ + + public enum {{{datatypeWithEnum}}} { + {{#allowableValues}}{{#enumVars}}{{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private String value; + + {{{datatypeWithEnum}}}(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } diff --git a/modules/swagger-codegen/src/main/resources/undertow/enumOuterClass.mustache b/modules/swagger-codegen/src/main/resources/undertow/enumOuterClass.mustache new file mode 100644 index 00000000000..aca7bd48c14 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/enumOuterClass.mustache @@ -0,0 +1,42 @@ +{{#jackson}} + import com.fasterxml.jackson.annotation.JsonCreator; +{{/jackson}} + +/** +* {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} +*/ +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{#gson}} + {{#allowableValues}}{{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} +{{/gson}} +{{^gson}} + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} +{{/gson}} + +private {{{dataType}}} value; + +{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { +this.value = value; +} + +@Override +@JsonValue +public String toString() { +return String.valueOf(value); +} + +@JsonCreator +public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { +for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { +if (String.valueOf(b.value).equals(text)) { +return b; +} +} +return null; +} +} diff --git a/modules/swagger-codegen/src/main/resources/undertow/formParams.mustache b/modules/swagger-codegen/src/main/resources/undertow/formParams.mustache new file mode 100644 index 00000000000..e44ab167e8f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}FormDataContentDisposition fileDetail{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/generatedAnnotation.mustache b/modules/swagger-codegen/src/main/resources/undertow/generatedAnnotation.mustache new file mode 100644 index 00000000000..49110fc1ad9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/generatedAnnotation.mustache @@ -0,0 +1 @@ +@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/handler.mustache b/modules/swagger-codegen/src/main/resources/undertow/handler.mustache new file mode 100644 index 00000000000..c6830c0cd97 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/handler.mustache @@ -0,0 +1,34 @@ +package io.swagger.handler; + +import com.networknt.config.Config; +import com.networknt.server.HandlerProvider; +import io.undertow.Handlers; +import io.undertow.server.HttpHandler; +import io.undertow.server.HttpServerExchange; +import io.undertow.util.Methods; + +public class PathHandlerProvider implements HandlerProvider { + + public HttpHandler getHandler() { + HttpHandler handler = Handlers.routing() + +{{#apiInfo}} +{{#apis}} +{{#operations}} +{{#operation}} + + .add(Methods.{{httpMethod}}, "{{basePathWithoutHost}}{{path}}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("{{operationId}}"); + } + }) + +{{/operation}} +{{/operations}} +{{/apis}} +{{/apiInfo}} + ; + return handler; + } +} + diff --git a/modules/swagger-codegen/src/main/resources/undertow/headerParams.mustache b/modules/swagger-codegen/src/main/resources/undertow/headerParams.mustache new file mode 100644 index 00000000000..bd03573d196 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}{{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/inflector.mustache b/modules/swagger-codegen/src/main/resources/undertow/inflector.mustache new file mode 100644 index 00000000000..87fc5581316 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/inflector.mustache @@ -0,0 +1,13 @@ +controllerPackage: {{invokerPackage}} +modelPackage: {{modelPackage}} +swaggerUrl: ./src/main/swagger/swagger.yaml +modelMappings: + # to enable explicit mappings, use this syntax: + DefinitionFromSwaggerSpecification: fully.qualified.path.to.Model + {{#models}}{{#model}}{{classname}} : {{modelPackage}}.{{classname}}{{/model}} + {{/models}} + +entityProcessors: + - json + - xml + - yaml \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/model.mustache b/modules/swagger-codegen/src/main/resources/undertow/model.mustache new file mode 100644 index 00000000000..b9512d2b83c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/model.mustache @@ -0,0 +1,16 @@ +package {{package}}; + +import java.util.Objects; +{{#imports}}import {{import}}; +{{/imports}} + +{{#serializableModel}}import java.io.Serializable;{{/serializableModel}} +{{#models}} +{{#model}}{{#description}} +/** + * {{description}} + **/{{/description}} +{{#isEnum}}{{>enumOuterClass}}{{/isEnum}} +{{^isEnum}}{{>pojo}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/undertow/pathParams.mustache b/modules/swagger-codegen/src/main/resources/undertow/pathParams.mustache new file mode 100644 index 00000000000..6829cf8c7a6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}{{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/pojo.mustache b/modules/swagger-codegen/src/main/resources/undertow/pojo.mustache new file mode 100644 index 00000000000..58bfed16381 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/pojo.mustache @@ -0,0 +1,73 @@ +{{#description}}@ApiModel(description = "{{{description}}}"){{/description}} +{{>generatedAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} { + {{#vars}}{{#isEnum}} + +{{>enumClass}}{{/isEnum}}{{#items.isEnum}}{{#items}} + +{{>enumClass}}{{/items}}{{/items.isEnum}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/vars}} + + {{#vars}} + /**{{#description}} + * {{{description}}}{{/description}}{{#minimum}} + * minimum: {{minimum}}{{/minimum}}{{#maximum}} + * maximum: {{maximum}}{{/maximum}} + **/ + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + + {{#vendorExtensions.extraAnnotation}}{{vendorExtensions.extraAnnotation}}{{/vendorExtensions.extraAnnotation}} + @ApiModelProperty({{#example}}example = "{{example}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") + @JsonProperty("{{baseName}}") + public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + } + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + {{/vars}} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + {{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}} + return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/modules/swagger-codegen/src/main/resources/undertow/pom.mustache b/modules/swagger-codegen/src/main/resources/undertow/pom.mustache new file mode 100644 index 00000000000..f15f97eab44 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/pom.mustache @@ -0,0 +1,189 @@ + + + org.sonatype.oss + oss-parent + 5 + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + 2.2.0 + + + + 1.8 + UTF-8 + 0.1.1 + 2.8.2 + 1.7.21 + 0.5.2 + 4.5.3 + 2.6 + 2.5 + 1.10 + 1.2 + 3.1.2 + 1.1.7 + 4.12 + 2.1.0-beta.124 + 1.4.0.Final + 2.2.0 + 4.5.2 + 4.1.2 + 1.5.10 + + + + + com.networknt + config + ${version.framework} + + + com.networknt + utility + ${version.framework} + + + com.networknt + security + ${version.framework} + + + com.networknt + client + ${version.framework} + + + com.networknt + audit + ${version.framework} + + + com.networknt + info + ${version.framework} + + + com.networknt + validator + ${version.framework} + + + com.networknt + server + ${version.framework} + + + + com.fasterxml.jackson.core + jackson-databind + ${version.jackson} + + + com.fasterxml.jackson.core + jackson-core + ${version.jackson} + + + com.jayway.jsonpath + json-path + ${version.jsonpath} + + + ch.qos.logback + logback-classic + ${version.logback} + + + io.undertow + undertow-core + ${version.undertow} + + + io.swagger + swagger-annotations + ${version.swagger} + + + + + junit + junit + ${version.junit} + test + + + org.apache.httpcomponents + httpclient + ${version.httpclient} + test + + + + + + + install + target + ${project.artifactId}-${project.version} + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + com.networknt.server.Server + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + java + + -jar + target/${project.build.finalName}.jar + + + + + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/primary.crt b/modules/swagger-codegen/src/main/resources/undertow/primary.crt new file mode 100644 index 00000000000..51ee3649759 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/primary.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDmzCCAoOgAwIBAgIEHnAgtDANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJDQTEQMA4GA1UE +CBMHT250YXJpbzEUMBIGA1UEBxMLTWlzc2lzc2F1Z2ExJjAkBgNVBAoTHU5ldHdvcmsgTmV3IFRl +Y2hub2xvZ2llcyBJbmMuMQwwCgYDVQQLEwNERVYxETAPBgNVBAMTCFN0ZXZlIEh1MB4XDTE2MDkw +MTE2MTYxNVoXDTI2MDcxMTE2MTYxNVowfjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8x +FDASBgNVBAcTC01pc3Npc3NhdWdhMSYwJAYDVQQKEx1OZXR3b3JrIE5ldyBUZWNobm9sb2dpZXMg +SW5jLjEMMAoGA1UECxMDREVWMREwDwYDVQQDEwhTdGV2ZSBIdTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALrlxMtDb60DogElf4TBz504tRheZimAE0dJL/Yby4nacJdqvc5l4z+WWpDf +rI9krQ2Yi9yvhwAP+PrR6gWcIqWP4cpNE7XIAUDgr4CtyI7CptT/lpjtbkz4DGCMmaeDn0jqHqJt +SeSZGfwVu5zAGm8n4sHatjnnxBI/iWzkTII3V4xv0WeK37szNTEd+ly2ag7n2IV5zNnYmqZTeMQm +J2ENS+IwAG3ENtiVtrVTx/2bGtqutJjtdxsN58/cUG/guRyMT6OPI8Yi3ZzevdvRbxadyhEl/Kaw +6vJcdxmJI3tp4lx+p6sAxOWa7aapJe4JxutAQqzv0GKdVjoHKQ1wB60CAwEAAaMhMB8wHQYDVR0O +BBYEFIPF9SBd06RWU1eDL73CKfy01lavMA0GCSqGSIb3DQEBCwUAA4IBAQAoaKZGOak3Upz/ordF +slZoJuZlCu7jnKQEjYwHf3DNxcd1WmgFPtMcna6pW0VUxPIfidEA6VCMsGoK1RvshB0SjrRdCht6 +5qPXs9kV3NW0WvMiwDSYZZ9HgaZ9efTe5E9Fzc7ltKrE43L6k8NJcaEEWEdpdjFbrAqH4I+j/Vro +K3OhIo062fXjas5ipL4gF+3ECImjWzirQP8UiAfM0/36x7rtAu3btH/qI9hSyx39LBPPE5AsDJZ4 +dSMwNTW1gqmBAZIj+zQ/RD5dyWfPwON7Q+t96YbK6WBuYo0xy+I+PjcUgrWYWP3N24hlq8ZBIei+ +BudoEVJlIlmS0aRCuP8n +-----END CERTIFICATE----- diff --git a/modules/swagger-codegen/src/main/resources/undertow/queryParams.mustache b/modules/swagger-codegen/src/main/resources/undertow/queryParams.mustache new file mode 100644 index 00000000000..ff79730471d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/security.json b/modules/swagger-codegen/src/main/resources/undertow/security.json new file mode 100644 index 00000000000..400070d0a2d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/security.json @@ -0,0 +1,13 @@ +{ + "description": "security configuration", + "enableVerifyJwt": false, + "jwt": { + "certificate": [ + "oauth/primary.crt" + ], + "clockSkewInSeconds": 60 + }, + "logJwtToken": true, + "logClientUserScope": false, + "enableVerifyScope": true +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/server.json b/modules/swagger-codegen/src/main/resources/undertow/server.json new file mode 100644 index 00000000000..14d16ce289a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/server.json @@ -0,0 +1,5 @@ +{ + "description": "server config", + "ip": "0.0.0.0", + "port": 8080 +} diff --git a/modules/swagger-codegen/src/main/resources/undertow/service.mustache b/modules/swagger-codegen/src/main/resources/undertow/service.mustache new file mode 100644 index 00000000000..e6f7ef0b3e5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/service.mustache @@ -0,0 +1 @@ +io.swagger.handler.PathHandlerProvider \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/undertow/swagger.mustache b/modules/swagger-codegen/src/main/resources/undertow/swagger.mustache new file mode 100644 index 00000000000..0a7a2006155 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/undertow/swagger.mustache @@ -0,0 +1 @@ +{{{swagger-json}}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaUndertowServerOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaUndertowServerOptionsProvider.java new file mode 100644 index 00000000000..9a1ab264fd3 --- /dev/null +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaUndertowServerOptionsProvider.java @@ -0,0 +1,16 @@ +package io.swagger.codegen.options; + +/** + * Created by steve on 18/09/16. + */ +public class JavaUndertowServerOptionsProvider extends JavaOptionsProvider { + @Override + public String getLanguage() { + return "undertow"; + } + + @Override + public boolean isServer() { + return true; + } +} diff --git a/pom.xml b/pom.xml index bb9d99ca5a4..a06b416d98e 100644 --- a/pom.xml +++ b/pom.xml @@ -616,6 +616,18 @@ samples/server/petstore/java-inflector + + java-undertowr + + + env + java + + + + samples/server/petstore/undertow + + samples @@ -650,6 +662,7 @@ samples/client/petstore/typescript-node/npm samples/server/petstore/java-inflector + samples/server/petstore/undertow samples/server/petstore/jaxrs/jersey1 samples/server/petstore/jaxrs/jersey2 samples/server/petstore/jaxrs-resteasy/default diff --git a/samples/server/petstore/undertow/.swagger-codegen-ignore b/samples/server/petstore/undertow/.swagger-codegen-ignore new file mode 100644 index 00000000000..c5fa491b4c5 --- /dev/null +++ b/samples/server/petstore/undertow/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/server/petstore/undertow/LICENSE b/samples/server/petstore/undertow/LICENSE new file mode 100644 index 00000000000..8dada3edaf5 --- /dev/null +++ b/samples/server/petstore/undertow/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/samples/server/petstore/undertow/README.md b/samples/server/petstore/undertow/README.md new file mode 100644 index 00000000000..9f1e36dd163 --- /dev/null +++ b/samples/server/petstore/undertow/README.md @@ -0,0 +1,28 @@ +# Swagger Undertow Server + +## Start server + +Run with + +``` +mvn package exec:exec +`` + +## Test + +By default, all endpoints are protected by OAuth jwt token verifier. It can be turned off with config change through for development. + + +In order to access the server, there is a long lived token below issued by my +oauth2 server [undertow-server-oauth2](https://github.com/networknt/undertow-server-oauth2) + +``` +Bearer eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ1cm46Y29tOm5ldHdvcmtudDpvYXV0aDI6djEiLCJhdWQiOiJ1cm46Y29tLm5ldHdvcmtudCIsImV4cCI6MTc4ODEzMjczNSwianRpIjoiNWtyM2ZWOHJaelBZNEJrSnNYZzFpQSIsImlhdCI6MTQ3Mjc3MjczNSwibmJmIjoxNDcyNzcyNjE1LCJ2ZXJzaW9uIjoiMS4wIiwidXNlcl9pZCI6InN0ZXZlIiwidXNlcl90eXBlIjoiRU1QTE9ZRUUiLCJjbGllbnRfaWQiOiJkZGNhZjBiYS0xMTMxLTIyMzItMzMxMy1kNmYyNzUzZjI1ZGMiLCJzY29wZSI6WyJhcGkuciIsImFwaS53Il19.gteJiy1uao8HLeWRljpZxHWUgQfofwmnFP-zv3EPUyXjyCOy3xclnfeTnTE39j8PgBwdFASPcDLLk1YfZJbsU6pLlmYXLtdpHDBsVmIRuch6LFPCVQ3JdqSQVci59OhSK0bBThGWqCD3UzDI_OnX4IVCAahcT9Bu94m5u_H_JNmwDf1XaP3Lt4I34buYMuRD9stchsnZi-tuIRkL13FARm1XA9aPZUMUXFdedBWDXo1zMREQ_qCJXOpaZDJM9Im0rIkq9wTEVU00pbRp_Vcdya3dfkFteBMHiwFVt6VNQaco5BXURDAIzXidwQxNEbX1ek03wra8AIani65ZK7fy_w +``` + +Postman is the best tool to test REST APIs + +Add "Authorization" header with value as above token and a dummy message will return from the generated stub. + + + diff --git a/samples/server/petstore/undertow/dependency-reduced-pom.xml b/samples/server/petstore/undertow/dependency-reduced-pom.xml new file mode 100644 index 00000000000..59481b75ae5 --- /dev/null +++ b/samples/server/petstore/undertow/dependency-reduced-pom.xml @@ -0,0 +1,114 @@ + + + + oss-parent + org.sonatype.oss + 5 + ../pom.xml/pom.xml + + 4.0.0 + io.swagger + swagger-undertow-server + swagger-undertow-server + 1.0.0 + + 2.2.0 + + + install + target + ${project.artifactId}-${project.version} + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + + + + + maven-jar-plugin + 2.6 + + + + com.networknt.server.Server + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + java + + -jar + target/${project.build.finalName}.jar + + + + + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + + + junit + junit + 4.12 + test + + + hamcrest-core + org.hamcrest + + + + + org.apache.httpcomponents + httpclient + 4.5.2 + test + + + + 4.1.2 + 1.10 + 3.1.2 + 2.2.0 + UTF-8 + 1.2 + 4.5.2 + 1.4.0.Final + 0.5.2 + 2.6 + 1.8 + 2.8.2 + 0.1.1 + 1.5.10 + 2.1.0-beta.124 + 1.7.21 + 2.5 + 1.1.7 + 4.12 + 4.5.3 + + + diff --git a/samples/server/petstore/undertow/pom.xml b/samples/server/petstore/undertow/pom.xml new file mode 100644 index 00000000000..f5e8cc42f31 --- /dev/null +++ b/samples/server/petstore/undertow/pom.xml @@ -0,0 +1,189 @@ + + + org.sonatype.oss + oss-parent + 5 + + 4.0.0 + io.swagger + swagger-undertow-server + jar + swagger-undertow-server + 1.0.0 + + 2.2.0 + + + + 1.8 + UTF-8 + 0.1.1 + 2.8.2 + 1.7.21 + 0.5.2 + 4.5.3 + 2.6 + 2.5 + 1.10 + 1.2 + 3.1.2 + 1.1.7 + 4.12 + 2.1.0-beta.124 + 1.4.0.Final + 2.2.0 + 4.5.2 + 4.1.2 + 1.5.10 + + + + + com.networknt + config + ${version.framework} + + + com.networknt + utility + ${version.framework} + + + com.networknt + security + ${version.framework} + + + com.networknt + client + ${version.framework} + + + com.networknt + audit + ${version.framework} + + + com.networknt + info + ${version.framework} + + + com.networknt + validator + ${version.framework} + + + com.networknt + server + ${version.framework} + + + + com.fasterxml.jackson.core + jackson-databind + ${version.jackson} + + + com.fasterxml.jackson.core + jackson-core + ${version.jackson} + + + com.jayway.jsonpath + json-path + ${version.jsonpath} + + + ch.qos.logback + logback-classic + ${version.logback} + + + io.undertow + undertow-core + ${version.undertow} + + + io.swagger + swagger-annotations + ${version.swagger} + + + + + junit + junit + ${version.junit} + test + + + org.apache.httpcomponents + httpclient + ${version.httpclient} + test + + + + + + + install + target + ${project.artifactId}-${project.version} + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + com.networknt.server.Server + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + java + + -jar + target/${project.build.finalName}.jar + + + + + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + \ No newline at end of file diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/handler/PathHandlerProvider.java b/samples/server/petstore/undertow/src/main/java/io/swagger/handler/PathHandlerProvider.java new file mode 100644 index 00000000000..2dbba6aff95 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/handler/PathHandlerProvider.java @@ -0,0 +1,159 @@ +package io.swagger.handler; + +import com.networknt.config.Config; +import com.networknt.server.HandlerProvider; +import io.undertow.Handlers; +import io.undertow.server.HttpHandler; +import io.undertow.server.HttpServerExchange; +import io.undertow.util.Methods; + +public class PathHandlerProvider implements HandlerProvider { + + public HttpHandler getHandler() { + HttpHandler handler = Handlers.routing() + + + .add(Methods.POST, "/v2/pet", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("addPet"); + } + }) + + + .add(Methods.DELETE, "/v2/pet/{petId}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("deletePet"); + } + }) + + + .add(Methods.GET, "/v2/pet/findByStatus", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("findPetsByStatus"); + } + }) + + + .add(Methods.GET, "/v2/pet/findByTags", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("findPetsByTags"); + } + }) + + + .add(Methods.GET, "/v2/pet/{petId}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("getPetById"); + } + }) + + + .add(Methods.PUT, "/v2/pet", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("updatePet"); + } + }) + + + .add(Methods.POST, "/v2/pet/{petId}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("updatePetWithForm"); + } + }) + + + .add(Methods.POST, "/v2/pet/{petId}/uploadImage", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("uploadFile"); + } + }) + + + .add(Methods.DELETE, "/v2/store/order/{orderId}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("deleteOrder"); + } + }) + + + .add(Methods.GET, "/v2/store/inventory", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("getInventory"); + } + }) + + + .add(Methods.GET, "/v2/store/order/{orderId}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("getOrderById"); + } + }) + + + .add(Methods.POST, "/v2/store/order", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("placeOrder"); + } + }) + + + .add(Methods.POST, "/v2/user", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("createUser"); + } + }) + + + .add(Methods.POST, "/v2/user/createWithArray", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("createUsersWithArrayInput"); + } + }) + + + .add(Methods.POST, "/v2/user/createWithList", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("createUsersWithListInput"); + } + }) + + + .add(Methods.DELETE, "/v2/user/{username}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("deleteUser"); + } + }) + + + .add(Methods.GET, "/v2/user/{username}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("getUserByName"); + } + }) + + + .add(Methods.GET, "/v2/user/login", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("loginUser"); + } + }) + + + .add(Methods.GET, "/v2/user/logout", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("logoutUser"); + } + }) + + + .add(Methods.PUT, "/v2/user/{username}", new HttpHandler() { + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("updateUser"); + } + }) + + ; + return handler; + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/Category.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Category.java new file mode 100644 index 00000000000..3009c443dd3 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Category.java @@ -0,0 +1,94 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class Category { + + private Long id = null; + private String name = null; + + /** + **/ + public Category id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Category name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(id, category.id) && + Objects.equals(name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/ModelApiResponse.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/ModelApiResponse.java new file mode 100644 index 00000000000..1525277a43c --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/ModelApiResponse.java @@ -0,0 +1,114 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class ModelApiResponse { + + private Integer code = null; + private String type = null; + private String message = null; + + /** + **/ + public ModelApiResponse code(Integer code) { + this.code = code; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("code") + public Integer getCode() { + return code; + } + public void setCode(Integer code) { + this.code = code; + } + + /** + **/ + public ModelApiResponse type(String type) { + this.type = type; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("type") + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + /** + **/ + public ModelApiResponse message(String message) { + this.message = message; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("message") + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ModelApiResponse _apiResponse = (ModelApiResponse) o; + return Objects.equals(code, _apiResponse.code) && + Objects.equals(type, _apiResponse.type) && + Objects.equals(message, _apiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ModelApiResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/Order.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Order.java new file mode 100644 index 00000000000..0c449c82625 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Order.java @@ -0,0 +1,197 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class Order { + + private Long id = null; + private Long petId = null; + private Integer quantity = null; + private Date shipDate = null; + + + public enum StatusEnum { + PLACED("placed"), + APPROVED("approved"), + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } + + private StatusEnum status = null; + private Boolean complete = false; + + /** + **/ + public Order id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Order petId(Long petId) { + this.petId = petId; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("petId") + public Long getPetId() { + return petId; + } + public void setPetId(Long petId) { + this.petId = petId; + } + + /** + **/ + public Order quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("quantity") + public Integer getQuantity() { + return quantity; + } + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + /** + **/ + public Order shipDate(Date shipDate) { + this.shipDate = shipDate; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("shipDate") + public Date getShipDate() { + return shipDate; + } + public void setShipDate(Date shipDate) { + this.shipDate = shipDate; + } + + /** + * Order Status + **/ + public Order status(StatusEnum status) { + this.status = status; + return this; + } + + + @ApiModelProperty(example = "null", value = "Order Status") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + /** + **/ + public Order complete(Boolean complete) { + this.complete = complete; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("complete") + public Boolean getComplete() { + return complete; + } + public void setComplete(Boolean complete) { + this.complete = complete; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(id, order.id) && + Objects.equals(petId, order.petId) && + Objects.equals(quantity, order.quantity) && + Objects.equals(shipDate, order.shipDate) && + Objects.equals(status, order.status) && + Objects.equals(complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/Pet.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Pet.java new file mode 100644 index 00000000000..54d5e1bb352 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Pet.java @@ -0,0 +1,200 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.model.Category; +import io.swagger.model.Tag; +import java.util.ArrayList; +import java.util.List; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class Pet { + + private Long id = null; + private Category category = null; + private String name = null; + private List photoUrls = new ArrayList(); + private List tags = new ArrayList(); + + + public enum StatusEnum { + AVAILABLE("available"), + PENDING("pending"), + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } + + private StatusEnum status = null; + + /** + **/ + public Pet id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Pet category(Category category) { + this.category = category; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("category") + public Category getCategory() { + return category; + } + public void setCategory(Category category) { + this.category = category; + } + + /** + **/ + public Pet name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(example = "doggie", required = true, value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + /** + **/ + public Pet photoUrls(List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + + @ApiModelProperty(example = "null", required = true, value = "") + @JsonProperty("photoUrls") + public List getPhotoUrls() { + return photoUrls; + } + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + /** + **/ + public Pet tags(List tags) { + this.tags = tags; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("tags") + public List getTags() { + return tags; + } + public void setTags(List tags) { + this.tags = tags; + } + + /** + * pet status in the store + **/ + public Pet status(StatusEnum status) { + this.status = status; + return this; + } + + + @ApiModelProperty(example = "null", value = "pet status in the store") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(id, pet.id) && + Objects.equals(category, pet.category) && + Objects.equals(name, pet.name) && + Objects.equals(photoUrls, pet.photoUrls) && + Objects.equals(tags, pet.tags) && + Objects.equals(status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/Tag.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Tag.java new file mode 100644 index 00000000000..0bd33725ff0 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/Tag.java @@ -0,0 +1,94 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class Tag { + + private Long id = null; + private String name = null; + + /** + **/ + public Tag id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Tag name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(id, tag.id) && + Objects.equals(name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/java/io/swagger/model/User.java b/samples/server/petstore/undertow/src/main/java/io/swagger/model/User.java new file mode 100644 index 00000000000..1135fc1b379 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/java/io/swagger/model/User.java @@ -0,0 +1,215 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.UndertowCodegen", date = "2016-09-19T05:56:00.864-04:00") +public class User { + + private Long id = null; + private String username = null; + private String firstName = null; + private String lastName = null; + private String email = null; + private String password = null; + private String phone = null; + private Integer userStatus = null; + + /** + **/ + public User id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public User username(String username) { + this.username = username; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("username") + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + /** + **/ + public User firstName(String firstName) { + this.firstName = firstName; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("firstName") + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + **/ + public User lastName(String lastName) { + this.lastName = lastName; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("lastName") + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + **/ + public User email(String email) { + this.email = email; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("email") + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + /** + **/ + public User password(String password) { + this.password = password; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("password") + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + /** + **/ + public User phone(String phone) { + this.phone = phone; + return this; + } + + + @ApiModelProperty(example = "null", value = "") + @JsonProperty("phone") + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + + /** + * User Status + **/ + public User userStatus(Integer userStatus) { + this.userStatus = userStatus; + return this; + } + + + @ApiModelProperty(example = "null", value = "User Status") + @JsonProperty("userStatus") + public Integer getUserStatus() { + return userStatus; + } + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(id, user.id) && + Objects.equals(username, user.username) && + Objects.equals(firstName, user.firstName) && + Objects.equals(lastName, user.lastName) && + Objects.equals(email, user.email) && + Objects.equals(password, user.password) && + Objects.equals(phone, user.phone) && + Objects.equals(userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/undertow/src/main/resources/META-INF/services/com.networknt.server.HandlerProvider b/samples/server/petstore/undertow/src/main/resources/META-INF/services/com.networknt.server.HandlerProvider new file mode 100644 index 00000000000..e6f7ef0b3e5 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/resources/META-INF/services/com.networknt.server.HandlerProvider @@ -0,0 +1 @@ +io.swagger.handler.PathHandlerProvider \ No newline at end of file diff --git a/samples/server/petstore/undertow/src/main/resources/config/oauth/primary.crt b/samples/server/petstore/undertow/src/main/resources/config/oauth/primary.crt new file mode 100644 index 00000000000..51ee3649759 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/resources/config/oauth/primary.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDmzCCAoOgAwIBAgIEHnAgtDANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJDQTEQMA4GA1UE +CBMHT250YXJpbzEUMBIGA1UEBxMLTWlzc2lzc2F1Z2ExJjAkBgNVBAoTHU5ldHdvcmsgTmV3IFRl +Y2hub2xvZ2llcyBJbmMuMQwwCgYDVQQLEwNERVYxETAPBgNVBAMTCFN0ZXZlIEh1MB4XDTE2MDkw +MTE2MTYxNVoXDTI2MDcxMTE2MTYxNVowfjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8x +FDASBgNVBAcTC01pc3Npc3NhdWdhMSYwJAYDVQQKEx1OZXR3b3JrIE5ldyBUZWNobm9sb2dpZXMg +SW5jLjEMMAoGA1UECxMDREVWMREwDwYDVQQDEwhTdGV2ZSBIdTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALrlxMtDb60DogElf4TBz504tRheZimAE0dJL/Yby4nacJdqvc5l4z+WWpDf +rI9krQ2Yi9yvhwAP+PrR6gWcIqWP4cpNE7XIAUDgr4CtyI7CptT/lpjtbkz4DGCMmaeDn0jqHqJt +SeSZGfwVu5zAGm8n4sHatjnnxBI/iWzkTII3V4xv0WeK37szNTEd+ly2ag7n2IV5zNnYmqZTeMQm +J2ENS+IwAG3ENtiVtrVTx/2bGtqutJjtdxsN58/cUG/guRyMT6OPI8Yi3ZzevdvRbxadyhEl/Kaw +6vJcdxmJI3tp4lx+p6sAxOWa7aapJe4JxutAQqzv0GKdVjoHKQ1wB60CAwEAAaMhMB8wHQYDVR0O +BBYEFIPF9SBd06RWU1eDL73CKfy01lavMA0GCSqGSIb3DQEBCwUAA4IBAQAoaKZGOak3Upz/ordF +slZoJuZlCu7jnKQEjYwHf3DNxcd1WmgFPtMcna6pW0VUxPIfidEA6VCMsGoK1RvshB0SjrRdCht6 +5qPXs9kV3NW0WvMiwDSYZZ9HgaZ9efTe5E9Fzc7ltKrE43L6k8NJcaEEWEdpdjFbrAqH4I+j/Vro +K3OhIo062fXjas5ipL4gF+3ECImjWzirQP8UiAfM0/36x7rtAu3btH/qI9hSyx39LBPPE5AsDJZ4 +dSMwNTW1gqmBAZIj+zQ/RD5dyWfPwON7Q+t96YbK6WBuYo0xy+I+PjcUgrWYWP3N24hlq8ZBIei+ +BudoEVJlIlmS0aRCuP8n +-----END CERTIFICATE----- diff --git a/samples/server/petstore/undertow/src/main/resources/config/security.json b/samples/server/petstore/undertow/src/main/resources/config/security.json new file mode 100644 index 00000000000..400070d0a2d --- /dev/null +++ b/samples/server/petstore/undertow/src/main/resources/config/security.json @@ -0,0 +1,13 @@ +{ + "description": "security configuration", + "enableVerifyJwt": false, + "jwt": { + "certificate": [ + "oauth/primary.crt" + ], + "clockSkewInSeconds": 60 + }, + "logJwtToken": true, + "logClientUserScope": false, + "enableVerifyScope": true +} \ No newline at end of file diff --git a/samples/server/petstore/undertow/src/main/resources/config/server.json b/samples/server/petstore/undertow/src/main/resources/config/server.json new file mode 100644 index 00000000000..14d16ce289a --- /dev/null +++ b/samples/server/petstore/undertow/src/main/resources/config/server.json @@ -0,0 +1,5 @@ +{ + "description": "server config", + "ip": "0.0.0.0", + "port": 8080 +} diff --git a/samples/server/petstore/undertow/src/main/resources/config/swagger.json b/samples/server/petstore/undertow/src/main/resources/config/swagger.json new file mode 100644 index 00000000000..3e0f26ec144 --- /dev/null +++ b/samples/server/petstore/undertow/src/main/resources/config/swagger.json @@ -0,0 +1,864 @@ +{ + "swagger" : "2.0", + "info" : { + "description" : "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version" : "1.0.0", + "title" : "Swagger Petstore", + "termsOfService" : "http://swagger.io/terms/", + "contact" : { + "email" : "apiteam@swagger.io" + }, + "license" : { + "name" : "Apache 2.0", + "url" : "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host" : "petstore.swagger.io", + "basePath" : "/v2", + "tags" : [ { + "name" : "pet", + "description" : "Everything about your Pets", + "externalDocs" : { + "description" : "Find out more", + "url" : "http://swagger.io" + } + }, { + "name" : "store", + "description" : "Access to Petstore orders" + }, { + "name" : "user", + "description" : "Operations about user", + "externalDocs" : { + "description" : "Find out more about our store", + "url" : "http://swagger.io" + } + } ], + "schemes" : [ "http" ], + "paths" : { + "/pet" : { + "post" : { + "tags" : [ "pet" ], + "summary" : "Add a new pet to the store", + "description" : "", + "operationId" : "addPet", + "consumes" : [ "application/json", "application/xml" ], + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "Pet object that needs to be added to the store", + "required" : true, + "schema" : { + "$ref" : "#/definitions/Pet" + } + } ], + "responses" : { + "405" : { + "description" : "Invalid input" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + }, + "put" : { + "tags" : [ "pet" ], + "summary" : "Update an existing pet", + "description" : "", + "operationId" : "updatePet", + "consumes" : [ "application/json", "application/xml" ], + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "Pet object that needs to be added to the store", + "required" : true, + "schema" : { + "$ref" : "#/definitions/Pet" + } + } ], + "responses" : { + "400" : { + "description" : "Invalid ID supplied" + }, + "404" : { + "description" : "Pet not found" + }, + "405" : { + "description" : "Validation exception" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/pet/findByStatus" : { + "get" : { + "tags" : [ "pet" ], + "summary" : "Finds Pets by status", + "description" : "Multiple status values can be provided with comma separated strings", + "operationId" : "findPetsByStatus", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "status", + "in" : "query", + "description" : "Status values that need to be considered for filter", + "required" : true, + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "available", "pending", "sold" ], + "default" : "available" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Pet" + } + } + }, + "400" : { + "description" : "Invalid status value" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/pet/findByTags" : { + "get" : { + "tags" : [ "pet" ], + "summary" : "Finds Pets by tags", + "description" : "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId" : "findPetsByTags", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "tags", + "in" : "query", + "description" : "Tags to filter by", + "required" : true, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/Pet" + } + } + }, + "400" : { + "description" : "Invalid tag value" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "deprecated" : true, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/pet/{petId}" : { + "get" : { + "tags" : [ "pet" ], + "summary" : "Find pet by ID", + "description" : "Returns a single pet", + "operationId" : "getPetById", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "petId", + "in" : "path", + "description" : "ID of pet to return", + "required" : true, + "type" : "integer", + "format" : "int64" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/Pet" + } + }, + "400" : { + "description" : "Invalid ID supplied" + }, + "404" : { + "description" : "Pet not found" + } + }, + "security" : [ { + "api_key" : [ ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + }, + "post" : { + "tags" : [ "pet" ], + "summary" : "Updates a pet in the store with form data", + "description" : "", + "operationId" : "updatePetWithForm", + "consumes" : [ "application/x-www-form-urlencoded" ], + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "petId", + "in" : "path", + "description" : "ID of pet that needs to be updated", + "required" : true, + "type" : "integer", + "format" : "int64" + }, { + "name" : "name", + "in" : "formData", + "description" : "Updated name of the pet", + "required" : false, + "type" : "string" + }, { + "name" : "status", + "in" : "formData", + "description" : "Updated status of the pet", + "required" : false, + "type" : "string" + } ], + "responses" : { + "405" : { + "description" : "Invalid input" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/x-www-form-urlencoded" + }, + "delete" : { + "tags" : [ "pet" ], + "summary" : "Deletes a pet", + "description" : "", + "operationId" : "deletePet", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "api_key", + "in" : "header", + "required" : false, + "type" : "string" + }, { + "name" : "petId", + "in" : "path", + "description" : "Pet id to delete", + "required" : true, + "type" : "integer", + "format" : "int64" + } ], + "responses" : { + "400" : { + "description" : "Invalid ID supplied" + }, + "404" : { + "description" : "Pet not found" + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/pet/{petId}/uploadImage" : { + "post" : { + "tags" : [ "pet" ], + "summary" : "uploads an image", + "description" : "", + "operationId" : "uploadFile", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "petId", + "in" : "path", + "description" : "ID of pet to update", + "required" : true, + "type" : "integer", + "format" : "int64" + }, { + "name" : "additionalMetadata", + "in" : "formData", + "description" : "Additional data to pass to server", + "required" : false, + "type" : "string" + }, { + "name" : "file", + "in" : "formData", + "description" : "file to upload", + "required" : false, + "type" : "file" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ApiResponse" + } + } + }, + "security" : [ { + "petstore_auth" : [ "write:pets", "read:pets" ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "multipart/form-data" + } + }, + "/store/inventory" : { + "get" : { + "tags" : [ "store" ], + "summary" : "Returns pet inventories by status", + "description" : "Returns a map of status codes to quantities", + "operationId" : "getInventory", + "produces" : [ "application/json" ], + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "integer", + "format" : "int32" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + } ], + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/store/order" : { + "post" : { + "tags" : [ "store" ], + "summary" : "Place an order for a pet", + "description" : "", + "operationId" : "placeOrder", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "order placed for purchasing the pet", + "required" : true, + "schema" : { + "$ref" : "#/definitions/Order" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/Order" + } + }, + "400" : { + "description" : "Invalid Order" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/store/order/{orderId}" : { + "get" : { + "tags" : [ "store" ], + "summary" : "Find purchase order by ID", + "description" : "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", + "operationId" : "getOrderById", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "orderId", + "in" : "path", + "description" : "ID of pet that needs to be fetched", + "required" : true, + "type" : "integer", + "maximum" : 10.0, + "minimum" : 1.0, + "format" : "int64" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/Order" + } + }, + "400" : { + "description" : "Invalid ID supplied" + }, + "404" : { + "description" : "Order not found" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + }, + "delete" : { + "tags" : [ "store" ], + "summary" : "Delete purchase order by ID", + "description" : "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", + "operationId" : "deleteOrder", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "orderId", + "in" : "path", + "description" : "ID of the order that needs to be deleted", + "required" : true, + "type" : "integer", + "minimum" : 1.0, + "format" : "int64" + } ], + "responses" : { + "400" : { + "description" : "Invalid ID supplied" + }, + "404" : { + "description" : "Order not found" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user" : { + "post" : { + "tags" : [ "user" ], + "summary" : "Create user", + "description" : "This can only be done by the logged in user.", + "operationId" : "createUser", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "Created user object", + "required" : true, + "schema" : { + "$ref" : "#/definitions/User" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user/createWithArray" : { + "post" : { + "tags" : [ "user" ], + "summary" : "Creates list of users with given input array", + "description" : "", + "operationId" : "createUsersWithArrayInput", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "List of user object", + "required" : true, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/User" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user/createWithList" : { + "post" : { + "tags" : [ "user" ], + "summary" : "Creates list of users with given input array", + "description" : "", + "operationId" : "createUsersWithListInput", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "description" : "List of user object", + "required" : true, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/User" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user/login" : { + "get" : { + "tags" : [ "user" ], + "summary" : "Logs user into the system", + "description" : "", + "operationId" : "loginUser", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "query", + "description" : "The user name for login", + "required" : true, + "type" : "string" + }, { + "name" : "password", + "in" : "query", + "description" : "The password for login in clear text", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "string" + }, + "headers" : { + "X-Rate-Limit" : { + "type" : "integer", + "format" : "int32", + "description" : "calls per hour allowed by the user" + }, + "X-Expires-After" : { + "type" : "string", + "format" : "date-time", + "description" : "date in UTC when token expires" + } + } + }, + "400" : { + "description" : "Invalid username/password supplied" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user/logout" : { + "get" : { + "tags" : [ "user" ], + "summary" : "Logs out current logged in user session", + "description" : "", + "operationId" : "logoutUser", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + }, + "/user/{username}" : { + "get" : { + "tags" : [ "user" ], + "summary" : "Get user by user name", + "description" : "", + "operationId" : "getUserByName", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "path", + "description" : "The name that needs to be fetched. Use user1 for testing. ", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/User" + } + }, + "400" : { + "description" : "Invalid username supplied" + }, + "404" : { + "description" : "User not found" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + }, + "put" : { + "tags" : [ "user" ], + "summary" : "Updated user", + "description" : "This can only be done by the logged in user.", + "operationId" : "updateUser", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "path", + "description" : "name that need to be updated", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "description" : "Updated user object", + "required" : true, + "schema" : { + "$ref" : "#/definitions/User" + } + } ], + "responses" : { + "400" : { + "description" : "Invalid user supplied" + }, + "404" : { + "description" : "User not found" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + }, + "delete" : { + "tags" : [ "user" ], + "summary" : "Delete user", + "description" : "This can only be done by the logged in user.", + "operationId" : "deleteUser", + "produces" : [ "application/xml", "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "path", + "description" : "The name that needs to be deleted", + "required" : true, + "type" : "string" + } ], + "responses" : { + "400" : { + "description" : "Invalid username supplied" + }, + "404" : { + "description" : "User not found" + } + }, + "x-accepts" : "application/json", + "x-contentType" : "application/json" + } + } + }, + "securityDefinitions" : { + "petstore_auth" : { + "type" : "oauth2", + "authorizationUrl" : "http://petstore.swagger.io/oauth/dialog", + "flow" : "implicit", + "scopes" : { + "write:pets" : "modify pets in your account", + "read:pets" : "read your pets" + } + }, + "api_key" : { + "type" : "apiKey", + "name" : "api_key", + "in" : "header" + } + }, + "definitions" : { + "Order" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64" + }, + "petId" : { + "type" : "integer", + "format" : "int64" + }, + "quantity" : { + "type" : "integer", + "format" : "int32" + }, + "shipDate" : { + "type" : "string", + "format" : "date-time" + }, + "status" : { + "type" : "string", + "description" : "Order Status", + "enum" : [ "placed", "approved", "delivered" ] + }, + "complete" : { + "type" : "boolean", + "default" : false + } + }, + "xml" : { + "name" : "Order" + } + }, + "Category" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64" + }, + "name" : { + "type" : "string" + } + }, + "xml" : { + "name" : "Category" + } + }, + "User" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64" + }, + "username" : { + "type" : "string" + }, + "firstName" : { + "type" : "string" + }, + "lastName" : { + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "password" : { + "type" : "string" + }, + "phone" : { + "type" : "string" + }, + "userStatus" : { + "type" : "integer", + "format" : "int32", + "description" : "User Status" + } + }, + "xml" : { + "name" : "User" + } + }, + "Tag" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64" + }, + "name" : { + "type" : "string" + } + }, + "xml" : { + "name" : "Tag" + } + }, + "ApiResponse" : { + "type" : "object", + "properties" : { + "code" : { + "type" : "integer", + "format" : "int32" + }, + "type" : { + "type" : "string" + }, + "message" : { + "type" : "string" + } + } + }, + "Pet" : { + "type" : "object", + "required" : [ "name", "photoUrls" ], + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64" + }, + "category" : { + "$ref" : "#/definitions/Category" + }, + "name" : { + "type" : "string", + "example" : "doggie" + }, + "photoUrls" : { + "type" : "array", + "xml" : { + "name" : "photoUrl", + "wrapped" : true + }, + "items" : { + "type" : "string" + } + }, + "tags" : { + "type" : "array", + "xml" : { + "name" : "tag", + "wrapped" : true + }, + "items" : { + "$ref" : "#/definitions/Tag" + } + }, + "status" : { + "type" : "string", + "description" : "pet status in the store", + "enum" : [ "available", "pending", "sold" ] + } + }, + "xml" : { + "name" : "Pet" + } + } + }, + "externalDocs" : { + "description" : "Find out more about Swagger", + "url" : "http://swagger.io" + } +} \ No newline at end of file