Committed by
Gerrit Code Review
ONOS Swagger Plugin
just does swagger now to build the plugin, you need to download to following: https://github.com/bocon13/buck/releases/download/v2016.07.29.01-wip/buck.jar put the buck.jar in tools/build/buck-plugin/lib Change-Id: Id1b833dd013fbc5581f8e884e755920829c4a17e
Showing
15 changed files
with
1133 additions
and
2 deletions
... | @@ -16,4 +16,9 @@ osgi_jar_with_tests ( | ... | @@ -16,4 +16,9 @@ osgi_jar_with_tests ( |
16 | deps = COMPILE_DEPS, | 16 | deps = COMPILE_DEPS, |
17 | test_deps = TEST_DEPS, | 17 | test_deps = TEST_DEPS, |
18 | web_context = '/onos/dhcp', | 18 | web_context = '/onos/dhcp', |
19 | + api_title = 'DHCP Server App', | ||
20 | + api_version = '1.0', | ||
21 | + api_description = 'REST API for DHCP Server App', | ||
22 | + api_package = 'org.onosproject.dhcp.rest', | ||
23 | + debug = False | ||
19 | ) | 24 | ) | ... | ... |
... | @@ -107,6 +107,10 @@ def osgi_jar( | ... | @@ -107,6 +107,10 @@ def osgi_jar( |
107 | package_name_root = 'org.onosproject', | 107 | package_name_root = 'org.onosproject', |
108 | include_resources = NONE, | 108 | include_resources = NONE, |
109 | web_context = NONE, | 109 | web_context = NONE, |
110 | + api_title = NONE, | ||
111 | + api_version = NONE, | ||
112 | + api_package = NONE, | ||
113 | + api_description = NONE, | ||
110 | resources = NONE, | 114 | resources = NONE, |
111 | resources_root = None, | 115 | resources_root = None, |
112 | **kwargs | 116 | **kwargs |
... | @@ -128,18 +132,27 @@ def osgi_jar( | ... | @@ -128,18 +132,27 @@ def osgi_jar( |
128 | if resources and not resources_root: | 132 | if resources and not resources_root: |
129 | resources_root = RESOURCES_ROOT | 133 | resources_root = RESOURCES_ROOT |
130 | 134 | ||
135 | + if api_title != NONE: | ||
136 | + r = 'WEB-INF/classes/apidoc/swagger.json=bin/swagger.json' | ||
137 | + include_resources = include_resources + ',' + r if include_resources != NONE else r | ||
138 | + | ||
131 | bare_jar_name = name + '-jar' | 139 | bare_jar_name = name + '-jar' |
132 | osgi_jar_name = name + '-osgi' | 140 | osgi_jar_name = name + '-osgi' |
133 | mvn_coords = group_id + ':' + name + ':' + version | 141 | mvn_coords = group_id + ':' + name + ':' + version |
134 | 142 | ||
135 | 143 | ||
136 | - java_library( | 144 | + onos_jar( |
137 | name = bare_jar_name, | 145 | name = bare_jar_name, |
138 | srcs = srcs, | 146 | srcs = srcs, |
139 | deps = deps, | 147 | deps = deps, |
140 | visibility = [], #intentially, not visible | 148 | visibility = [], #intentially, not visible |
141 | resources = resources, | 149 | resources = resources, |
142 | resources_root = resources_root, | 150 | resources_root = resources_root, |
151 | + web_context = web_context, | ||
152 | + api_title = api_title, | ||
153 | + api_version = api_version, | ||
154 | + api_package = api_package, | ||
155 | + api_description = api_description, | ||
143 | **kwargs | 156 | **kwargs |
144 | ) | 157 | ) |
145 | 158 | ||
... | @@ -167,6 +180,7 @@ def osgi_jar( | ... | @@ -167,6 +180,7 @@ def osgi_jar( |
167 | bash = stage_jar + DEBUG_ARG + ' ' + wrap_jar | 180 | bash = stage_jar + DEBUG_ARG + ' ' + wrap_jar |
168 | print bash | 181 | print bash |
169 | 182 | ||
183 | + # FIXME: make sure that /swagger.json gets filtered | ||
170 | genrule( | 184 | genrule( |
171 | name = osgi_jar_name, | 185 | name = osgi_jar_name, |
172 | bash = bash, | 186 | bash = bash, | ... | ... |
tools/build/buck-plugin/BUCK
0 → 100644
1 | +remote_jar ( | ||
2 | + name = 'buck-api', | ||
3 | + out = 'buck.jar', | ||
4 | + url = 'https://github.com/bocon13/buck/releases/download/v2016.07.29.01-wip/buck.jar', | ||
5 | + sha1 = 'f89324cb869b74fdcd4db9972233065a93d890a2', | ||
6 | + visibility = [], | ||
7 | +) | ||
8 | + | ||
9 | +COMPILE = [ | ||
10 | + '//lib:qdox', | ||
11 | + #'//lib:jackson-core', | ||
12 | + #'//lib:jackson-databind', | ||
13 | + #'//lib:jackson-annotations', | ||
14 | +] | ||
15 | + | ||
16 | +RUNTIME = [ | ||
17 | +] | ||
18 | + | ||
19 | +java_library( | ||
20 | + name = 'lib', | ||
21 | + srcs = glob(['src/main/java/**/*.java']), | ||
22 | + resources = glob(['src/main/resources/**/*']), | ||
23 | + resources_root = 'src/main/resources', | ||
24 | + deps = COMPILE, | ||
25 | + provided_deps = [':buck-api'], | ||
26 | + visibility = [], | ||
27 | +) | ||
28 | + | ||
29 | +java_binary( | ||
30 | + name = 'onosjar', | ||
31 | + deps = [':lib'], | ||
32 | + visibility = ['PUBLIC'], | ||
33 | +) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
tools/build/buck-plugin/buck-plugin-install
0 → 100755
1 | +#!/bin/bash | ||
2 | + | ||
3 | +PLUGINS=$ONOS_ROOT/bucklets/plugins | ||
4 | + | ||
5 | +# Build it first | ||
6 | +pluginJar=$(NO_BUCKD=1 buck build //tools/build/buck-plugin:onosjar --no-cache --show-output | grep onosjar.jar | cut -d\ -f2) | ||
7 | + | ||
8 | +# Then install it | ||
9 | +mkdir -p $PLUGINS | ||
10 | +cp $ONOS_ROOT/$pluginJar $PLUGINS | ||
11 | + | ||
12 | +ls -l $PLUGINS |
tools/build/buck-plugin/buck-plugin-test
0 → 100755
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.onosjar; | ||
17 | + | ||
18 | +import com.facebook.buck.jvm.java.CompileToJarStepFactory; | ||
19 | +import com.facebook.buck.jvm.java.DefaultJavaLibrary; | ||
20 | +import com.facebook.buck.model.BuildTarget; | ||
21 | +import com.facebook.buck.rules.AddToRuleKey; | ||
22 | +import com.facebook.buck.rules.BuildRule; | ||
23 | +import com.facebook.buck.rules.BuildRuleParams; | ||
24 | +import com.facebook.buck.rules.SourcePath; | ||
25 | +import com.facebook.buck.rules.SourcePathResolver; | ||
26 | +import com.google.common.base.Optional; | ||
27 | +import com.google.common.collect.ImmutableList; | ||
28 | +import com.google.common.collect.ImmutableSet; | ||
29 | +import com.google.common.collect.ImmutableSortedSet; | ||
30 | + | ||
31 | +import java.nio.file.Path; | ||
32 | +import java.util.Set; | ||
33 | +import java.util.regex.Pattern; | ||
34 | + | ||
35 | +/** | ||
36 | + * Implementation of a build rule that generates a onosjar.json file for a set | ||
37 | + * of Java sources. | ||
38 | + */ | ||
39 | +public class OnosJar extends DefaultJavaLibrary { | ||
40 | + | ||
41 | + @AddToRuleKey | ||
42 | + final Optional<String> webContext; | ||
43 | + | ||
44 | + @AddToRuleKey | ||
45 | + final Optional<String> apiTitle; | ||
46 | + | ||
47 | + @AddToRuleKey | ||
48 | + final Optional<String> apiVersion; | ||
49 | + | ||
50 | + @AddToRuleKey | ||
51 | + final Optional<String> apiPackage; | ||
52 | + | ||
53 | + @AddToRuleKey | ||
54 | + final Optional<String> apiDescription; | ||
55 | + | ||
56 | + public OnosJar(BuildRuleParams params, | ||
57 | + SourcePathResolver resolver, | ||
58 | + Set<? extends SourcePath> srcs, | ||
59 | + Set<? extends SourcePath> resources, | ||
60 | + Optional<Path> generatedSourceFolder, | ||
61 | + Optional<SourcePath> proguardConfig, | ||
62 | + ImmutableList<String> postprocessClassesCommands, | ||
63 | + ImmutableSortedSet<BuildRule> exportedDeps, | ||
64 | + ImmutableSortedSet<BuildRule> providedDeps, | ||
65 | + SourcePath abiJar, boolean trackClassUsage, | ||
66 | + ImmutableSet<Path> additionalClasspathEntries, | ||
67 | + CompileToJarStepFactory compileStepFactory, | ||
68 | + Optional<Path> resourcesRoot, | ||
69 | + Optional<String> mavenCoords, | ||
70 | + ImmutableSortedSet<BuildTarget> tests, | ||
71 | + ImmutableSet<Pattern> classesToRemoveFromJar, | ||
72 | + Optional<String> webContext, | ||
73 | + Optional<String> apiTitle, | ||
74 | + Optional<String> apiVersion, | ||
75 | + Optional<String> apiPackage, | ||
76 | + Optional<String> apiDescription) { | ||
77 | + super(params, resolver, srcs, resources, generatedSourceFolder, | ||
78 | + proguardConfig, postprocessClassesCommands, exportedDeps, | ||
79 | + providedDeps, abiJar, trackClassUsage, additionalClasspathEntries, | ||
80 | + compileStepFactory, resourcesRoot, mavenCoords, tests, | ||
81 | + classesToRemoveFromJar); | ||
82 | + this.webContext = webContext; | ||
83 | + this.apiTitle = apiTitle; | ||
84 | + this.apiVersion = apiVersion; | ||
85 | + this.apiPackage = apiPackage; | ||
86 | + this.apiDescription = apiDescription; | ||
87 | + } | ||
88 | +} |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.onosjar; | ||
17 | + | ||
18 | +import com.facebook.buck.cli.BuckConfig; | ||
19 | +import com.facebook.buck.jvm.java.CalculateAbi; | ||
20 | +import com.facebook.buck.jvm.java.DefaultJavaLibrary; | ||
21 | +import com.facebook.buck.jvm.java.JavaBuckConfig; | ||
22 | +import com.facebook.buck.jvm.java.JavaLibraryDescription; | ||
23 | +import com.facebook.buck.jvm.java.JavaOptions; | ||
24 | +import com.facebook.buck.jvm.java.JavacOptions; | ||
25 | +import com.facebook.buck.jvm.java.JavacOptionsAmender; | ||
26 | +import com.facebook.buck.jvm.java.JavacOptionsFactory; | ||
27 | +import com.facebook.buck.model.BuildTarget; | ||
28 | +import com.facebook.buck.model.Flavor; | ||
29 | +import com.facebook.buck.parser.NoSuchBuildTargetException; | ||
30 | +import com.facebook.buck.rules.BuildRule; | ||
31 | +import com.facebook.buck.rules.BuildRuleParams; | ||
32 | +import com.facebook.buck.rules.BuildRuleResolver; | ||
33 | +import com.facebook.buck.rules.BuildRuleType; | ||
34 | +import com.facebook.buck.rules.BuildRules; | ||
35 | +import com.facebook.buck.rules.BuildTargetSourcePath; | ||
36 | +import com.facebook.buck.rules.Description; | ||
37 | +import com.facebook.buck.rules.SourcePathResolver; | ||
38 | +import com.facebook.buck.rules.SourcePaths; | ||
39 | +import com.facebook.buck.rules.TargetGraph; | ||
40 | +import com.google.common.base.Optional; | ||
41 | +import com.google.common.collect.ImmutableSet; | ||
42 | +import com.google.common.collect.ImmutableSortedSet; | ||
43 | +import com.google.common.collect.Iterables; | ||
44 | + | ||
45 | +import java.nio.file.Path; | ||
46 | + | ||
47 | +import static com.facebook.buck.jvm.common.ResourceValidator.validateResources; | ||
48 | + | ||
49 | +/** | ||
50 | + * Description for the onos_jar rules. | ||
51 | + * | ||
52 | + * Currently, this only does Swagger generation. | ||
53 | + */ | ||
54 | +public class OnosJarDescription implements Description<OnosJarDescription.Arg> { | ||
55 | + public static final BuildRuleType TYPE = BuildRuleType.of("onos_jar"); | ||
56 | + private final JavacOptions defaultJavacOptions; | ||
57 | + private final JavaOptions defaultJavaOptions; | ||
58 | + | ||
59 | + public OnosJarDescription(BuckConfig config) { | ||
60 | + JavaBuckConfig javaConfig = new JavaBuckConfig(config); | ||
61 | + defaultJavacOptions = javaConfig.getDefaultJavacOptions(); | ||
62 | + defaultJavaOptions = javaConfig.getDefaultJavaOptions(); | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public BuildRuleType getBuildRuleType() { | ||
67 | + return TYPE; | ||
68 | + } | ||
69 | + | ||
70 | + @Override | ||
71 | + public Arg createUnpopulatedConstructorArg() { | ||
72 | + return new Arg(); | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public <A extends Arg> BuildRule createBuildRule(TargetGraph targetGraph, | ||
77 | + BuildRuleParams params, | ||
78 | + BuildRuleResolver resolver, | ||
79 | + A args) | ||
80 | + throws NoSuchBuildTargetException { | ||
81 | + | ||
82 | + | ||
83 | + SourcePathResolver pathResolver = new SourcePathResolver(resolver); | ||
84 | + BuildTarget target = params.getBuildTarget(); | ||
85 | + | ||
86 | + // We know that the flavour we're being asked to create is valid, since the check is done when | ||
87 | + // creating the action graph from the target graph. | ||
88 | + | ||
89 | + ImmutableSortedSet<Flavor> flavors = target.getFlavors(); | ||
90 | + BuildRuleParams paramsWithMavenFlavor = null; | ||
91 | + | ||
92 | + JavacOptions javacOptions = JavacOptionsFactory.create( | ||
93 | + defaultJavacOptions, | ||
94 | + params, | ||
95 | + resolver, | ||
96 | + pathResolver, | ||
97 | + args | ||
98 | + ); | ||
99 | + | ||
100 | + BuildTarget abiJarTarget = params.getBuildTarget().withAppendedFlavors(CalculateAbi.FLAVOR); | ||
101 | + | ||
102 | + ImmutableSortedSet<BuildRule> exportedDeps = resolver.getAllRules(args.exportedDeps.get()); | ||
103 | + | ||
104 | + DefaultJavaLibrary defaultJavaLibrary = | ||
105 | + resolver.addToIndex( | ||
106 | + new OnosJar( | ||
107 | + params.appendExtraDeps( | ||
108 | + Iterables.concat( | ||
109 | + BuildRules.getExportedRules( | ||
110 | + Iterables.concat( | ||
111 | + params.getDeclaredDeps().get(), | ||
112 | + exportedDeps, | ||
113 | + resolver.getAllRules(args.providedDeps.get()))), | ||
114 | + pathResolver.filterBuildRuleInputs( | ||
115 | + javacOptions.getInputs(pathResolver)))), | ||
116 | + pathResolver, | ||
117 | + args.srcs.get(), | ||
118 | + validateResources( | ||
119 | + pathResolver, | ||
120 | + params.getProjectFilesystem(), | ||
121 | + args.resources.get()), | ||
122 | + javacOptions.getGeneratedSourceFolderName(), | ||
123 | + args.proguardConfig.transform( | ||
124 | + SourcePaths.toSourcePath(params.getProjectFilesystem())), | ||
125 | + args.postprocessClassesCommands.get(), // FIXME this should be forbidden | ||
126 | + exportedDeps, | ||
127 | + resolver.getAllRules(args.providedDeps.get()), | ||
128 | + new BuildTargetSourcePath(abiJarTarget), | ||
129 | + javacOptions.trackClassUsage(), | ||
130 | + /* additionalClasspathEntries */ ImmutableSet.<Path>of(), | ||
131 | + new OnosJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY, | ||
132 | + args.webContext, args.apiTitle, args.apiVersion, | ||
133 | + args.apiPackage, args.apiDescription, args.resources), | ||
134 | + args.resourcesRoot, | ||
135 | + args.mavenCoords, | ||
136 | + args.tests.get(), | ||
137 | + javacOptions.getClassesToRemoveFromJar(), | ||
138 | + args.webContext, | ||
139 | + args.apiTitle, | ||
140 | + args.apiVersion, | ||
141 | + args.apiPackage, | ||
142 | + args.apiDescription)); | ||
143 | + | ||
144 | + resolver.addToIndex( | ||
145 | + CalculateAbi.of( | ||
146 | + abiJarTarget, | ||
147 | + pathResolver, | ||
148 | + params, | ||
149 | + new BuildTargetSourcePath(defaultJavaLibrary.getBuildTarget()))); | ||
150 | + | ||
151 | + return defaultJavaLibrary; | ||
152 | + } | ||
153 | + | ||
154 | + | ||
155 | + public static class Arg extends JavaLibraryDescription.Arg { | ||
156 | + public Optional<String> webContext; | ||
157 | + public Optional<String> apiTitle; | ||
158 | + public Optional<String> apiVersion; | ||
159 | + public Optional<String> apiPackage; | ||
160 | + public Optional<String> apiDescription; | ||
161 | + } | ||
162 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.onosjar; | ||
17 | + | ||
18 | +import com.facebook.buck.io.ProjectFilesystem; | ||
19 | +import com.facebook.buck.jvm.core.SuggestBuildRules; | ||
20 | +import com.facebook.buck.jvm.java.ClassUsageFileWriter; | ||
21 | +import com.facebook.buck.jvm.java.JarDirectoryStep; | ||
22 | +import com.facebook.buck.jvm.java.JavacOptions; | ||
23 | +import com.facebook.buck.jvm.java.JavacOptionsAmender; | ||
24 | +import com.facebook.buck.jvm.java.JavacToJarStepFactory; | ||
25 | +import com.facebook.buck.model.BuildTarget; | ||
26 | +import com.facebook.buck.rules.BuildContext; | ||
27 | +import com.facebook.buck.rules.BuildableContext; | ||
28 | +import com.facebook.buck.rules.SourcePath; | ||
29 | +import com.facebook.buck.rules.SourcePathResolver; | ||
30 | +import com.facebook.buck.step.Step; | ||
31 | +import com.google.common.base.Optional; | ||
32 | +import com.google.common.collect.ImmutableList; | ||
33 | +import com.google.common.collect.ImmutableSet; | ||
34 | +import com.google.common.collect.ImmutableSortedSet; | ||
35 | + | ||
36 | +import java.nio.file.Path; | ||
37 | +import java.util.regex.Pattern; | ||
38 | +import java.util.stream.Collectors; | ||
39 | + | ||
40 | +/** | ||
41 | + * Creates the list of build steps for the onos_jar rules. | ||
42 | + */ | ||
43 | +public class OnosJarStepFactory extends JavacToJarStepFactory { | ||
44 | + | ||
45 | + private static final String DEFINITIONS = "/definitions/"; | ||
46 | + private final String webContext; | ||
47 | + private final String apiTitle; | ||
48 | + private final String apiVersion; | ||
49 | + private final String apiPackage; | ||
50 | + private final String apiDescription; | ||
51 | + private final Optional<ImmutableSortedSet<SourcePath>> resources; | ||
52 | + | ||
53 | + public OnosJarStepFactory(JavacOptions javacOptions, | ||
54 | + JavacOptionsAmender amender, | ||
55 | + Optional<String> webContext, | ||
56 | + Optional<String> apiTitle, | ||
57 | + Optional<String> apiVersion, | ||
58 | + Optional<String> apiPackage, | ||
59 | + Optional<String> apiDescription, | ||
60 | + Optional<ImmutableSortedSet<SourcePath>> resources) { | ||
61 | + super(javacOptions, amender); | ||
62 | + this.webContext = processParameter(webContext); | ||
63 | + this.apiTitle = processParameter(apiTitle); | ||
64 | + this.apiVersion = processParameter(apiVersion); | ||
65 | + this.apiPackage = processParameter(apiPackage); | ||
66 | + this.apiDescription = processParameter(apiDescription); | ||
67 | + this.resources = resources; | ||
68 | + } | ||
69 | + | ||
70 | + private String processParameter(Optional<String> p) { | ||
71 | + return !p.isPresent() || p.get().equals("NONE") ? null : p.get(); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public void createCompileToJarStep(BuildContext context, | ||
76 | + ImmutableSortedSet<Path> sourceFilePaths, | ||
77 | + BuildTarget invokingRule, | ||
78 | + SourcePathResolver resolver, | ||
79 | + ProjectFilesystem filesystem, | ||
80 | + ImmutableSortedSet<Path> declaredClasspathEntries, | ||
81 | + Path outputDirectory, | ||
82 | + Optional<Path> workingDirectory, | ||
83 | + Path pathToSrcsList, | ||
84 | + Optional<SuggestBuildRules> suggestBuildRules, | ||
85 | + ImmutableList<String> postprocessClassesCommands, | ||
86 | + ImmutableSortedSet<Path> entriesToJar, | ||
87 | + Optional<String> mainClass, | ||
88 | + Optional<Path> manifestFile, | ||
89 | + Path outputJar, | ||
90 | + ClassUsageFileWriter usedClassesFileWriter, | ||
91 | + ImmutableList.Builder<Step> steps, | ||
92 | + BuildableContext buildableContext, | ||
93 | + ImmutableSet<Pattern> classesToRemoveFromJar) { | ||
94 | + | ||
95 | + ImmutableSet.Builder<Path> sourceFilePathBuilder = ImmutableSet.builder(); | ||
96 | + sourceFilePathBuilder.addAll(sourceFilePaths); | ||
97 | + | ||
98 | + ImmutableSet.Builder<Pattern> blacklistBuilder = ImmutableSet.builder(); | ||
99 | + blacklistBuilder.addAll(classesToRemoveFromJar); | ||
100 | + | ||
101 | + // precompilation steps | ||
102 | + // - generate sources | ||
103 | + // add all generated sources ot pathToSrcsList | ||
104 | + if (webContext != null && apiTitle != null && resources.isPresent()) { | ||
105 | + ImmutableSortedSet<Path> resourceFilePaths = findSwaggerModelDefs(resolver, resources.get()); | ||
106 | + blacklistBuilder.addAll(resourceFilePaths.stream() | ||
107 | + .map(rp -> Pattern.compile(rp.getFileName().toString(), Pattern.LITERAL)) | ||
108 | + .collect(Collectors.toSet())); | ||
109 | + Path genSourcesOutput = workingDirectory.get(); | ||
110 | + | ||
111 | + SwaggerStep swaggerStep = new SwaggerStep(filesystem, sourceFilePaths, resourceFilePaths, | ||
112 | + genSourcesOutput, outputDirectory, | ||
113 | + webContext, apiTitle, apiVersion, | ||
114 | + apiPackage, apiDescription); | ||
115 | + sourceFilePathBuilder.add(swaggerStep.apiRegistratorPath()); | ||
116 | + steps.add(swaggerStep); | ||
117 | + } | ||
118 | + | ||
119 | + createCompileStep(context, | ||
120 | + ImmutableSortedSet.copyOf(sourceFilePathBuilder.build()), | ||
121 | + invokingRule, | ||
122 | + resolver, | ||
123 | + filesystem, | ||
124 | + declaredClasspathEntries, | ||
125 | + outputDirectory, | ||
126 | + workingDirectory, | ||
127 | + pathToSrcsList, | ||
128 | + suggestBuildRules, | ||
129 | + usedClassesFileWriter, | ||
130 | + steps, | ||
131 | + buildableContext); | ||
132 | + | ||
133 | + // post compilation steps | ||
134 | + | ||
135 | + // FIXME BOC: add mechanism to inject new Steps | ||
136 | + //context.additionalStepFactory(JavaStep.class); | ||
137 | + | ||
138 | + // build the jar | ||
139 | + steps.add(new JarDirectoryStep(filesystem, | ||
140 | + outputJar, | ||
141 | + ImmutableSortedSet.of(outputDirectory), | ||
142 | + mainClass.orNull(), | ||
143 | + manifestFile.orNull(), | ||
144 | + true, | ||
145 | + blacklistBuilder.build())); | ||
146 | + } | ||
147 | + | ||
148 | + private ImmutableSortedSet<Path> findSwaggerModelDefs(SourcePathResolver resolver, | ||
149 | + ImmutableSortedSet<SourcePath> resourcePaths) { | ||
150 | + if (resourcePaths == null) { | ||
151 | + return ImmutableSortedSet.of(); | ||
152 | + } | ||
153 | + return ImmutableSortedSet.copyOf(resourcePaths.stream() | ||
154 | + .filter(sp -> sp.toString().contains(DEFINITIONS)) | ||
155 | + .map(resolver::getRelativePath) | ||
156 | + .collect(Collectors.toList())); | ||
157 | + } | ||
158 | +} |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.onosjar; | ||
18 | + | ||
19 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
20 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
21 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
22 | +import com.google.common.io.ByteStreams; | ||
23 | +import com.google.common.io.Files; | ||
24 | +import com.thoughtworks.qdox.JavaProjectBuilder; | ||
25 | +import com.thoughtworks.qdox.model.DocletTag; | ||
26 | +import com.thoughtworks.qdox.model.JavaAnnotation; | ||
27 | +import com.thoughtworks.qdox.model.JavaClass; | ||
28 | +import com.thoughtworks.qdox.model.JavaMethod; | ||
29 | +import com.thoughtworks.qdox.model.JavaParameter; | ||
30 | +import com.thoughtworks.qdox.model.JavaType; | ||
31 | + | ||
32 | +import java.io.File; | ||
33 | +import java.io.FileWriter; | ||
34 | +import java.io.IOException; | ||
35 | +import java.io.PrintWriter; | ||
36 | +import java.util.HashMap; | ||
37 | +import java.util.List; | ||
38 | +import java.util.Map; | ||
39 | +import java.util.Optional; | ||
40 | + | ||
41 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
42 | + | ||
43 | +/** | ||
44 | + * Generates Swagger JSON artifacts from the Java source files. | ||
45 | + */ | ||
46 | +public class SwaggerGenerator { | ||
47 | + | ||
48 | + private final ObjectMapper mapper = new ObjectMapper(); | ||
49 | + | ||
50 | + private static final String JSON_FILE = "swagger.json"; | ||
51 | + private static final String GEN_SRC = "generated-sources"; | ||
52 | + private static final String REG_SRC = "/registrator.javat"; | ||
53 | + | ||
54 | + private static final String PATH = "javax.ws.rs.Path"; | ||
55 | + private static final String PATH_PARAM = "javax.ws.rs.PathParam"; | ||
56 | + private static final String QUERY_PARAM = "javax.ws.rs.QueryParam"; | ||
57 | + private static final String POST = "javax.ws.rs.POST"; | ||
58 | + private static final String GET = "javax.ws.rs.GET"; | ||
59 | + private static final String PUT = "javax.ws.rs.PUT"; | ||
60 | + private static final String DELETE = "javax.ws.rs.DELETE"; | ||
61 | + private static final String PRODUCES = "javax.ws.rs.Produces"; | ||
62 | + private static final String CONSUMES = "javax.ws.rs.Consumes"; | ||
63 | + private static final String JSON = "MediaType.APPLICATION_JSON"; | ||
64 | + private static final String OCTET_STREAM = "MediaType.APPLICATION_OCTET_STREAM"; | ||
65 | + | ||
66 | + private final List<File> srcs; | ||
67 | + private final List<File> resources; | ||
68 | + private final File srcDirectory; | ||
69 | + private final File resourceDirectory; | ||
70 | + private final File genSrcOutputDirectory; | ||
71 | + private final File genResourcesOutputDirectory; | ||
72 | + private final String webContext; | ||
73 | + private final String apiTitle; | ||
74 | + private final String apiVersion; | ||
75 | + private final String apiPackage; | ||
76 | + private final String apiDescription; | ||
77 | + | ||
78 | + public SwaggerGenerator(List<File> srcs, List<File> resources, | ||
79 | + File srcDirectory, File resourceDirectory, | ||
80 | + File genSrcOutputDirectory, File genResourcesOutputDirectory, | ||
81 | + String webContext, String apiTitle, String apiVersion, | ||
82 | + String apiPackage, String apiDescription) { | ||
83 | + this.srcs = srcs; | ||
84 | + this.resources = resources; | ||
85 | + this.srcDirectory = srcDirectory; | ||
86 | + this.resourceDirectory = resourceDirectory; | ||
87 | + this.genSrcOutputDirectory = genSrcOutputDirectory; | ||
88 | + this.genResourcesOutputDirectory = genResourcesOutputDirectory; | ||
89 | + this.webContext = webContext; | ||
90 | + | ||
91 | + this.apiTitle = apiTitle; | ||
92 | + this.apiVersion = apiVersion; | ||
93 | + this.apiPackage = apiPackage; | ||
94 | + this.apiDescription = apiDescription; | ||
95 | + } | ||
96 | + | ||
97 | + public void execute() { | ||
98 | + try { | ||
99 | + JavaProjectBuilder builder = new JavaProjectBuilder(); | ||
100 | + if (srcDirectory != null) { | ||
101 | + builder.addSourceTree(new File(srcDirectory, "src/main/java")); | ||
102 | + } | ||
103 | + if (srcs != null) { | ||
104 | + srcs.forEach(src -> { | ||
105 | + try { | ||
106 | + builder.addSource(src); | ||
107 | + } catch (IOException e) { | ||
108 | + throw new RuntimeException(e); | ||
109 | + } | ||
110 | + }); | ||
111 | + } | ||
112 | + | ||
113 | + ObjectNode root = initializeRoot(webContext, apiTitle, apiVersion, apiDescription); | ||
114 | + ArrayNode tags = mapper.createArrayNode(); | ||
115 | + ObjectNode paths = mapper.createObjectNode(); | ||
116 | + ObjectNode definitions = mapper.createObjectNode(); | ||
117 | + | ||
118 | + root.set("tags", tags); | ||
119 | + root.set("paths", paths); | ||
120 | + root.set("definitions", definitions); | ||
121 | + | ||
122 | + // TODO: Process resources to allow lookup of files by name | ||
123 | + | ||
124 | + builder.getClasses().forEach(jc -> processClass(jc, paths, tags, definitions, srcDirectory)); | ||
125 | + | ||
126 | + if (paths.size() > 0) { | ||
127 | + genCatalog(genResourcesOutputDirectory, root); | ||
128 | + if (!isNullOrEmpty(apiPackage)) { | ||
129 | + genRegistrator(genSrcOutputDirectory, webContext, apiTitle, apiVersion, | ||
130 | + apiPackage, apiDescription); | ||
131 | + } | ||
132 | + } | ||
133 | + } catch (Exception e) { | ||
134 | + e.printStackTrace(); | ||
135 | + throw new RuntimeException("Unable to generate ONOS REST API documentation", e); | ||
136 | + } | ||
137 | + } | ||
138 | + | ||
139 | + // initializes top level root with Swagger required specifications | ||
140 | + private ObjectNode initializeRoot(String webContext, String apiTitle, | ||
141 | + String apiVersion, String apiDescription) { | ||
142 | + ObjectNode root = mapper.createObjectNode(); | ||
143 | + root.put("swagger", "2.0"); | ||
144 | + ObjectNode info = mapper.createObjectNode(); | ||
145 | + root.set("info", info); | ||
146 | + | ||
147 | + root.put("basePath", webContext); | ||
148 | + info.put("version", apiVersion); | ||
149 | + info.put("title", apiTitle); | ||
150 | + info.put("description", apiDescription); | ||
151 | + | ||
152 | + ArrayNode produces = mapper.createArrayNode(); | ||
153 | + produces.add("application/json"); | ||
154 | + root.set("produces", produces); | ||
155 | + | ||
156 | + ArrayNode consumes = mapper.createArrayNode(); | ||
157 | + consumes.add("application/json"); | ||
158 | + root.set("consumes", consumes); | ||
159 | + | ||
160 | + return root; | ||
161 | + } | ||
162 | + | ||
163 | + // Checks whether javaClass has a path tag associated with it and if it does | ||
164 | + // processes its methods and creates a tag for the class on the root | ||
165 | + void processClass(JavaClass javaClass, ObjectNode paths, ArrayNode tags, | ||
166 | + ObjectNode definitions, File srcDirectory) { | ||
167 | + // If the class does not have a Path tag then ignore it | ||
168 | + JavaAnnotation annotation = getPathAnnotation(javaClass); | ||
169 | + if (annotation == null) { | ||
170 | + return; | ||
171 | + } | ||
172 | + | ||
173 | + String path = getPath(annotation); | ||
174 | + if (path == null) { | ||
175 | + return; | ||
176 | + } | ||
177 | + | ||
178 | + String resourcePath = "/" + path; | ||
179 | + String tagPath = path.isEmpty() ? "/" : path; | ||
180 | + | ||
181 | + // Create tag node for this class. | ||
182 | + ObjectNode tagObject = mapper.createObjectNode(); | ||
183 | + tagObject.put("name", tagPath); | ||
184 | + if (javaClass.getComment() != null) { | ||
185 | + tagObject.put("description", shortText(javaClass.getComment())); | ||
186 | + } | ||
187 | + tags.add(tagObject); | ||
188 | + | ||
189 | + // Create an array node add to all methods from this class. | ||
190 | + ArrayNode tagArray = mapper.createArrayNode(); | ||
191 | + tagArray.add(tagPath); | ||
192 | + | ||
193 | + processAllMethods(javaClass, resourcePath, paths, tagArray, definitions, srcDirectory); | ||
194 | + } | ||
195 | + | ||
196 | + private JavaAnnotation getPathAnnotation(JavaClass javaClass) { | ||
197 | + Optional<JavaAnnotation> optional = javaClass.getAnnotations() | ||
198 | + .stream().filter(a -> a.getType().getName().equals(PATH)).findAny(); | ||
199 | + return optional.orElse(null); | ||
200 | + } | ||
201 | + | ||
202 | + // Checks whether a class's methods are REST methods and then places all the | ||
203 | + // methods under a specific path into the paths node | ||
204 | + private void processAllMethods(JavaClass javaClass, String resourcePath, | ||
205 | + ObjectNode paths, ArrayNode tagArray, ObjectNode definitions, | ||
206 | + File srcDirectory) { | ||
207 | + // map of the path to its methods represented by an ObjectNode | ||
208 | + Map<String, ObjectNode> pathMap = new HashMap<>(); | ||
209 | + | ||
210 | + javaClass.getMethods().forEach(javaMethod -> { | ||
211 | + javaMethod.getAnnotations().forEach(annotation -> { | ||
212 | + String name = annotation.getType().getName(); | ||
213 | + if (name.equals(POST) || name.equals(GET) || name.equals(DELETE) || name.equals(PUT)) { | ||
214 | + // substring(12) removes "javax.ws.rs." | ||
215 | + String method = annotation.getType().toString().substring(12).toLowerCase(); | ||
216 | + processRestMethod(javaMethod, method, pathMap, resourcePath, tagArray, definitions, srcDirectory); | ||
217 | + } | ||
218 | + }); | ||
219 | + }); | ||
220 | + | ||
221 | + // for each path add its methods to the path node | ||
222 | + for (Map.Entry<String, ObjectNode> entry : pathMap.entrySet()) { | ||
223 | + paths.set(entry.getKey(), entry.getValue()); | ||
224 | + } | ||
225 | + | ||
226 | + | ||
227 | + } | ||
228 | + | ||
229 | + private void processRestMethod(JavaMethod javaMethod, String method, | ||
230 | + Map<String, ObjectNode> pathMap, | ||
231 | + String resourcePath, ArrayNode tagArray, | ||
232 | + ObjectNode definitions, File srcDirectory) { | ||
233 | + String fullPath = resourcePath, consumes = "", produces = "", | ||
234 | + comment = javaMethod.getComment(); | ||
235 | + DocletTag tag = javaMethod.getTagByName("onos.rsModel"); | ||
236 | + for (JavaAnnotation annotation : javaMethod.getAnnotations()) { | ||
237 | + String name = annotation.getType().getName(); | ||
238 | + if (name.equals(PATH)) { | ||
239 | + fullPath = resourcePath + "/" + getPath(annotation); | ||
240 | + fullPath = fullPath.replaceFirst("^//", "/"); | ||
241 | + } | ||
242 | + if (name.equals(CONSUMES)) { | ||
243 | + consumes = getIOType(annotation); | ||
244 | + } | ||
245 | + if (name.equals(PRODUCES)) { | ||
246 | + produces = getIOType(annotation); | ||
247 | + } | ||
248 | + } | ||
249 | + ObjectNode methodNode = mapper.createObjectNode(); | ||
250 | + methodNode.set("tags", tagArray); | ||
251 | + | ||
252 | + addSummaryDescriptions(methodNode, comment); | ||
253 | + addJsonSchemaDefinition(srcDirectory, definitions, tag); | ||
254 | + | ||
255 | + processParameters(javaMethod, methodNode, method, tag); | ||
256 | + | ||
257 | + processConsumesProduces(methodNode, "consumes", consumes); | ||
258 | + processConsumesProduces(methodNode, "produces", produces); | ||
259 | + if (tag == null || ((method.toLowerCase().equals("post") || method.toLowerCase().equals("put")) | ||
260 | + && !(tag.getParameters().size() > 1))) { | ||
261 | + addResponses(methodNode, tag, false); | ||
262 | + } else { | ||
263 | + addResponses(methodNode, tag, true); | ||
264 | + } | ||
265 | + | ||
266 | + ObjectNode operations = pathMap.get(fullPath); | ||
267 | + if (operations == null) { | ||
268 | + operations = mapper.createObjectNode(); | ||
269 | + operations.set(method, methodNode); | ||
270 | + pathMap.put(fullPath, operations); | ||
271 | + } else { | ||
272 | + operations.set(method, methodNode); | ||
273 | + } | ||
274 | + } | ||
275 | + | ||
276 | + private void addJsonSchemaDefinition(File srcDirectory, ObjectNode definitions, DocletTag tag) { | ||
277 | + final File definitionsDirectory; | ||
278 | + if (resourceDirectory != null) { | ||
279 | + definitionsDirectory = new File(resourceDirectory, "definitions"); | ||
280 | + } else if (srcDirectory != null) { | ||
281 | + definitionsDirectory = new File(srcDirectory + "/src/main/resources/definitions"); | ||
282 | + } else { | ||
283 | + definitionsDirectory = null; | ||
284 | + } | ||
285 | + if (tag != null) { | ||
286 | + tag.getParameters().forEach(param -> { | ||
287 | + try { | ||
288 | + File config; | ||
289 | + if (definitionsDirectory != null) { | ||
290 | + config = new File(definitionsDirectory.getAbsolutePath() + "/" + param + ".json"); | ||
291 | + } else { | ||
292 | + config = resources.stream().filter(f -> f.getName().equals(param + ".json")).findFirst().orElse(null); | ||
293 | + } | ||
294 | + definitions.set(param, mapper.readTree(config)); | ||
295 | + } catch (IOException e) { | ||
296 | + throw new RuntimeException(String.format("Could not process %s in %s@%s: %s", | ||
297 | + tag.getName(), tag.getContext(), tag.getLineNumber(), | ||
298 | + e.getMessage()), e); | ||
299 | + } | ||
300 | + }); | ||
301 | + } | ||
302 | + } | ||
303 | + | ||
304 | + private void processConsumesProduces(ObjectNode methodNode, String type, String io) { | ||
305 | + if (!io.equals("")) { | ||
306 | + ArrayNode array = mapper.createArrayNode(); | ||
307 | + methodNode.set(type, array); | ||
308 | + array.add(io); | ||
309 | + } | ||
310 | + } | ||
311 | + | ||
312 | + private void addSummaryDescriptions(ObjectNode methodNode, String comment) { | ||
313 | + String summary = "", description; | ||
314 | + if (comment != null) { | ||
315 | + if (comment.contains(".")) { | ||
316 | + int periodIndex = comment.indexOf("."); | ||
317 | + summary = comment.substring(0, periodIndex); | ||
318 | + description = comment.length() > periodIndex + 1 ? | ||
319 | + comment.substring(periodIndex + 1).trim() : ""; | ||
320 | + } else { | ||
321 | + description = comment; | ||
322 | + } | ||
323 | + methodNode.put("summary", summary); | ||
324 | + methodNode.put("description", description); | ||
325 | + } | ||
326 | + } | ||
327 | + | ||
328 | + // Temporary solution to add responses to a method | ||
329 | + private void addResponses(ObjectNode methodNode, DocletTag tag, boolean responseJson) { | ||
330 | + ObjectNode responses = mapper.createObjectNode(); | ||
331 | + methodNode.set("responses", responses); | ||
332 | + | ||
333 | + ObjectNode success = mapper.createObjectNode(); | ||
334 | + success.put("description", "successful operation"); | ||
335 | + responses.set("200", success); | ||
336 | + if (tag != null && responseJson) { | ||
337 | + ObjectNode schema = mapper.createObjectNode(); | ||
338 | + tag.getParameters().stream().forEach( | ||
339 | + param -> schema.put("$ref", "#/definitions/" + param)); | ||
340 | + success.set("schema", schema); | ||
341 | + } | ||
342 | + | ||
343 | + ObjectNode defaultObj = mapper.createObjectNode(); | ||
344 | + defaultObj.put("description", "Unexpected error"); | ||
345 | + responses.set("default", defaultObj); | ||
346 | + } | ||
347 | + | ||
348 | + // Checks if the annotations has a value of JSON and returns the string | ||
349 | + // that Swagger requires | ||
350 | + private String getIOType(JavaAnnotation annotation) { | ||
351 | + if (annotation.getNamedParameter("value").toString().equals(JSON)) { | ||
352 | + return "application/json"; | ||
353 | + } else if (annotation.getNamedParameter("value").toString().equals(OCTET_STREAM)) { | ||
354 | + return "application/octet_stream"; | ||
355 | + } | ||
356 | + return ""; | ||
357 | + } | ||
358 | + | ||
359 | + // If the annotation has a Path tag, returns the value with leading and | ||
360 | + // trailing double quotes and slash removed. | ||
361 | + private String getPath(JavaAnnotation annotation) { | ||
362 | + String path = annotation.getNamedParameter("value").toString(); | ||
363 | + return path == null ? null : path.replaceAll("(^[\\\"/]*|[/\\\"]*$)", ""); | ||
364 | + } | ||
365 | + | ||
366 | + // Processes parameters of javaMethod and enters the proper key-values into the methodNode | ||
367 | + private void processParameters(JavaMethod javaMethod, ObjectNode methodNode, String method, DocletTag tag) { | ||
368 | + ArrayNode parameters = mapper.createArrayNode(); | ||
369 | + methodNode.set("parameters", parameters); | ||
370 | + boolean required = true; | ||
371 | + | ||
372 | + for (JavaParameter javaParameter : javaMethod.getParameters()) { | ||
373 | + ObjectNode individualParameterNode = mapper.createObjectNode(); | ||
374 | + Optional<JavaAnnotation> optional = javaParameter.getAnnotations().stream().filter( | ||
375 | + annotation -> annotation.getType().getName().equals(PATH_PARAM) || | ||
376 | + annotation.getType().getName().equals(QUERY_PARAM)).findAny(); | ||
377 | + JavaAnnotation pathType = optional.orElse(null); | ||
378 | + | ||
379 | + String annotationName = javaParameter.getName(); | ||
380 | + | ||
381 | + | ||
382 | + if (pathType != null) { //the parameter is a path or query parameter | ||
383 | + individualParameterNode.put("name", | ||
384 | + pathType.getNamedParameter("value") | ||
385 | + .toString().replace("\"", "")); | ||
386 | + if (pathType.getType().getName().equals(PATH_PARAM)) { | ||
387 | + individualParameterNode.put("in", "path"); | ||
388 | + } else if (pathType.getType().getName().equals(QUERY_PARAM)) { | ||
389 | + individualParameterNode.put("in", "query"); | ||
390 | + } | ||
391 | + individualParameterNode.put("type", getType(javaParameter.getType())); | ||
392 | + } else { // the parameter is a body parameter | ||
393 | + individualParameterNode.put("name", annotationName); | ||
394 | + individualParameterNode.put("in", "body"); | ||
395 | + | ||
396 | + // Adds the reference to the Json model for the input | ||
397 | + // that goes in the post or put operation | ||
398 | + if (tag != null && (method.toLowerCase().equals("post") || | ||
399 | + method.toLowerCase().equals("put"))) { | ||
400 | + ObjectNode schema = mapper.createObjectNode(); | ||
401 | + tag.getParameters().stream().forEach(param -> { | ||
402 | + schema.put("$ref", "#/definitions/" + param); | ||
403 | + }); | ||
404 | + individualParameterNode.set("schema", schema); | ||
405 | + } | ||
406 | + } | ||
407 | + for (DocletTag p : javaMethod.getTagsByName("param")) { | ||
408 | + if (p.getValue().contains(annotationName)) { | ||
409 | + String description = ""; | ||
410 | + if (p.getValue().split(" ", 2).length >= 2) { | ||
411 | + description = p.getValue().split(" ", 2)[1].trim(); | ||
412 | + if (description.contains("optional")) { | ||
413 | + required = false; | ||
414 | + } | ||
415 | + } else { | ||
416 | + throw new RuntimeException(String.format("No description for parameter \"%s\" in " + | ||
417 | + "method \"%s\" in %s (line %d)", | ||
418 | + p.getValue(), javaMethod.getName(), | ||
419 | + javaMethod.getDeclaringClass().getName(), | ||
420 | + javaMethod.getLineNumber())); | ||
421 | + } | ||
422 | + individualParameterNode.put("description", description); | ||
423 | + } | ||
424 | + } | ||
425 | + individualParameterNode.put("required", required); | ||
426 | + parameters.add(individualParameterNode); | ||
427 | + } | ||
428 | + } | ||
429 | + | ||
430 | + // Returns the Swagger specified strings for the type of a parameter | ||
431 | + private String getType(JavaType javaType) { | ||
432 | + String type = javaType.getFullyQualifiedName(); | ||
433 | + String value; | ||
434 | + if (type.equals(String.class.getName())) { | ||
435 | + value = "string"; | ||
436 | + } else if (type.equals("int")) { | ||
437 | + value = "integer"; | ||
438 | + } else if (type.equals(boolean.class.getName())) { | ||
439 | + value = "boolean"; | ||
440 | + } else if (type.equals(long.class.getName())) { | ||
441 | + value = "number"; | ||
442 | + } else { | ||
443 | + value = ""; | ||
444 | + } | ||
445 | + return value; | ||
446 | + } | ||
447 | + | ||
448 | + // Writes the swagger.json file using the supplied JSON root. | ||
449 | + private void genCatalog(File dstDirectory, ObjectNode root) { | ||
450 | + File swaggerCfg = new File(dstDirectory, JSON_FILE); | ||
451 | + if (dstDirectory.exists() || dstDirectory.mkdirs()) { | ||
452 | + try (FileWriter fw = new FileWriter(swaggerCfg); | ||
453 | + PrintWriter pw = new PrintWriter(fw)) { | ||
454 | + pw.println(root.toString()); | ||
455 | + } catch (IOException e) { | ||
456 | + throw new RuntimeException("Unable to write " + JSON_FILE, e); | ||
457 | + } | ||
458 | + } else { | ||
459 | + throw new RuntimeException("Unable to create " + dstDirectory); | ||
460 | + } | ||
461 | + } | ||
462 | + | ||
463 | + // Generates the registrator Java component. | ||
464 | + private void genRegistrator(File dstDirectory, String webContext, | ||
465 | + String apiTitle, String apiVersion, | ||
466 | + String apiPackage, String apiDescription) { | ||
467 | + File dir = new File(dstDirectory, resourceDirectory != null ? GEN_SRC : "."); | ||
468 | + File reg = new File(dir, apiRegistratorPath(apiPackage)); | ||
469 | + File pkg = reg.getParentFile(); | ||
470 | + if (pkg.exists() || pkg.mkdirs()) { | ||
471 | + try { | ||
472 | + String src = new String(ByteStreams.toByteArray(getClass().getResourceAsStream(REG_SRC))); | ||
473 | + src = src.replace("${api.package}", apiPackage) | ||
474 | + .replace("${web.context}", webContext) | ||
475 | + .replace("${api.title}", apiTitle) | ||
476 | + .replace("${api.description}", apiDescription); | ||
477 | + Files.write(src.getBytes(), reg); | ||
478 | + } catch (IOException e) { | ||
479 | + throw new RuntimeException("Unable to write " + reg, e); | ||
480 | + } | ||
481 | + } else { | ||
482 | + throw new RuntimeException("Unable to create " + reg); | ||
483 | + } | ||
484 | + } | ||
485 | + | ||
486 | + private String shortText(String comment) { | ||
487 | + int i = comment.indexOf('.'); | ||
488 | + return i > 0 ? comment.substring(0, i) : comment; | ||
489 | + } | ||
490 | + | ||
491 | + public static String apiRegistratorPath(String apiPackage) { | ||
492 | + return apiPackage.replaceAll("\\.", "/") + "/ApiDocRegistrator.java"; | ||
493 | + } | ||
494 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.onosjar; | ||
17 | + | ||
18 | +import com.facebook.buck.io.ProjectFilesystem; | ||
19 | +import com.facebook.buck.rules.SourcePathResolver; | ||
20 | +import com.facebook.buck.step.AbstractExecutionStep; | ||
21 | +import com.facebook.buck.step.ExecutionContext; | ||
22 | +import com.facebook.buck.step.StepExecutionResult; | ||
23 | +import com.google.common.collect.ImmutableSortedSet; | ||
24 | + | ||
25 | +import java.io.File; | ||
26 | +import java.io.IOException; | ||
27 | +import java.nio.file.Path; | ||
28 | +import java.util.List; | ||
29 | +import java.util.stream.Collectors; | ||
30 | + | ||
31 | +/** | ||
32 | + * Buck build step to trigger SwaggerGenerator. | ||
33 | + */ | ||
34 | +public class SwaggerStep extends AbstractExecutionStep { | ||
35 | + | ||
36 | + private final ProjectFilesystem filesystem; | ||
37 | + | ||
38 | + private final ImmutableSortedSet<Path> srcs; | ||
39 | + private final ImmutableSortedSet<Path> resources; | ||
40 | + private final Path genSourcesOutput; | ||
41 | + private final Path genResourcesOutput; | ||
42 | + | ||
43 | + private final String webContext; | ||
44 | + private final String apiTitle; | ||
45 | + private final String apiVersion; | ||
46 | + private final String apiPackage; | ||
47 | + private final String apiDescription; | ||
48 | + | ||
49 | + | ||
50 | + public SwaggerStep(ProjectFilesystem filesystem, | ||
51 | + ImmutableSortedSet<Path> srcs, | ||
52 | + ImmutableSortedSet<Path> resources, | ||
53 | + Path genSourcesOutput, Path genResourcesOutput, | ||
54 | + String webContext, String apiTitle, String apiVersion, | ||
55 | + String apiPackage, String apiDescription) { | ||
56 | + super("swagger"); | ||
57 | + this.filesystem = filesystem; | ||
58 | + this.srcs = srcs; | ||
59 | + this.resources = resources; | ||
60 | + this.genSourcesOutput = genSourcesOutput; | ||
61 | + this.genResourcesOutput = genResourcesOutput; | ||
62 | + this.webContext = webContext; | ||
63 | + this.apiTitle = apiTitle; | ||
64 | + this.apiVersion = apiVersion; | ||
65 | + this.apiPackage = apiPackage; | ||
66 | + this.apiDescription = apiDescription; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public StepExecutionResult execute(ExecutionContext executionContext) | ||
71 | + throws IOException, InterruptedException { | ||
72 | + try { | ||
73 | + List<File> srcFiles = srcs.stream() | ||
74 | + .map(src -> filesystem.resolve(src).toFile()) | ||
75 | + .collect(Collectors.toList()); | ||
76 | + List<File> resourceFiles = resources.stream() | ||
77 | + .map(rsrc -> filesystem.resolve(rsrc).toFile()) | ||
78 | + .collect(Collectors.toList()); | ||
79 | + new SwaggerGenerator(srcFiles, resourceFiles, null, null, | ||
80 | + filesystem.resolve(genSourcesOutput).toFile(), | ||
81 | + filesystem.resolve(genResourcesOutput).toFile(), | ||
82 | + webContext, | ||
83 | + apiTitle, | ||
84 | + apiVersion, | ||
85 | + apiPackage, | ||
86 | + apiDescription).execute(); | ||
87 | + | ||
88 | + return StepExecutionResult.SUCCESS; | ||
89 | + } catch (Exception e) { | ||
90 | + e.printStackTrace(); | ||
91 | + // FIXME print the exception | ||
92 | + return StepExecutionResult.ERROR; | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + Path apiRegistratorPath() { | ||
97 | + return genSourcesOutput.resolve(SwaggerGenerator.apiRegistratorPath(apiPackage)); | ||
98 | + } | ||
99 | +} |
1 | +/* | ||
2 | + * Auto-generated by OnosSwaggerMojo. | ||
3 | + * | ||
4 | + * Copyright 2015-present Open Networking Laboratory | ||
5 | + * | ||
6 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + * you may not use this file except in compliance with the License. | ||
8 | + * You may obtain a copy of the License at | ||
9 | + * | ||
10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + * | ||
12 | + * Unless required by applicable law or agreed to in writing, software | ||
13 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + * See the License for the specific language governing permissions and | ||
16 | + * limitations under the License. | ||
17 | + */ | ||
18 | +package ${api.package}; | ||
19 | + | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.onosproject.rest.AbstractApiDocRegistrator; | ||
22 | +import org.onosproject.rest.ApiDocProvider; | ||
23 | + | ||
24 | +@Component(immediate = true) | ||
25 | +public class ApiDocRegistrator extends AbstractApiDocRegistrator { | ||
26 | + public ApiDocRegistrator() { | ||
27 | + super(new ApiDocProvider("${web.context}", | ||
28 | + "${api.title}", | ||
29 | + ApiDocRegistrator.class.getClassLoader())); | ||
30 | + } | ||
31 | +} |
... | @@ -34,5 +34,29 @@ if [ -n "$FORCE_UPDATE" ] || [ ! -f "buck" ] || [ "$REQUIRED_VERSION" != "$(cat | ... | @@ -34,5 +34,29 @@ if [ -n "$FORCE_UPDATE" ] || [ ! -f "buck" ] || [ "$REQUIRED_VERSION" != "$(cat |
34 | fi | 34 | fi |
35 | popd > /dev/null | 35 | popd > /dev/null |
36 | 36 | ||
37 | +BUCK=$ONOS_ROOT/bin/buck | ||
38 | +PLUGINS=$ONOS_ROOT/bucklets/plugins | ||
39 | +ONOS_PLUGIN=$PLUGINS/onosjar.jar | ||
40 | + | ||
41 | +if [ ! -f "$ONOS_PLUGIN" -o -n "$ONOS_BUILD_PLUGIN" ]; then | ||
42 | + echo "Building ONOS Buck plugins..." | ||
43 | + | ||
44 | + # Build it first | ||
45 | + pluginJar=$(NO_BUCKD=1 $BUCK build //tools/build/buck-plugin:onosjar --show-output 2>/dev/null | grep onosjar.jar | cut -d\ -f2) | ||
46 | + | ||
47 | + CHK_NEW=$(cksum $pluginJar | cut -d' ' -f1-2) | ||
48 | + CHK_OLD=$(cksum $ONOS_PLUGIN 2>/dev/null | cut -d' ' -f1-2) | ||
49 | + if [ "$CHK_NEW" != "$CHK_OLD" ]; then | ||
50 | + # diff plugins... if different, copy and restart buckd | ||
51 | + # Then install it | ||
52 | + mkdir -p $PLUGINS | ||
53 | + cp $ONOS_ROOT/$pluginJar $PLUGINS | ||
54 | + echo "Updated to the latest plugin." | ||
55 | + $BUCK clean 2>/dev/null | ||
56 | + else | ||
57 | + echo "Plugin was already up to date." | ||
58 | + fi | ||
59 | +fi | ||
60 | + | ||
37 | # Finally, run the Buck command... | 61 | # Finally, run the Buck command... |
38 | -$ONOS_ROOT/bin/buck "$@" | 62 | +$BUCK "$@" | ... | ... |
... | @@ -14,4 +14,8 @@ osgi_jar_with_tests ( | ... | @@ -14,4 +14,8 @@ osgi_jar_with_tests ( |
14 | deps = COMPILE_DEPS, | 14 | deps = COMPILE_DEPS, |
15 | test_deps = TEST_DEPS, | 15 | test_deps = TEST_DEPS, |
16 | web_context = '/onos/v1', | 16 | web_context = '/onos/v1', |
17 | + api_title = 'ONOS Core REST API', | ||
18 | + api_version = '1.0', | ||
19 | + api_description = 'ONOS Core REST API', | ||
20 | + api_package = 'org.onosproject.rest.impl', | ||
17 | ) | 21 | ) | ... | ... |
-
Please register or login to post a comment