Skip to content

Commit

Permalink
simplified configuration; updated documentation; minor clean-up;
Browse files Browse the repository at this point in the history
  • Loading branch information
sdaschner committed Jul 13, 2018
1 parent 1ba40af commit 3be9b12
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 155 deletions.
17 changes: 13 additions & 4 deletions Changelog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@
Sebastian Daschner

// new versions are placed on the top
== v0.17-SNAPSHOT
- Generating description also in Plaintext, Asciidoc and Markdown
- Added Markdown support
- Added possibility to ignore JAX-RS boundary classes

== v0.17 SNAPSHOT
- Markdown support
- Added resource description in remaining backends
- Support to ignore JAX-RS boundary classes

== v0.16
- Added AsciiDoc prettification
- Fixed error on empty application path
- Minor fixes

== v0.15
- Fixed JavaDoc erased types

== v0.14
- Fixed test related execution phase
Expand Down
9 changes: 4 additions & 5 deletions Documentation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Just add the latest release version of the JAX-RS Analyzer to your Maven pom.xml
<plugin>
<groupId>com.sebastian-daschner</groupId>
<artifactId>jaxrs-analyzer-maven-plugin</artifactId>
<version>0.14</version>
<version>0.16</version>
<executions>
<execution>
<goals>
Expand Down Expand Up @@ -57,15 +57,14 @@ Following available backend specific options (only have effect if the correspond
* `--swaggerSchemes <scheme>[,schemes]` The Swagger schemes: `http` (default), `https`, `ws`, `wss`
* `--renderSwaggerTags` Enables rendering of Swagger tags (default tag will be used per default)
* `--swaggerTagsPathOffset <path offset>` The number at which path position the Swagger tags will be extracted (0 will be used per default)
* `--ignoredBoundaryClasses <fully qualified classname [class,...]>` Boundary classes which should be ignored by analyze (empty per default)
* `--ignoredRootResources <fully qualified classname [class,...]>` JAX-RS root resource classes which should be ignored by analyze (empty per default). Note that these ignores only cause the classes to be ignored as root resources; they might still be taken into account as JAX-RS sub-resources.

== Backends
The Analyzer supports Plaintext, AsciiDoc, Markdown and Swagger as output format.
The latter three can be processed further.

Markdown is a human-readable, lightweight markup langugae.

AsciiDoc is like Markdown. But it can be easily converted to PDF, HTML (and many more) using tools like https://github.com/asciidoctor/asciidoctor[Asciidoctor].
AsciiDoc and Markdown are human-readable, lightweight markup languages.
They can easily converted to PDF, HTML, and many more.

The Swagger JSON file can be used with Swagger UI or the http://editor.swagger.io[Swagger Editor].

Expand Down
109 changes: 66 additions & 43 deletions src/main/java/com/sebastian_daschner/jaxrs_analyzer/JAXRSAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,68 +22,43 @@
*/
public class JAXRSAnalyzer {

private final Set<Path> projectClassPaths = new HashSet<>();
private final Set<Path> projectSourcePaths = new HashSet<>();
private final Set<Path> classPaths = new HashSet<>();
private final String projectName;
private final String projectVersion;
private final Path outputLocation;
private final Backend backend;
private Set<String> ignoredBoundaryClasses = new HashSet<>();

private final Analysis analysis;

/**
* Constructs a JAX-RS Analyzer.
*
* @param projectClassPaths The paths of the projects classes to be analyzed (can either be directories or jar-files, at least one is mandatory)
* @param projectSourcePaths The paths of the projects sources to be analyzed (can either be directories or jar-files, optional)
* @param classPaths The additional class paths (can either be directories or jar-files)
* @param projectName The project name
* @param projectVersion The project version
* @param backend The backend to render the output
* @param outputLocation The location of the output file (output will be printed to standard out if {@code null})
*/
public JAXRSAnalyzer(final Set<Path> projectClassPaths, final Set<Path> projectSourcePaths, final Set<Path> classPaths, final String projectName, final String projectVersion,
final Backend backend, final Path outputLocation) {
Objects.requireNonNull(projectClassPaths);
Objects.requireNonNull(projectSourcePaths);
Objects.requireNonNull(classPaths);
Objects.requireNonNull(projectName);
Objects.requireNonNull(projectVersion);
Objects.requireNonNull(backend);

if (projectClassPaths.isEmpty())
public JAXRSAnalyzer(Analysis analysis) {
Objects.requireNonNull(analysis);
Objects.requireNonNull(analysis.projectClassPaths);
Objects.requireNonNull(analysis.projectSourcePaths);
Objects.requireNonNull(analysis.classPaths);
Objects.requireNonNull(analysis.projectName);
Objects.requireNonNull(analysis.projectVersion);
Objects.requireNonNull(analysis.backend);

if (analysis.projectClassPaths.isEmpty())
throw new IllegalArgumentException("At least one project path is mandatory");

this.projectClassPaths.addAll(projectClassPaths);
this.projectSourcePaths.addAll(projectSourcePaths);
this.classPaths.addAll(classPaths);
this.projectName = projectName;
this.projectVersion = projectVersion;
this.outputLocation = outputLocation;
this.backend = backend;
}

public void setIgnoredBoundaryClasses( Set<String> ignoredBoundaryClasses ) {
this.ignoredBoundaryClasses = ignoredBoundaryClasses;
this.analysis = analysis;
}

/**
* Analyzes the JAX-RS project at the class path and produces the output as configured.
*/
public void analyze() {
final Resources resources = new ProjectAnalyzer( classPaths, ignoredBoundaryClasses ).analyze(projectClassPaths, projectSourcePaths);
final Resources resources = new ProjectAnalyzer(analysis.classPaths)
.analyze(analysis.projectClassPaths, analysis.projectSourcePaths, analysis.ignoredResources);

if (resources.isEmpty()) {
LogProvider.info("Empty JAX-RS analysis result, omitting output");
return;
}

final Project project = new Project(projectName, projectVersion, resources);
final byte[] output = backend.render(project);
final Project project = new Project(analysis.projectName, analysis.projectVersion, resources);
final byte[] output = analysis.backend.render(project);

if (outputLocation != null) {
outputToFile(output, outputLocation);
if (analysis.outputLocation != null) {
outputToFile(output, analysis.outputLocation);
} else {
outputToConsole(output);
}
Expand Down Expand Up @@ -117,4 +92,52 @@ public static Backend constructBackend(final String backendType) {
.orElseThrow(() -> new IllegalArgumentException("Unknown backend type " + backendType));
}

public static class Analysis {

private final Set<Path> projectClassPaths = new HashSet<>();
private final Set<Path> projectSourcePaths = new HashSet<>();
private final Set<Path> classPaths = new HashSet<>();
private final Set<String> ignoredResources = new HashSet<>();
private String projectName;
private String projectVersion;
private Path outputLocation;
private Backend backend;

public Set<Path> getProjectClassPaths() {
return projectClassPaths;
}

public void addProjectClassPath(Path classPath) {
projectClassPaths.add(classPath);
}

public void addProjectSourcePath(Path sourcePath) {
projectSourcePaths.add(sourcePath);
}

public void addClassPath(Path classPath) {
classPaths.add(classPath);
}

public void addIgnoredResource(String ignored) {
ignoredResources.add(ignored);
}

public void setProjectName(String projectName) {
this.projectName = projectName;
}

public void setProjectVersion(String projectVersion) {
this.projectVersion = projectVersion;
}

public void setOutputLocation(Path outputLocation) {
this.outputLocation = outputLocation;
}

public void setBackend(Backend backend) {
this.backend = backend;
}
}

}
76 changes: 40 additions & 36 deletions src/main/java/com/sebastian_daschner/jaxrs_analyzer/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -35,16 +37,12 @@ public class Main {

private static final String DEFAULT_NAME = "project";
private static final String DEFAULT_VERSION = "0.1-SNAPSHOT";
private static final String DEFAULT_BACKEND = "swagger";
private static final String COMMA_LIST_SEPARATOR = ",";

private static final Set<Path> projectClassPaths = new HashSet<>();
private static final Set<Path> projectSourcePaths = new HashSet<>();
private static final Set<Path> classPaths = new HashSet<>();
private static final JAXRSAnalyzer.Analysis analysis = new JAXRSAnalyzer.Analysis();
private static final Map<String, String> attributes = new HashMap<>();
private static String name = DEFAULT_NAME;
private static String version = DEFAULT_VERSION;
private static String backendType = "swagger";
private static Set<String> ignoredBoundaryClasses = new HashSet<>();
private static Path outputFileLocation;
private static Backend backend;

/**
* Inspects JAX-RS projects and outputs the gathered information.
Expand All @@ -71,7 +69,7 @@ public class Main {
* <li>{@code --swaggerSchemes scheme[,schemes]} The Swagger schemes: {@code http} (default), {@code https}, {@code ws}, {@code wss}")</li>
* <li>{@code --renderSwaggerTags} Enables rendering of Swagger tags (will not be rendered per default)</li>
* <li>{@code --swaggerTagsPathOffset path offset} The number at which path position the Swagger tags should be extracted ({@code 0} per default)</li>
* <li>{@code --ignoredBoundaryClasses class[,classes]} Boundary classes which should be ignored by analyze (empty per default)</li>
* <li>{@code --ignoredRootResources class[,classes]} JAX-RS root resource classes which should be ignored by analyze (empty per default)</li>
* </ul>
*
* @param args The arguments
Expand All @@ -82,20 +80,22 @@ public static void main(final String... args) {
}

try {
setDefaults();
extractArgs(args);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage() + '\n');
printUsageAndExit();
}

validateArgs();
configureBackend();

final Backend backend = JAXRSAnalyzer.constructBackend(backendType);
backend.configure(attributes);
new JAXRSAnalyzer(analysis).analyze();
}

final JAXRSAnalyzer jaxrsAnalyzer = new JAXRSAnalyzer(projectClassPaths, projectSourcePaths, classPaths, name, version, backend, outputFileLocation);
jaxrsAnalyzer.setIgnoredBoundaryClasses( ignoredBoundaryClasses );
jaxrsAnalyzer.analyze();
private static void setDefaults() {
analysis.setProjectName(DEFAULT_NAME);
analysis.setProjectVersion(DEFAULT_VERSION);
}

private static void extractArgs(String[] args) {
Expand All @@ -104,28 +104,28 @@ private static void extractArgs(String[] args) {
if (args[i].startsWith("-")) {
switch (args[i]) {
case "-b":
backendType = extractBackend(args[++i]);
analysis.setBackend(extractBackend(args[++i]));
break;
case "-cp":
extractClassPaths(args[++i]).forEach(classPaths::add);
extractClassPaths(args[++i]).forEach(analysis::addClassPath);
break;
case "-sp":
extractClassPaths(args[++i]).forEach(projectSourcePaths::add);
extractClassPaths(args[++i]).forEach(analysis::addProjectSourcePath);
break;
case "-X":
LogProvider.injectDebugLogger(System.err::println);
break;
case "-n":
name = args[++i];
analysis.setProjectName(args[++i]);
break;
case "-v":
version = args[++i];
analysis.setProjectVersion(args[++i]);
break;
case "-d":
attributes.put(SwaggerOptions.DOMAIN, args[++i]);
break;
case "-o":
outputFileLocation = Paths.get(args[++i]);
analysis.setOutputLocation(Paths.get(args[++i]));
break;
case "-e":
System.setProperty("project.build.sourceEncoding", args[++i]);
Expand All @@ -142,8 +142,8 @@ private static void extractArgs(String[] args) {
case "--noInlinePrettify":
attributes.put(StringBackend.INLINE_PRETTIFY, "false");
break;
case "--ignoredBoundaryClasses":
ignoredBoundaryClasses = buildSetOfCommaList( args[++i] );
case "--ignoredRootResources":
extractList(args[++i]).forEach(analysis::addIgnoredResource);
break;
case "-a":
addAttribute(args[++i]);
Expand All @@ -157,7 +157,7 @@ private static void extractArgs(String[] args) {
System.err.println("Location " + path.toFile() + " doesn't exist\n");
printUsageAndExit();
}
projectClassPaths.add(path);
analysis.addProjectClassPath(path);
}
}
} catch (IndexOutOfBoundsException e) {
Expand All @@ -177,8 +177,8 @@ static Map<String, String> addAttribute(String attribute) {
return attributes;
}

private static String extractBackend(final String name) {
return name.toLowerCase();
private static Backend extractBackend(final String name) {
return JAXRSAnalyzer.constructBackend(name.toLowerCase());
}

private static List<Path> extractClassPaths(final String classPaths) {
Expand All @@ -193,27 +193,31 @@ private static List<Path> extractClassPaths(final String classPaths) {
return paths;
}

private static Set<String> buildSetOfCommaList( String commaList ) {
Set<String> set = new HashSet<>();
if( commaList==null || commaList.trim().isEmpty() )
return set;

set.addAll( Arrays.asList( commaList.split( "," ) ) );
return set;
private static List<String> extractList(String list) {
return Stream.of(list.split(COMMA_LIST_SEPARATOR))
.map(String::trim)
.filter(String::isEmpty)
.collect(Collectors.toList());
}

private static void validateArgs() {
if (projectClassPaths.isEmpty()) {
if (analysis.getProjectClassPaths().isEmpty()) {
System.err.println("Please provide at least one project path\n");
printUsageAndExit();
}
}

private static void configureBackend() {
if (backend == null)
backend = JAXRSAnalyzer.constructBackend(DEFAULT_BACKEND);
backend.configure(attributes);
}

private static void printUsageAndExit() {
System.err.println("Usage: java -jar jaxrs-analyzer.jar [options] classPath [classPaths...]");
System.err.println("The classPath entries may be directories or jar-files containing the classes to be analyzed\n");
System.err.println("Following available options:\n");
System.err.println(" -b <backend> The backend to choose: swagger (default), plaintext, asciidoc, mardown");
System.err.println(" -b <backend> The backend to choose: swagger (default), plaintext, asciidoc, markdown");
System.err.println(" -cp <class path>[:class paths] Additional class paths (separated with colon) which contain classes used in the project (may be directories or jar-files)");
System.err.println(" -sp <source path>[:source paths] Optional source paths (separated with colon) needed for JavaDoc analysis (may be directories or jar-files)");
System.err.println(" -X Debug enabled (enabled error debugging information)");
Expand All @@ -227,7 +231,7 @@ private static void printUsageAndExit() {
System.err.println(" --swaggerSchemes <scheme>[,schemes] The Swagger schemes: http (default), https, ws, wss");
System.err.println(" --renderSwaggerTags Enables rendering of Swagger tags (default tag will be used per default)");
System.err.println(" --swaggerTagsPathOffset <path offset> The number at which path position the Swagger tags will be extracted (0 will be used per default)");
System.err.println(" --ignoredBoundaryClasses <fully qualified classname [class,...]> Boundary classes which should be ignored by analyze (empty per default)");
System.err.println(" --ignoredRootResources <fully qualified classname [class,...]> JAX-RS root resource classes which should be ignored by analyze (empty per default)");
System.err.println(" --noPrettyPrint Don't pretty print inline JSON body representations (will be pretty printed per default)");
System.err.println("\nExample: java -jar jaxrs-analyzer.jar -b swagger -n \"My Project\" -cp ~/libs/lib1.jar:~/libs/project/bin ~/project/target/classes");
System.exit(1);
Expand Down
Loading

0 comments on commit 3be9b12

Please sign in to comment.