From 1df3ed44870db1906a5f1c97a19fd11b23bb7db3 Mon Sep 17 00:00:00 2001 From: Tony Tam Date: Sat, 6 Jun 2015 23:44:20 -0700 Subject: [PATCH] repackaged --- .../io/swagger/codegen/SwaggerCodegen.java | 37 ++++ .../io/swagger/codegen/cmd/ConfigHelp.java | 49 +++++ .../java/io/swagger/codegen/cmd/Generate.java | 156 ++++++++++++++++ .../java/io/swagger/codegen/cmd/Langs.java | 23 +++ .../java/io/swagger/codegen/cmd/Meta.java | 144 +++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 24 +++ .../java/io/swagger/generator/Bootstrap.java | 45 +++++ .../generator/DynamicSwaggerConfig.java | 69 ++++++++ .../generator/exception/ApiException.java | 25 +++ .../exception/BadRequestException.java | 25 +++ .../exception/NotFoundException.java | 25 +++ .../swagger/generator/model/ApiResponse.java | 84 +++++++++ .../io/swagger/generator/model/Generated.java | 36 ++++ .../generator/model/GeneratorInput.java | 44 +++++ .../swagger/generator/model/InputOption.java | 65 +++++++ .../swagger/generator/model/ResponseCode.java | 26 +++ .../swagger/generator/online/Generator.java | 167 ++++++++++++++++++ .../generator/resource/ExceptionWriter.java | 50 ++++++ .../generator/resource/SwaggerResource.java | 138 +++++++++++++++ .../generator/util/ApiOriginFilter.java | 42 +++++ .../generator/util/ValidationException.java | 27 +++ .../generator/util/ValidationMessage.java | 26 +++ .../io/swagger/generator/util/ZipUtil.java | 124 +++++++++++++ 23 files changed, 1451 insertions(+) create mode 100644 modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/SwaggerCodegen.java create mode 100644 modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/ConfigHelp.java create mode 100644 modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java create mode 100644 modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Langs.java create mode 100644 modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Meta.java create mode 100644 modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/Bootstrap.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/DynamicSwaggerConfig.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/exception/ApiException.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/exception/BadRequestException.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/exception/NotFoundException.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/model/ApiResponse.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/model/Generated.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/model/GeneratorInput.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/model/InputOption.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/model/ResponseCode.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/online/Generator.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/resource/ExceptionWriter.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/resource/SwaggerResource.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/util/ApiOriginFilter.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationException.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationMessage.java create mode 100644 modules/swagger-generator/src/main/java/io/swagger/generator/util/ZipUtil.java diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/SwaggerCodegen.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/SwaggerCodegen.java new file mode 100644 index 00000000000..62f0b5cb7e2 --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/SwaggerCodegen.java @@ -0,0 +1,37 @@ +package io.swagger.codegen; + +import io.swagger.codegen.cmd.ConfigHelp; +import io.swagger.codegen.cmd.Generate; +import io.swagger.codegen.cmd.Langs; +import io.swagger.codegen.cmd.Meta; +import io.airlift.airline.Cli; +import io.airlift.airline.Help; + +/** + * User: lanwen + * Date: 24.03.15 + * Time: 17:56 + * + * Command line interface for swagger codegen + * use `swagger-codegen-cli.jar help` for more info + * + * @since 2.1.3-M1 + */ +public class SwaggerCodegen { + + + public static void main(String[] args) { + Cli.CliBuilder builder = Cli.builder("swagger") + .withDescription("Swagger code generator CLI. More info on swagger.io") + .withDefaultCommand(Langs.class) + .withCommands( + Generate.class, + Meta.class, + Langs.class, + Help.class, + ConfigHelp.class + ); + + builder.build().parse(args).run(); + } +} diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/ConfigHelp.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/ConfigHelp.java new file mode 100644 index 00000000000..54fbfac6e7a --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/ConfigHelp.java @@ -0,0 +1,49 @@ +package io.swagger.codegen.cmd; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import java.util.ServiceLoader; +import static java.util.ServiceLoader.load; + +@Command(name = "config-help", description = "Config help for chosen lang") +public class ConfigHelp implements Runnable { + + @Option(name = {"-l", "--lang"}, title = "language", required = true, + description = "language to get config help for") + private String lang; + + @Override + public void run() { + System.out.println(); + CodegenConfig config = forName(lang); + System.out.println("CONFIG OPTIONS"); + for (CliOption langCliOption : config.cliOptions()) { + System.out.println("\t" + langCliOption.getOpt()); + System.out.println("\t " + langCliOption.getDescription()); + System.out.println(); + } + } + + /** + * Tries to load config class with SPI first, then with class name directly from classpath + * @param name name of config, or full qualified class name in classpath + * @return config class + */ + private static CodegenConfig forName(String name) { + ServiceLoader loader = load(CodegenConfig.class); + for (CodegenConfig config : loader) { + if (config.getName().equals(name)) { + return config; + } + } + + // else try to load directly + try { + return (CodegenConfig) Class.forName(name).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Can't load config class with name ".concat(name), e); + } + } +} diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java new file mode 100644 index 00000000000..497cba64511 --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Generate.java @@ -0,0 +1,156 @@ +package io.swagger.codegen.cmd; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.ClientOptInput; +import io.swagger.codegen.ClientOpts; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.DefaultGenerator; +import io.swagger.models.Swagger; +import config.Config; +import config.ConfigParser; +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import io.swagger.parser.SwaggerParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ServiceLoader; + +import static java.util.ServiceLoader.load; +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +/** + * User: lanwen + * Date: 24.03.15 + * Time: 20:22 + */ + +@Command(name = "generate", description = "Generate code with chosen lang") +public class Generate implements Runnable { + + public static final Logger LOG = LoggerFactory.getLogger(Generate.class); + + public static final String TEMPLATE_DIR_PARAM = "templateDir"; + + @Option(name = {"-v", "--verbose"}, description = "verbose mode") + private boolean verbose; + + @Option(name = {"-l", "--lang"}, title = "language", required = true, + description = "client language to generate (maybe class name in classpath, required)") + private String lang; + + @Option(name = {"-o", "--output"}, title = "output directory", + description = "where to write the generated files (current dir by default)") + private String output = ""; + + @Option(name = {"-i", "--input-spec"}, title = "spec file", required = true, + description = "location of the swagger spec, as URL or file (required)") + private String spec; + + @Option(name = {"-t", "--template-dir"}, title = "template directory", + description = "folder containing the template files") + private String templateDir; + + @Option(name = {"-a", "--auth"}, title = "authorization", + description = "adds authorization headers when fetching the swagger definitions remotely. " + + "Pass in a URL-encoded string of name:header with a comma separating multiple values") + private String auth; + + @Option( name= {"-D"}, title = "system properties", description = "sets specified system properties in " + + "the format of name=value,name=value") + private String systemProperties; + + @Option( name= {"-c", "--config"}, title = "configuration file", description = "Path to json configuration file. " + + "File content should be in a json format {\"optionKey\":\"optionValue\", \"optionKey1\":\"optionValue1\"...} " + + "Supported options can be different for each language. Run config-help -l {lang} command for language specific config options.") + private String configFile; + + @Override + public void run() { + verbosed(verbose); + + setSystemProperties(); + + ClientOptInput input = new ClientOptInput(); + + if (isNotEmpty(auth)) { + input.setAuth(auth); + } + + CodegenConfig config = forName(lang); + config.setOutputDir(new File(output).getAbsolutePath()); + + if (null != templateDir) { + config.additionalProperties().put(TEMPLATE_DIR_PARAM, new File(templateDir).getAbsolutePath()); + } + + if(null != configFile){ + Config genConfig = ConfigParser.read(configFile); + if (null != genConfig) { + for (CliOption langCliOption : config.cliOptions()) { + if (genConfig.hasOption(langCliOption.getOpt())) { + config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt())); + } + } + } + } + + input.setConfig(config); + + Swagger swagger = new SwaggerParser().read(spec, input.getAuthorizationValues(), true); + new DefaultGenerator().opts(input.opts(new ClientOpts()).swagger(swagger)).generate(); + } + + private void setSystemProperties() { + if( systemProperties != null && systemProperties.length() > 0 ){ + for( String property : systemProperties.split(",")) { + int ix = property.indexOf('='); + if( ix > 0 && ix < property.length()-1 ){ + System.setProperty( property.substring(0, ix), property.substring(ix+1) ); + } + } + } + } + + /** + * If true parameter, adds system properties which enables debug mode in generator + * @param verbose - if true, enables debug mode + */ + private void verbosed(boolean verbose) { + if (!verbose) { + return; + } + LOG.info("\nVERBOSE MODE: ON. Additional debug options are injected" + + "\n - [debugSwagger] prints the swagger specification as interpreted by the codegen" + + "\n - [debugModels] prints models passed to the template engine" + + "\n - [debugOperations] prints operations passed to the template engine" + + "\n - [debugSupportingFiles] prints additional data passed to the template engine"); + + System.setProperty("debugSwagger", ""); + System.setProperty("debugModels", ""); + System.setProperty("debugOperations", ""); + System.setProperty("debugSupportingFiles", ""); + } + + /** + * Tries to load config class with SPI first, then with class name directly from classpath + * @param name name of config, or full qualified class name in classpath + * @return config class + */ + private static CodegenConfig forName(String name) { + ServiceLoader loader = load(CodegenConfig.class); + for (CodegenConfig config : loader) { + if (config.getName().equals(name)) { + return config; + } + } + + // else try to load directly + try { + return (CodegenConfig) Class.forName(name).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Can't load config class with name ".concat(name), e); + } + } +} diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Langs.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Langs.java new file mode 100644 index 00000000000..5627b6c7ac8 --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Langs.java @@ -0,0 +1,23 @@ +package io.swagger.codegen.cmd; + +import ch.lambdaj.collection.LambdaIterable; +import io.swagger.codegen.CodegenConfig; +import io.airlift.airline.Command; + +import static ch.lambdaj.Lambda.on; +import static ch.lambdaj.collection.LambdaCollections.with; +import static java.util.ServiceLoader.load; + +/** + * User: lanwen + * Date: 24.03.15 + * Time: 20:25 + */ +@Command(name = "langs", description = "Shows available langs") +public class Langs implements Runnable { + @Override + public void run() { + LambdaIterable langs = with(load(CodegenConfig.class)).extract(on(CodegenConfig.class).getName()); + System.out.printf("Available languages: %s%n", langs); + } +} diff --git a/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Meta.java b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Meta.java new file mode 100644 index 00000000000..4a875b7199e --- /dev/null +++ b/modules/swagger-codegen-cli/src/main/java/io/swagger/codegen/cmd/Meta.java @@ -0,0 +1,144 @@ +package io.swagger.codegen.cmd; + +import ch.lambdaj.function.convert.Converter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache; +import io.swagger.codegen.DefaultGenerator; +import io.swagger.codegen.SupportingFile; +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import java.util.Map; + +import static ch.lambdaj.collection.LambdaCollections.with; +import static com.google.common.base.Joiner.on; + +/** + * User: lanwen + * Date: 24.03.15 + * Time: 20:22 + */ + +@Command(name = "meta", description = "MetaGenerator. Generator for creating a new template set " + + "and configuration for Codegen. The output will be based on the language you " + + "specify, and includes default templates to include.") +public class Meta implements Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(Meta.class); + + private static final String TEMPLATE_DIR_CLASSPATH = "codegen"; + private static final String MUSTACHE_EXTENSION = ".mustache"; + + @Option(name = {"-o", "--output"}, title = "output directory", + description = "where to write the generated files (current dir by default)") + private String outputFolder = ""; + + @Option(name = {"-n", "--name"}, title = "name", + description = "the human-readable name of the generator") + private String name = "default"; + + @Option(name = {"-p", "--package"}, title = "package", + description = "the package to put the main class into (defaults to io.swagger.codegen)") + private String targetPackage = "io.swagger.codegen"; + + @Override + public void run() { + final File targetDir = new File(outputFolder); + LOG.info("writing to folder [{}]", targetDir.getAbsolutePath()); + + String mainClass = StringUtils.capitalize(name) + "Generator"; + + List supportingFiles = ImmutableList.of( + new SupportingFile("pom.mustache", "", "pom.xml"), + new SupportingFile("generatorClass.mustache", + on(File.separator).join("src/main/java", asPath(targetPackage)), mainClass.concat(".java")), + new SupportingFile("README.mustache", "", "README.md"), + new SupportingFile("api.template", "src/main/resources" + File.separator + name, "api.mustache"), + new SupportingFile("model.template", "src/main/resources" + File.separator + name, "model.mustache"), + new SupportingFile("services.mustache", + "src/main/resources/META-INF/services", "io.swagger.codegen.CodegenConfig") + ); + + Map data = new ImmutableMap.Builder() + .put("generatorPackage", targetPackage) + .put("generatorClass", mainClass) + .put("name", name) + .put("fullyQualifiedGeneratorClass", targetPackage + "." + mainClass).build(); + + + with(supportingFiles).convert(processFiles(targetDir, data)); + } + + /** + * Converter method to process supporting files: execute with mustache, + * or simply copy to destination directory + * @param targetDir - destination directory + * @param data - map with additional params needed to process templates + * @return converter object to pass to lambdaj + */ + private Converter processFiles(final File targetDir, final Map data) { + return new Converter() { + private DefaultGenerator generator = new DefaultGenerator(); + + @Override + public File convert(SupportingFile support) { + try { + File destinationFolder = new File(new File(targetDir.getAbsolutePath()), support.folder); + File outputFile = new File(destinationFolder, support.destinationFilename); + + String template = generator + .readTemplate(new File(TEMPLATE_DIR_CLASSPATH, support.templateFile).getPath()); + String formatted = template; + + if (support.templateFile.endsWith(MUSTACHE_EXTENSION)) { + LOG.info("writing file to {}", outputFile.getAbsolutePath()); + formatted = Mustache.compiler().withLoader(loader(generator)) + .defaultValue("") + .compile(template) + .execute(data); + } else { + LOG.info("copying file to {}", outputFile.getAbsolutePath()); + } + + FileUtils.writeStringToFile(outputFile, formatted); + return outputFile; + + } catch (IOException e) { + throw new RuntimeException("Can't generate project", e); + } + } + }; + } + + /** + * Creates mustache loader for template using classpath loader + * @param generator - class with reader getter + * @return loader for template + */ + private Mustache.TemplateLoader loader(final DefaultGenerator generator) { + return new Mustache.TemplateLoader() { + public Reader getTemplate(String name) { + return generator.getTemplateReader(TEMPLATE_DIR_CLASSPATH + + File.separator + name.concat(MUSTACHE_EXTENSION)); + } + }; + } + + /** + * Converts package name to path on file system + * @param packageName - package name to convert + * @return relative path + */ + private String asPath(String packageName) { + return packageName.replace(".", File.separator); + } +} 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 new file mode 100644 index 00000000000..8bbdbc8d140 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -0,0 +1,24 @@ +io.swagger.codegen.languages.AndroidClientCodegen +io.swagger.codegen.languages.AsyncScalaClientCodegen +io.swagger.codegen.languages.CSharpClientCodegen +io.swagger.codegen.languages.JavaClientCodegen +io.swagger.codegen.languages.JaxRSServerCodegen +io.swagger.codegen.languages.NodeJSServerCodegen +io.swagger.codegen.languages.ObjcClientCodegen +io.swagger.codegen.languages.PerlClientCodegen +io.swagger.codegen.languages.PhpClientCodegen +io.swagger.codegen.languages.PythonClientCodegen +io.swagger.codegen.languages.Python3ClientCodegen +io.swagger.codegen.languages.Qt5CPPGenerator +io.swagger.codegen.languages.RetrofitClientCodegen +io.swagger.codegen.languages.RubyClientCodegen +io.swagger.codegen.languages.ScalaClientCodegen +io.swagger.codegen.languages.ScalatraServerCodegen +io.swagger.codegen.languages.SpringMVCServerCodegen +io.swagger.codegen.languages.StaticDocCodegen +io.swagger.codegen.languages.StaticHtmlGenerator +io.swagger.codegen.languages.SwaggerGenerator +io.swagger.codegen.languages.SwaggerYamlGenerator +io.swagger.codegen.languages.SwiftGenerator +io.swagger.codegen.languages.TizenClientCodegen +io.swagger.codegen.languages.AkkaScalaClientCodegen diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/Bootstrap.java b/modules/swagger-generator/src/main/java/io/swagger/generator/Bootstrap.java new file mode 100644 index 00000000000..8a5d0bcb324 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/Bootstrap.java @@ -0,0 +1,45 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator; + +import io.swagger.models.*; + +import javax.servlet.http.HttpServlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +public class Bootstrap extends HttpServlet { + public void init(ServletConfig config) throws ServletException { + ServletContext context = config.getServletContext(); + + DynamicSwaggerConfig bc = new DynamicSwaggerConfig(); + bc.setBasePath("/api"); + bc.setTitle("Swagger Generator"); + bc.setDescription("This is an online swagger codegen server. You can find out more " + + "at https://github.com/swagger-api/swagger-codegen or on irc.freenode.net, #swagger." + + "http://helloreverb.com/terms/"); + bc.setTermsOfServiceUrl("http://helloreverb.com/terms/"); + bc.setContact("apiteam@swagger.io"); + bc.setLicense("Apache 2.0"); + bc.setVersion("1.0.0"); + bc.setHost("generator.swagger.io"); + bc.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html"); + bc.setResourcePackage("io.swagger.generator.resource"); + bc.setScan(true); + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/DynamicSwaggerConfig.java b/modules/swagger-generator/src/main/java/io/swagger/generator/DynamicSwaggerConfig.java new file mode 100644 index 00000000000..5cdc75ed9f5 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/DynamicSwaggerConfig.java @@ -0,0 +1,69 @@ +package io.swagger.generator; + +import io.swagger.models.*; +import io.swagger.models.parameters.*; +import io.swagger.models.properties.*; +import io.swagger.codegen.*; + +import io.swagger.util.Json; + +import io.swagger.jaxrs.config.BeanConfig; + +import java.util.*; + +public class DynamicSwaggerConfig extends BeanConfig { + static List clients = new ArrayList(); + static List servers = new ArrayList(); + static { + List extensions = Codegen.getExtensions(); + for(CodegenConfig config : extensions) { + if(config.getTag().equals(CodegenType.CLIENT) || config.getTag().equals(CodegenType.DOCUMENTATION)) { + clients.add(config.getName()); + } + else if(config.getTag().equals(CodegenType.SERVER)) { + servers.add(config.getName()); + } + } + } + + @Override + public Swagger configure(Swagger swagger) { + Path clientPath = swagger.getPaths().get("/gen/clients/{language}"); + // update the path description based on what clients are available via SPI + if(clientPath != null) { + Operation post = clientPath.getPost(); + Parameter framework = post.getParameters().get(0); + if(framework instanceof PathParameter) { + PathParameter param = (PathParameter) framework; + StringBuilder b = new StringBuilder(); + for(String client : clients) { + if(b.toString().length() > 0) + b.append(", "); + b.append(client); + } + param.setDescription("available clients: " + b.toString()); + } + } + + Path serverPath = swagger.getPaths().get("/gen/servers/{framework}"); + // update the path description based on what servers are available via SPI + if(serverPath != null) { + Operation post = serverPath.getPost(); + Parameter framework = post.getParameters().get(0); + if(framework instanceof PathParameter) { + PathParameter param = (PathParameter) framework; + StringBuilder b = new StringBuilder(); + for(String server : servers) { + if(b.toString().length() > 0) + b.append(", "); + b.append(server); + } + param.setDescription("available clients: " + b.toString()); + } + } + + return swagger.info(getInfo()) + .host(getHost()) + .basePath("/api"); + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/exception/ApiException.java b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/ApiException.java new file mode 100644 index 00000000000..1ed3e84af41 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/ApiException.java @@ -0,0 +1,25 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.exception; + +public class ApiException extends Exception{ + private int code; + public ApiException (int code, String msg) { + super(msg); + this.code = code; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/exception/BadRequestException.java b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/BadRequestException.java new file mode 100644 index 00000000000..70db17379e6 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/BadRequestException.java @@ -0,0 +1,25 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.exception; + +public class BadRequestException extends ApiException { + private int code; + public BadRequestException (int code, String msg) { + super(code, msg); + this.code = code; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/exception/NotFoundException.java b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/NotFoundException.java new file mode 100644 index 00000000000..119a7307437 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/exception/NotFoundException.java @@ -0,0 +1,25 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.exception; + +public class NotFoundException extends ApiException { + private int code; + public NotFoundException (int code, String msg) { + super(code, msg); + this.code = code; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/model/ApiResponse.java b/modules/swagger-generator/src/main/java/io/swagger/generator/model/ApiResponse.java new file mode 100644 index 00000000000..88661f45bf5 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/model/ApiResponse.java @@ -0,0 +1,84 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.model; + +import javax.xml.bind.annotation.XmlTransient; + +@javax.xml.bind.annotation.XmlRootElement +public class ApiResponse { + public static final int ERROR = 1; + public static final int WARNING = 2; + public static final int INFO = 3; + public static final int OK = 4; + public static final int TOO_BUSY = 5; + + int code; + String type; + String message; + + public ApiResponse(){} + + public ApiResponse(int code, String message){ + this.code = code; + switch(code){ + case ERROR: + setType("error"); + break; + case WARNING: + setType("warning"); + break; + case INFO: + setType("info"); + break; + case OK: + setType("ok"); + break; + case TOO_BUSY: + setType("too busy"); + break; + default: + setType("unknown"); + break; + } + this.message = message; + } + + @XmlTransient + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/model/Generated.java b/modules/swagger-generator/src/main/java/io/swagger/generator/model/Generated.java new file mode 100644 index 00000000000..95786cf8b76 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/model/Generated.java @@ -0,0 +1,36 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.model; + +public class Generated { + private String filename; + private String friendlyName; + + public String getFilename() { + return filename; + } + public void setFilename(String filename) { + this.filename = filename; + } + + public String getFriendlyName() { + return friendlyName; + } + public void setFriendlyName(String friendlyName) { + this.friendlyName = friendlyName; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/model/GeneratorInput.java b/modules/swagger-generator/src/main/java/io/swagger/generator/model/GeneratorInput.java new file mode 100644 index 00000000000..8adb1f3ecf0 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/model/GeneratorInput.java @@ -0,0 +1,44 @@ +package io.swagger.generator.model; + +import io.swagger.annotations.ApiModelProperty; +import io.swagger.models.auth.SecuritySchemeDefinition; + +import com.fasterxml.jackson.databind.*; + +import java.util.*; + +public class GeneratorInput { + private JsonNode spec; + private Map options; + private String swaggerUrl; + private SecuritySchemeDefinition auth; + + @ApiModelProperty(dataType="Object") + public JsonNode getSpec() { + return spec; + } + public void setSpec(JsonNode spec) { + this.spec = spec; + } + + public Map getOptions() { + return options; + } + public void setOptions(Map options) { + this.options = options; + } + + public String getSwaggerUrl() { + return swaggerUrl; + } + public void setSwaggerUrl(String url) { + this.swaggerUrl = url; + } + + public SecuritySchemeDefinition getSecurityDefinition() { + return auth; + } + public void setSecurityDefinition(SecuritySchemeDefinition auth) { + this.auth = auth; + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/model/InputOption.java b/modules/swagger-generator/src/main/java/io/swagger/generator/model/InputOption.java new file mode 100644 index 00000000000..6ed89a654e6 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/model/InputOption.java @@ -0,0 +1,65 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.model; + +public class InputOption { + private String name; + private String description; + private Boolean required; + private String defaultValue; + + public InputOption() {} + + public InputOption(String name, String description, String defaultValue, Boolean required) { + this.name = name; + this.description = description; + this.defaultValue = defaultValue; + this.required = required; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public Boolean getRequired() { + return required; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getDefaultValue() { + return defaultValue; + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/model/ResponseCode.java b/modules/swagger-generator/src/main/java/io/swagger/generator/model/ResponseCode.java new file mode 100644 index 00000000000..50da05250d9 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/model/ResponseCode.java @@ -0,0 +1,26 @@ +package io.swagger.generator.model; + +public class ResponseCode { + private String code; + private String link; + public ResponseCode() {} + + public ResponseCode(String code, String link) { + setCode(code); + setLink(link); + } + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + public String getLink() { + return link; + } + public void setLink(String link) { + this.link = link; + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/online/Generator.java b/modules/swagger-generator/src/main/java/io/swagger/generator/online/Generator.java new file mode 100644 index 00000000000..fd0abb37d6d --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/online/Generator.java @@ -0,0 +1,167 @@ +package io.swagger.generator.online; + +import io.swagger.parser.SwaggerParser; + +import io.swagger.generator.exception.*; +import io.swagger.codegen.*; +import io.swagger.models.Swagger; +import io.swagger.generator.model.*; +import io.swagger.util.Json; +import io.swagger.generator.util.ZipUtil; + +import com.fasterxml.jackson.databind.JsonNode; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.List; +import java.util.ArrayList; + +public class Generator { + static Logger LOGGER = LoggerFactory.getLogger(Generator.class); + + public static String generateClient(String language, GeneratorInput opts) throws ApiException { + Swagger swagger; + LOGGER.debug("generate client for " + language); + if(opts == null) { + throw new BadRequestException(400, "No options were supplied"); + } + JsonNode node = opts.getSpec(); + if(node == null) { + if(opts.getSwaggerUrl() != null) { + swagger = new SwaggerParser().read(opts.getSwaggerUrl()); + } + else + throw new BadRequestException(400, "No swagger specification was supplied"); + } + else { + swagger = new SwaggerParser().read(node); + } + if(swagger == null) { + throw new BadRequestException(400, "The swagger specification supplied was not valid"); + } + + ClientOptInput clientOptInput = new ClientOptInput(); + ClientOpts clientOpts = new ClientOpts(); + String outputFolder = getTmpFolder().getAbsolutePath() + File.separator + language + "-client"; + String outputFilename = outputFolder + "-bundle.zip"; + + clientOptInput + .opts(clientOpts) + .swagger(swagger); + + CodegenConfig codegenConfig = Codegen.getConfig(language); + if(codegenConfig == null) { + throw new BadRequestException(400, "Unsupported target " + language + " supplied"); + } + + codegenConfig.setOutputDir(outputFolder); + + Json.prettyPrint(clientOpts); + + clientOptInput.setConfig(codegenConfig); + + try{ + List files = new Codegen().opts(clientOptInput).generate(); + if(files.size() > 0) { + List filesToAdd = new ArrayList(); + System.out.println("adding to " + outputFolder); + filesToAdd.add(new File(outputFolder)); + ZipUtil zip = new ZipUtil(); + zip.compressFiles(filesToAdd, outputFilename); + } + else { + throw new BadRequestException(400, "A target generation was attempted, but no files were created!"); + } + } + catch (Exception e) { + throw new BadRequestException(500, "Unable to build target: " + e.getMessage()); + } + return outputFilename; + } + + public static String generateServer(String language, GeneratorInput opts) throws ApiException { + LOGGER.debug("generate server for " + language); + Swagger swagger; + if(opts == null) { + throw new BadRequestException(400, "No options were supplied"); + } + if(opts == null) { + throw new BadRequestException(400, "No options were supplied"); + } + JsonNode node = opts.getSpec(); + if(node == null) { + if(opts.getSwaggerUrl() != null) { + swagger = new SwaggerParser().read(opts.getSwaggerUrl()); + } + else + throw new BadRequestException(400, "No swagger specification was supplied"); + } + else { + swagger = new SwaggerParser().read(node); + } + if(swagger == null) { + throw new BadRequestException(400, "The swagger specification supplied was not valid"); + } + + ClientOptInput clientOptInput = new ClientOptInput(); + ClientOpts clientOpts = new ClientOpts(); + String outputFolder = getTmpFolder().getAbsolutePath() + File.separator + language + "-server"; + String outputFilename = outputFolder + "-bundle.zip"; + + clientOptInput + .opts(clientOpts) + .swagger(swagger); + + CodegenConfig codegenConfig = Codegen.getConfig(language); + if(codegenConfig == null) { + throw new BadRequestException(400, "Unsupported target " + language + " supplied"); + } + + codegenConfig.setOutputDir(outputFolder); + + Json.prettyPrint(clientOpts); + + clientOptInput.setConfig(codegenConfig); + + try{ + List files = new Codegen().opts(clientOptInput).generate(); + if(files.size() > 0) { + List filesToAdd = new ArrayList(); + filesToAdd.add(new File(outputFolder)); + ZipUtil zip = new ZipUtil(); + zip.compressFiles(filesToAdd, outputFilename); + } + else { + throw new BadRequestException(400, "A target generation was attempted, but no files were created!"); + } + } + catch (Exception e) { + throw new BadRequestException(500, "Unable to build target: " + e.getMessage()); + } + return outputFilename; + } + + public static InputOption clientOptions(String language) { + return null; + } + + public static InputOption serverOptions(String language) { + return null; + } + + protected static File getTmpFolder() { + try { + File outputFolder = File.createTempFile("codegen-", "-tmp"); + outputFolder.delete(); + outputFolder.mkdir(); + outputFolder.deleteOnExit(); + return outputFolder; + } + catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/resource/ExceptionWriter.java b/modules/swagger-generator/src/main/java/io/swagger/generator/resource/ExceptionWriter.java new file mode 100644 index 00000000000..2f680a7db07 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/resource/ExceptionWriter.java @@ -0,0 +1,50 @@ +package io.swagger.generator.resource; + +import io.swagger.generator.util.ValidationException; + +import io.swagger.generator.exception.ApiException; +import io.swagger.generator.exception.BadRequestException; +import io.swagger.generator.exception.NotFoundException; +import io.swagger.generator.model.ApiResponse; + +import javax.ws.rs.ext.*; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +@Provider +public class ExceptionWriter implements ExceptionMapper { + public Response toResponse(Exception exception) { + if (exception instanceof javax.ws.rs.WebApplicationException) { + javax.ws.rs.WebApplicationException e = (javax.ws.rs.WebApplicationException) exception; + return Response + .status(e.getResponse().getStatus()) + .entity(new ApiResponse(e.getResponse().getStatus(), + exception.getMessage())).build(); + } else if (exception instanceof com.fasterxml.jackson.core.JsonParseException) { + return Response.status(400) + .entity(new ApiResponse(400, "bad input")).build(); + } else if (exception instanceof ValidationException) { + ValidationException e = (ValidationException) exception; + return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } else if (exception instanceof NotFoundException) { + return Response + .status(Status.NOT_FOUND) + .entity(new ApiResponse(ApiResponse.ERROR, exception + .getMessage())).build(); + } else if (exception instanceof BadRequestException) { + return Response + .status(Status.BAD_REQUEST) + .entity(new ApiResponse(ApiResponse.ERROR, exception + .getMessage())).build(); + } else if (exception instanceof ApiException) { + return Response + .status(Status.BAD_REQUEST) + .entity(new ApiResponse(ApiResponse.ERROR, exception + .getMessage())).build(); + } else { + return Response.status(500) + .entity(new ApiResponse(500, "something bad happened")) + .build(); + } + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/resource/SwaggerResource.java b/modules/swagger-generator/src/main/java/io/swagger/generator/resource/SwaggerResource.java new file mode 100644 index 00000000000..e591efb1b37 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/resource/SwaggerResource.java @@ -0,0 +1,138 @@ +package io.swagger.generator.resource; + +import io.swagger.codegen.*; +import io.swagger.generator.util.*; +import io.swagger.annotations.*; +import io.swagger.generator.model.*; +import io.swagger.generator.exception.BadRequestException; +import io.swagger.generator.online.Generator; + +import java.io.File; +import java.util.*; + +import javax.ws.rs.*; +import javax.ws.rs.core.*; + +@Path("/gen") +@Api(value = "/gen", description = "Resource for generating swagger components") +public class SwaggerResource { + private static Map fileMap = new HashMap(); + + static List clients = new ArrayList(); + static List servers = new ArrayList(); + static { + List extensions = Codegen.getExtensions(); + for(CodegenConfig config : extensions) { + if(config.getTag().equals(CodegenType.CLIENT) || config.getTag().equals(CodegenType.DOCUMENTATION)) { + clients.add(config.getName()); + } + else if(config.getTag().equals(CodegenType.SERVER)) { + servers.add(config.getName()); + } + } + } + + @GET + @Path("/download/{fileId}") + @Produces({MediaType.APPLICATION_OCTET_STREAM}) + @ApiOperation(value = "Downloads a pre-generated file", + response = String.class, + tags = {"clients", "servers"}) + public Response downloadFile(@PathParam("fileId") String fileId) throws Exception { + Generated g = fileMap.get(fileId); + System.out.println("looking for fileId " + fileId); + System.out.println("got filename " + g.getFilename()); + if(g.getFilename() != null) { + byte[] bytes = org.apache.commons.io.FileUtils.readFileToByteArray(new java.io.File(g.getFilename())); + + return Response.ok(bytes, "application/zip") + .header("Content-Disposition","attachment; filename=\"" + g.getFriendlyName() + "-generated.zip\"") + .header("Accept-Range", "bytes") + .header("Content-Length", bytes.length) + .build(); + } + else { + return Response.status(404).build(); + } + } + + @POST + @Path("/clients/{language}") + @ApiOperation( + value = "Generates a client library based on the config", + response = ResponseCode.class, + tags = "clients") + public Response generateClient( + @ApiParam(value = "The target language for the client library", allowableValues = "android,java,php,objc,docs", required = true) @PathParam("language") String language, + @ApiParam(value = "Configuration for building the client library", required = true) GeneratorInput opts) throws Exception { + + String filename = Generator.generateClient(language, opts); + + if(filename != null) { + String code = String.valueOf(System.currentTimeMillis()); + Generated g = new Generated(); + g.setFilename(filename); + g.setFriendlyName(language + "-client"); + fileMap.put(code, g); + System.out.println(code + ", " + filename); + String link = "http://generator.swagger.io/api/gen/download/" + code; + return Response.ok().entity(new ResponseCode(code, link)).build(); + } + else { + return Response.status(500).build(); + } + } + + @GET + @Path("/clients") + @ApiOperation(value = "Gets languages supported by the client generator", + response = String.class, + responseContainer = "List", + tags = "clients") + public Response clientOptions() { + String[] languages = new String[clients.size()]; + languages = clients.toArray(languages); + return Response.ok().entity(languages).build(); + } + + @GET + @Path("/servers") + @ApiOperation(value = "Gets languages supported by the server generator", + response = String.class, + responseContainer = "List", + tags = "servers") + public Response serverOptions() { + String[] languages = new String[servers.size()]; + languages = servers.toArray(languages); + return Response.ok().entity(languages).build(); + } + + @POST + @Path("/servers/{framework}") + @ApiOperation(value = "Generates a server library for the supplied server framework", + response = ResponseCode.class, + tags = "servers") + public Response generateServerForLanguage( + @ApiParam(value = "framework", allowableValues = "jaxrs,nodejs", required = true) @PathParam("framework") String framework, + @ApiParam(value = "parameters", required = true) GeneratorInput opts) + throws Exception { + if(framework == null) + throw new BadRequestException(400, "Framework is required"); + String filename = Generator.generateServer(framework, opts); + System.out.println("generated name: " + filename); + + if(filename != null) { + String code = String.valueOf(System.currentTimeMillis()); + Generated g = new Generated(); + g.setFilename(filename); + g.setFriendlyName(framework + "-server"); + fileMap.put(code, g); + System.out.println(code + ", " + filename); + String link = "http://generator.swagger.io/api/gen/download/" + code; + return Response.ok().entity(new ResponseCode(code, link)).build(); + } + else { + return Response.status(500).build(); + } + } +} diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/util/ApiOriginFilter.java b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ApiOriginFilter.java new file mode 100644 index 00000000000..8b59594211d --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ApiOriginFilter.java @@ -0,0 +1,42 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.util; + +import java.io.IOException; + +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; + +public class ApiOriginFilter implements javax.servlet.Filter { + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletResponse res = (HttpServletResponse) response; + res.addHeader("Access-Control-Allow-Origin", "*"); + res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); + res.addHeader("Access-Control-Allow-Headers", "Content-Type"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationException.java b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationException.java new file mode 100644 index 00000000000..46931e6ff6c --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationException.java @@ -0,0 +1,27 @@ +package io.swagger.generator.util; + +import java.util.List; + +public class ValidationException extends Exception { + private int code; + private String msg; + private List errors; + + public ValidationException(String msg) { + super(msg); + } + + public int getCode() { + return code; + } + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return msg; + } + public void setMessage(String msg) { + this.msg = msg; + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationMessage.java b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationMessage.java new file mode 100644 index 00000000000..b4a71d77ef4 --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ValidationMessage.java @@ -0,0 +1,26 @@ +package io.swagger.generator.util; + +public class ValidationMessage { + private String path, message, severity; + + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + public String getSeverity() { + return severity; + } + public void setSeverity(String severity) { + this.severity = severity; + } +} \ No newline at end of file diff --git a/modules/swagger-generator/src/main/java/io/swagger/generator/util/ZipUtil.java b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ZipUtil.java new file mode 100644 index 00000000000..54f0291195b --- /dev/null +++ b/modules/swagger-generator/src/main/java/io/swagger/generator/util/ZipUtil.java @@ -0,0 +1,124 @@ +/** + * Copyright 2015 Reverb, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.swagger.generator.util; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** +* This utility compresses a list of files to standard ZIP format file. +* It is able to compresses all sub files and sub directories, recursively. +* @author Ha Minh Nam +* +*/ +public class ZipUtil { + /** + * A constants for buffer size used to read/write data + */ + private static final int BUFFER_SIZE = 4096; + + /** + * Compresses a collection of files to a destination zip file + * @param listFiles A collection of files and directories + * @param destZipFile The path of the destination zip file + * @throws FileNotFoundException + * @throws IOException + */ + public void compressFiles(List listFiles, String destZipFile) throws FileNotFoundException, IOException { + + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(destZipFile)); + + for (File file : listFiles) { + if (file.isDirectory()) { + addFolderToZip(file, file.getName(), zos); + } else { + addFileToZip(file, zos); + } + } + + zos.flush(); + zos.close(); + } + + /** + * Adds a directory to the current zip output stream + * @param folder the directory to be added + * @param parentFolder the path of parent directory + * @param zos the current zip output stream + * @throws FileNotFoundException + * @throws IOException + */ + private void addFolderToZip(File folder, String parentFolder, + ZipOutputStream zos) throws FileNotFoundException, IOException { + for (File file : folder.listFiles()) { + if (file.isDirectory()) { + addFolderToZip(file, parentFolder + "/" + file.getName(), zos); + continue; + } + + zos.putNextEntry(new ZipEntry(parentFolder + "/" + file.getName())); + + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(file)); + + long bytesRead = 0; + byte[] bytesIn = new byte[BUFFER_SIZE]; + int read = 0; + + while ((read = bis.read(bytesIn)) != -1) { + zos.write(bytesIn, 0, read); + bytesRead += read; + } + + zos.closeEntry(); + + } + } + + /** + * Adds a file to the current zip output stream + * @param file the file to be added + * @param zos the current zip output stream + * @throws FileNotFoundException + * @throws IOException + */ + private void addFileToZip(File file, ZipOutputStream zos) + throws FileNotFoundException, IOException { + zos.putNextEntry(new ZipEntry(file.getName())); + + BufferedInputStream bis = new BufferedInputStream(new FileInputStream( + file)); + + long bytesRead = 0; + byte[] bytesIn = new byte[BUFFER_SIZE]; + int read = 0; + + while ((read = bis.read(bytesIn)) != -1) { + zos.write(bytesIn, 0, read); + bytesRead += read; + } + + zos.closeEntry(); + } +} \ No newline at end of file