| /* |
| * Copyright 2015-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.rest.resources; |
| |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import org.onosproject.rest.AbstractInjectionResource; |
| import org.onosproject.rest.ApiDocService; |
| |
| import javax.ws.rs.GET; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.PathParam; |
| import javax.ws.rs.core.Context; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.UriInfo; |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.SequenceInputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| |
| import static com.google.common.collect.ImmutableList.of; |
| import static com.google.common.io.ByteStreams.toByteArray; |
| import static javax.ws.rs.core.MediaType.*; |
| import static javax.ws.rs.core.Response.temporaryRedirect; |
| import static org.onlab.util.Tools.nullIsNotFound; |
| |
| /** |
| * REST API documentation. |
| */ |
| @Path("docs") |
| public class ApiDocResource extends AbstractInjectionResource { |
| |
| private static final String CONTENT_TYPE = "Content-Type"; |
| private static final String STYLESHEET = "text/css"; |
| private static final String SCRIPT = "text/javascript"; |
| private static final String DOCS = "/docs/"; |
| |
| private static final String INJECT_START = "<!-- {API-START} -->"; |
| private static final String INJECT_END = "<!-- {API-END} -->"; |
| |
| @Context |
| private UriInfo uriInfo; |
| |
| /** |
| * Get all registered REST API docs. |
| * Returns array of all registered API docs. |
| * |
| * @return 200 OK |
| */ |
| @GET |
| @Path("apis") |
| public Response getApiList() { |
| ObjectNode root = mapper().createObjectNode(); |
| ArrayNode apis = newArray(root, "apis"); |
| get(ApiDocService.class).getDocProviders().forEach(p -> apis.add(p.name())); |
| return ok(root.toString()).build(); |
| } |
| |
| /** |
| * Get Swagger UI JSON. |
| * |
| * @param key REST API web context |
| * @return 200 OK |
| */ |
| @GET |
| @Path("apis/{key: .*?}/swagger.json") |
| public Response getApi(@PathParam("key") String key) { |
| String k = key.startsWith("/") ? key : "/" + key; |
| InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k), |
| "REST API not found for " + k).docs(); |
| return ok(nullIsNotFound(stream, "REST API docs not found for " + k)) |
| .header(CONTENT_TYPE, APPLICATION_JSON).build(); |
| } |
| |
| /** |
| * Get REST API model schema. |
| * |
| * @param key REST API web context |
| * @return 200 OK |
| */ |
| @GET |
| @Path("apis/{key: .*?}/model.json") |
| public Response getApiModel(@PathParam("name") String key) { |
| String k = key.startsWith("/") ? key : "/" + key; |
| InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k), |
| "REST API not found for " + k).model(); |
| return ok(nullIsNotFound(stream, "REST API model not found for " + k)) |
| .header(CONTENT_TYPE, APPLICATION_JSON).build(); |
| } |
| |
| /** |
| * Get Swagger UI main index page. |
| * |
| * @return 200 OK |
| * @throws IOException if unable to get index resource |
| * @throws URISyntaxException if unable to create redirect URI |
| */ |
| @GET |
| public Response getDefault() throws IOException, URISyntaxException { |
| return uriInfo.getPath().endsWith("/") ? getIndex() : |
| temporaryRedirect(new URI(uriInfo.getPath() + "/")).build(); |
| } |
| |
| /** |
| * Get Swagger UI main index page. |
| * |
| * @return 200 OK |
| * @throws IOException if unable to get index resource |
| */ |
| @GET |
| @Path("index.html") |
| public Response getIndex() throws IOException { |
| InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + "index.html"); |
| nullIsNotFound(stream, "index.html not found"); |
| |
| String index = new String(toByteArray(stream)); |
| |
| int p1s = split(index, 0, INJECT_START); |
| int p1e = split(index, p1s, INJECT_END); |
| int p2s = split(index, p1e, null); |
| |
| StreamEnumeration streams = |
| new StreamEnumeration(of(stream(index, 0, p1s), |
| includeOptions(get(ApiDocService.class)), |
| stream(index, p1e, p2s))); |
| |
| return ok(new SequenceInputStream(streams)) |
| .header(CONTENT_TYPE, TEXT_HTML).build(); |
| } |
| |
| private InputStream includeOptions(ApiDocService service) { |
| StringBuilder sb = new StringBuilder(); |
| service.getDocProviders().forEach(p -> { |
| sb.append("<option value=\"").append(p.key()).append("\"") |
| .append("/onos/v1".equals(p.key()) ? " selected>" : ">") |
| .append(p.name()) |
| .append("</option>"); |
| }); |
| return new ByteArrayInputStream(sb.toString().getBytes()); |
| } |
| |
| /** |
| * Get Swagger UI resource. |
| * |
| * @param resource path of the resource |
| * @return 200 OK |
| * @throws IOException if unable to get named resource |
| */ |
| @GET |
| @Path("{resource: .*}") |
| public Response getResource(@PathParam("resource") String resource) throws IOException { |
| if ("".equals(resource)) { |
| return getIndex(); |
| } |
| InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + resource); |
| return ok(nullIsNotFound(stream, resource + " not found")) |
| .header(CONTENT_TYPE, contentType(resource)).build(); |
| } |
| |
| static String contentType(String resource) { |
| return resource.endsWith(".html") ? TEXT_HTML : |
| resource.endsWith(".css") ? STYLESHEET : |
| resource.endsWith(".js") ? SCRIPT : |
| APPLICATION_OCTET_STREAM; |
| } |
| } |