Brian O'Connor
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
1 [buildfile] 1 [buildfile]
2 includes = //buck-tools/default.defs 2 includes = //buck-tools/default.defs
3 3
4 +[plugins]
5 + directory = //bucklets/plugins
6 +
4 [java] 7 [java]
5 source_level = 8 8 source_level = 8
6 target_level = 8 9 target_level = 8
......
...@@ -17,6 +17,7 @@ localDB.* ...@@ -17,6 +17,7 @@ localDB.*
17 .buckd 17 .buckd
18 buck-out 18 buck-out
19 .buckconfig.local 19 .buckconfig.local
20 +.buckjavaargs*
20 21
21 core/store/trivial/data/ 22 core/store/trivial/data/
22 core/store/apps 23 core/store/apps
......
...@@ -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,
......
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
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
1 +#!/bin/bash
2 +
3 +NO_BUCKD=1 buck build //apps/dhcp/app:onos-apps-dhcp-app --no-cache --show-output
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 )
......