This is an automated email from the ASF dual-hosted git repository.
iuliana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new 5d6f0ea make swagger classes extensible
new b2f7806 Merge pull request #1149 from ahgittin/swagger-improvements
5d6f0ea is described below
commit 5d6f0ea87410715d71390f1d9e711fc5b5202b44
Author: Alex Heneveld <[email protected]>
AuthorDate: Mon Feb 15 14:57:55 2021 +0000
make swagger classes extensible
so add'l projects can add classes to be documented
---
.../apache/brooklyn/camp/server/RestApiSetup.java | 2 +-
.../brooklyn/rest/resources/ApidocResource.java | 26 ++++++++
.../brooklyn/rest/util/ScannerInjectHelper.java | 2 +-
.../rest/resources/ApidocResourceTest.java | 2 +-
.../org/apache/brooklyn/rest/RestApiSetup.java | 2 +-
.../rest/apidoc/RestApiResourceScanner.java | 74 ++++++++++++++++------
6 files changed, 86 insertions(+), 22 deletions(-)
diff --git
a/camp/camp-server/src/main/java/org/apache/brooklyn/camp/server/RestApiSetup.java
b/camp/camp-server/src/main/java/org/apache/brooklyn/camp/server/RestApiSetup.java
index 302dff8..ab94527 100644
---
a/camp/camp-server/src/main/java/org/apache/brooklyn/camp/server/RestApiSetup.java
+++
b/camp/camp-server/src/main/java/org/apache/brooklyn/camp/server/RestApiSetup.java
@@ -28,7 +28,7 @@ import io.swagger.config.ScannerFactory;
public class RestApiSetup {
public static void install(ServletContextHandler context) {
- ScannerFactory.setScanner(new RestApiResourceScanner());
+ RestApiResourceScanner.install(null);
CampRestApp app = new CampRestApp();
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApidocResource.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApidocResource.java
index 7372288..0be166f 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApidocResource.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApidocResource.java
@@ -19,10 +19,16 @@
package org.apache.brooklyn.rest.resources;
+import javax.servlet.ServletConfig;
import javax.ws.rs.Path;
import io.swagger.annotations.Api;
import io.swagger.jaxrs.listing.ApiListingResource;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import org.apache.brooklyn.rest.apidoc.RestApiResourceScanner;
/**
* @author Ciprian Ciubotariu <[email protected]>
@@ -31,4 +37,24 @@ import io.swagger.jaxrs.listing.ApiListingResource;
@Path("/apidoc")
public class ApidocResource extends ApiListingResource {
+ private void preprocess(Application app, ServletConfig sc) {
+ RestApiResourceScanner.rescanIfNeeded(() -> scan(app, sc));
+ }
+
+ @Override
+ public Response getListing(Application app, ServletConfig sc, HttpHeaders
headers, UriInfo uriInfo, String type) {
+ preprocess(app, sc);
+ return super.getListing(app, sc, headers, uriInfo, type);
+ }
+
+ @Override
+ public Response getListingJson(Application app, ServletConfig sc,
HttpHeaders headers, UriInfo uriInfo) {
+ return super.getListingJson(app, sc, headers, uriInfo);
+ }
+
+ @Override
+ public Response getListingYaml(Application app, ServletConfig sc,
HttpHeaders headers, UriInfo uriInfo) {
+ return super.getListingYaml(app, sc, headers, uriInfo);
+ }
+
}
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ScannerInjectHelper.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ScannerInjectHelper.java
index f8c224a..86202f5 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ScannerInjectHelper.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ScannerInjectHelper.java
@@ -22,6 +22,6 @@ import io.swagger.config.ScannerFactory;
public class ScannerInjectHelper {
public void setServer(JAXRSServerFactoryBean server) {
- ScannerFactory.setScanner(new
RestApiResourceScanner(server.getResourceClasses()));
+ RestApiResourceScanner.install(server.getResourceClasses());
}
}
diff --git
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApidocResourceTest.java
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApidocResourceTest.java
index af09e67..7fde63a 100644
---
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApidocResourceTest.java
+++
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApidocResourceTest.java
@@ -56,7 +56,7 @@ public class ApidocResourceTest extends
BrooklynRestResourceTest {
@Override
protected void addBrooklynResources() {
- ScannerFactory.setScanner(new RestApiResourceScanner());
+ RestApiResourceScanner.install(null);
for (Object o : BrooklynRestApi.getApidocResources()) {
addResource(o);
diff --git
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
index 33bbfd3..52dd376 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
@@ -67,7 +67,7 @@ public class RestApiSetup {
}
public static void initSwagger() {
- ScannerFactory.setScanner(new RestApiResourceScanner());
+ RestApiResourceScanner.install(null);
}
}
diff --git
a/utils/rest-swagger/src/main/java/org/apache/brooklyn/rest/apidoc/RestApiResourceScanner.java
b/utils/rest-swagger/src/main/java/org/apache/brooklyn/rest/apidoc/RestApiResourceScanner.java
index e90aea0..83e56e0 100644
---
a/utils/rest-swagger/src/main/java/org/apache/brooklyn/rest/apidoc/RestApiResourceScanner.java
+++
b/utils/rest-swagger/src/main/java/org/apache/brooklyn/rest/apidoc/RestApiResourceScanner.java
@@ -16,10 +16,9 @@
package org.apache.brooklyn.rest.apidoc;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
+import io.swagger.config.Scanner;
+import io.swagger.config.ScannerFactory;
+import java.util.*;
import javax.servlet.ServletConfig;
import javax.ws.rs.core.Application;
@@ -32,54 +31,74 @@ import io.swagger.models.Swagger;
/**
+ * Scans resources for Swagger API resources. Makes them available to the
Swagger scanner.
* Much like DefaultJaxrsScanner, but looks at annotations of ancestors as
well.
*
* For instance, if a resource implementation exposes an annotated interface,
* that interface will be added as well.
*
+ * Unfortunately the Swagger scanner is a static so this {@link
#install(Collection)} expects static scope;
+ * it works out okay as we want all the resources from different bundles to be
available in the API doc page.
+ * But it is a bit ugly.
+ *
+ * Swagger also caches things so, also unfortunately, we need to hack in to
the ApiListing calls and
+ * {@link #rescanIfNeeded(Runnable)}.
*/
public class RestApiResourceScanner extends AbstractScanner implements
JaxrsScanner, SwaggerConfig {
- private Set<Class<?>> apiClasses = null;
+ private boolean scannerDirty = true;
+
+ private final Set<Class<?>> globalClasses = new HashSet<>();
+
+ private final Map<Application,Set<Class<?>>> appCache = new
WeakHashMap<>();
public RestApiResourceScanner() {}
public RestApiResourceScanner(Collection<Class<?>> resourceClasses) {
- this.apiClasses = new HashSet<>();
- addAnnotatedClasses(apiClasses, resourceClasses);
+ addAnnotatedClasses(globalClasses, resourceClasses);
+ }
+
+ private void addAnnotatedClasses(Collection<Class<?>> classes) {
+ addAnnotatedClasses(globalClasses, classes);
}
private void addAnnotatedClasses(Set<Class<?>> output,
Collection<Class<?>> classes) {
- for (Class<?> clz : classes) {
- if (clz.getAnnotation(Api.class) != null) {
- output.add(clz);
+ if (classes!=null) {
+ for (Class<?> clz : classes) {
+ if (clz.getAnnotation(Api.class) != null) {
+ output.add(clz);
+ }
+ addAnnotatedClasses(output,
Arrays.asList(clz.getInterfaces()));
}
- addAnnotatedClasses(output, Arrays.asList(clz.getInterfaces()));
}
}
- private synchronized void buildApiClasses(Application app) {
- if (apiClasses == null) {
- apiClasses = new HashSet<>();
+ private synchronized Set<Class<?>> buildApiClasses(Application app) {
+ Set<Class<?>> cached = appCache.get(app);
+ if (cached == null) {
+ cached = new HashSet<>();
if (app != null) {
Set<Class<?>> classes = app.getClasses();
if (classes != null) {
- addAnnotatedClasses(apiClasses, classes);
+ addAnnotatedClasses(cached, classes);
}
Set<Object> singletons = app.getSingletons();
if (singletons != null) {
for (Object o : singletons) {
- addAnnotatedClasses(apiClasses,
Arrays.<Class<?>>asList(o.getClass()));
+ addAnnotatedClasses(cached,
Arrays.<Class<?>>asList(o.getClass()));
}
}
}
+ appCache.put(app, cached);
}
+ return cached;
}
@Override
public Set<Class<?>> classesFromContext(Application app, ServletConfig sc)
{
- buildApiClasses(app);
- return apiClasses;
+ HashSet<Class<?>> all = new HashSet<>(globalClasses);
+ all.addAll(buildApiClasses(app));
+ return all;
}
@Override
@@ -98,4 +117,23 @@ public class RestApiResourceScanner extends AbstractScanner
implements JaxrsScan
return null;
}
+ /** install this as the scanner which Swagger will use, with the given
class also installed */
+ public static void install(Collection<Class<?>> resourceClasses) {
+ Scanner scanner = ScannerFactory.getScanner();
+ if (scanner instanceof RestApiResourceScanner) {
+
((RestApiResourceScanner)scanner).addAnnotatedClasses(resourceClasses);
+ } else {
+ scanner = new RestApiResourceScanner(resourceClasses);
+ }
+ ScannerFactory.setScanner(scanner);
+ ((RestApiResourceScanner)ScannerFactory.getScanner()).scannerDirty =
true;
+ }
+
+ public static void rescanIfNeeded(Runnable r) {
+ if (ScannerFactory.getScanner() instanceof RestApiResourceScanner &&
((RestApiResourceScanner)ScannerFactory.getScanner()).scannerDirty) {
+ r.run();
+ ((RestApiResourceScanner)ScannerFactory.getScanner()).scannerDirty
= false;
+ }
+ }
+
}