forked from loafle/openapi-generator-original
[bug] Templates via classpath (#5164)
* Fixes issue with templates loading via classpath The templating engines were originally written to load templates via the classpath, but this functionality was blocked by file-only checks further up the stack. This loosens those file-only checks, allowing files and relatively imported files to be included via classpath. * [docs] Add details about classpath-level templates * [feat][maven] templateResourcePath for template on classpath - NOTE templateResourcePath is not needed for gradle, as it accepts a string for the target template directory, which supports classpath
This commit is contained in:
parent
22c6c0ca68
commit
507f80617d
@ -26,6 +26,29 @@ OpenAPI Generator supports user-defined templates. This approach is often the ea
|
|||||||
|
|
||||||
> **Note:** You cannot use this approach to create new templates, only override existing ones. If you'd like to create a new generator to contribute back to the project, see `new.sh` in the repository root. If you'd like to create a private generator for more templating control, see the [customization](./customization.md) docs.
|
> **Note:** You cannot use this approach to create new templates, only override existing ones. If you'd like to create a new generator to contribute back to the project, see `new.sh` in the repository root. If you'd like to create a private generator for more templating control, see the [customization](./customization.md) docs.
|
||||||
|
|
||||||
|
OpenAPI Generator not only supports local files for templating, but also templates defined on the classpath. This is a great option if you want to reuse templates across multiple projects. To load a template via classpath, you'll need to generate a little differently. For example, if you've created an artifact called `template-classpath-example` which contains extended templates for the `htmlDocs` generator with the following structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
└── src
|
||||||
|
├── main
|
||||||
|
│ ├── java
|
||||||
|
│ └── resources
|
||||||
|
│ └── templates
|
||||||
|
│ └── htmlDocs
|
||||||
|
│ ├── index.mustache
|
||||||
|
│ └── style.css.mustache
|
||||||
|
```
|
||||||
|
|
||||||
|
You can define your classpath to contain your JAR and the openapi-generator-cli _fat jar_, then invoke main class `org.openapitools.codegen.OpenAPIGenerator`. For instance,
|
||||||
|
|
||||||
|
```sh
|
||||||
|
java -cp /path/totemplate-classpath-example-1.0-SNAPSHOT.jar:modules/openapi-generator-cli/target/openapi-generator-cli.jar \
|
||||||
|
org.openapitools.codegen.OpenAPIGenerator generate -i https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml \
|
||||||
|
-g html -o template-example -t templates/htmlDocs
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that our template directory is relative to the resource directory of the JAR defined on the classpath.
|
||||||
|
|
||||||
### Custom Logic
|
### Custom Logic
|
||||||
|
|
||||||
For this example, let's modify a Java client to use AOP via [jcabi/jcabi-aspects](https://github.com/jcabi/jcabi-aspects). We'll log API method execution at the `INFO` level. The jcabi-aspects project could also be used to implement method retries on failures; this would be a great exercise to further play around with templating.
|
For this example, let's modify a Java client to use AOP via [jcabi/jcabi-aspects](https://github.com/jcabi/jcabi-aspects). We'll log API method execution at the `INFO` level. The jcabi-aspects project could also be used to implement method retries on failures; this would be a great exercise to further play around with templating.
|
||||||
|
@ -21,6 +21,9 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -406,15 +409,29 @@ public class WorkflowSettings {
|
|||||||
*/
|
*/
|
||||||
public Builder withTemplateDir(String templateDir) {
|
public Builder withTemplateDir(String templateDir) {
|
||||||
if (templateDir != null) {
|
if (templateDir != null) {
|
||||||
|
URI uri = null;
|
||||||
File f = new File(templateDir);
|
File f = new File(templateDir);
|
||||||
|
|
||||||
// check to see if the folder exists
|
// check to see if the folder exists
|
||||||
if (!(f.exists() && f.isDirectory())) {
|
if (f.exists() && f.isDirectory()) {
|
||||||
|
uri = f.toURI();
|
||||||
|
this.templateDir = Paths.get(uri).toAbsolutePath().toString();
|
||||||
|
} else {
|
||||||
|
URL url = this.getClass().getClassLoader().getResource(templateDir);
|
||||||
|
if (url != null) {
|
||||||
|
try {
|
||||||
|
uri = url.toURI();
|
||||||
|
this.templateDir = templateDir;
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
LOGGER.warn("The requested template was found on the classpath, but resulted in a syntax error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Template directory " + templateDir + " does not exist.");
|
"Template directory " + templateDir + " does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.templateDir = Paths.get(f.toURI()).toAbsolutePath().toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -48,6 +48,7 @@ mvn clean compile
|
|||||||
| `generatorName` | `openapi.generator.maven.plugin.generatorName` | target generator name
|
| `generatorName` | `openapi.generator.maven.plugin.generatorName` | target generator name
|
||||||
| `output` | `openapi.generator.maven.plugin.output` | target output path (default is `${project.build.directory}/generated-sources/openapi`. Can also be set globally through the `openapi.generator.maven.plugin.output` property)
|
| `output` | `openapi.generator.maven.plugin.output` | target output path (default is `${project.build.directory}/generated-sources/openapi`. Can also be set globally through the `openapi.generator.maven.plugin.output` property)
|
||||||
| `templateDirectory` | `openapi.generator.maven.plugin.templateDirectory` | directory with mustache templates
|
| `templateDirectory` | `openapi.generator.maven.plugin.templateDirectory` | directory with mustache templates
|
||||||
|
| `templateResourcePath` | `openapi.generator.maven.plugin.templateResourcePath` | directory with mustache templates via resource path. This option will overwrite any option defined in `templateDirectory`.
|
||||||
| `addCompileSourceRoot` | `openapi.generator.maven.plugin.addCompileSourceRoot` | add the output directory to the project as a source root (`true` by default)
|
| `addCompileSourceRoot` | `openapi.generator.maven.plugin.addCompileSourceRoot` | add the output directory to the project as a source root (`true` by default)
|
||||||
| `modelPackage` | `openapi.generator.maven.plugin.modelPackage` | the package to use for generated model objects/classes
|
| `modelPackage` | `openapi.generator.maven.plugin.modelPackage` | the package to use for generated model objects/classes
|
||||||
| `apiPackage` | `openapi.generator.maven.plugin.apiPackage` | the package to use for generated api objects/classes
|
| `apiPackage` | `openapi.generator.maven.plugin.apiPackage` | the package to use for generated api objects/classes
|
||||||
|
@ -40,6 +40,7 @@ import java.util.Set;
|
|||||||
import com.google.common.io.ByteSource;
|
import com.google.common.io.ByteSource;
|
||||||
import com.google.common.io.CharSource;
|
import com.google.common.io.CharSource;
|
||||||
import io.swagger.v3.parser.util.ClasspathHelper;
|
import io.swagger.v3.parser.util.ClasspathHelper;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
@ -133,6 +134,12 @@ public class CodeGenMojo extends AbstractMojo {
|
|||||||
@Parameter(name = "templateDirectory", property = "openapi.generator.maven.plugin.templateDirectory")
|
@Parameter(name = "templateDirectory", property = "openapi.generator.maven.plugin.templateDirectory")
|
||||||
private File templateDirectory;
|
private File templateDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource path containing template files.
|
||||||
|
*/
|
||||||
|
@Parameter(name = "templateResourcePath", property = "openapi.generator.maven.plugin.templateResourcePath")
|
||||||
|
private String templateResourcePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of templating engine to use, "mustache" (default) or "handlebars" (beta)
|
* The name of templating engine to use, "mustache" (default) or "handlebars" (beta)
|
||||||
*/
|
*/
|
||||||
@ -583,6 +590,13 @@ public class CodeGenMojo extends AbstractMojo {
|
|||||||
configurator.setTemplateDir(templateDirectory.getAbsolutePath());
|
configurator.setTemplateDir(templateDirectory.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(templateResourcePath)) {
|
||||||
|
if (null != templateDirectory) {
|
||||||
|
LOGGER.warn("Both templateDirectory and templateResourcePath were configured. templateResourcePath overwrites templateDirectory.");
|
||||||
|
}
|
||||||
|
configurator.setTemplateDir(templateResourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
if (null != engine) {
|
if (null != engine) {
|
||||||
configurator.setTemplatingEngineName(engine);
|
configurator.setTemplatingEngineName(engine);
|
||||||
}
|
}
|
||||||
|
@ -161,14 +161,14 @@ public abstract class AbstractGenerator implements TemplatingGenerator {
|
|||||||
if (StringUtils.isNotEmpty(library)) {
|
if (StringUtils.isNotEmpty(library)) {
|
||||||
//look for the file in the library subfolder of the supplied template
|
//look for the file in the library subfolder of the supplied template
|
||||||
final String libTemplateFile = buildLibraryFilePath(config.templateDir(), library, templateFile);
|
final String libTemplateFile = buildLibraryFilePath(config.templateDir(), library, templateFile);
|
||||||
if (new File(libTemplateFile).exists()) {
|
if (new File(libTemplateFile).exists() || this.getClass().getClassLoader().getResource(libTemplateFile) != null) {
|
||||||
return libTemplateFile;
|
return libTemplateFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//check the supplied template main folder for the file
|
//check the supplied template main folder for the file
|
||||||
final String template = config.templateDir() + File.separator + templateFile;
|
final String template = config.templateDir() + File.separator + templateFile;
|
||||||
if (new File(template).exists()) {
|
if (new File(template).exists() || this.getClass().getClassLoader().getResource(template) != null) {
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user