blob: fa124f550dbe42f733342ec83ceb8639926cccb5 [file] [log] [blame]
Thomas Vachuska0fa2aa12015-08-18 12:53:04 -07001/*
2 * Copyright 2015 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 */
16package org.onosproject.rest.resources;
17
18import com.fasterxml.jackson.databind.node.ArrayNode;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import org.onosproject.rest.AbstractInjectionResource;
21import org.onosproject.rest.ApiDocService;
22
23import javax.ws.rs.GET;
24import javax.ws.rs.Path;
25import javax.ws.rs.PathParam;
26import javax.ws.rs.core.Response;
27import java.io.ByteArrayInputStream;
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.SequenceInputStream;
31
32import static com.google.common.collect.ImmutableList.of;
33import static com.google.common.io.ByteStreams.toByteArray;
34import static javax.ws.rs.core.MediaType.*;
35import static org.onlab.util.Tools.nullIsNotFound;
36
37/**
38 * REST API documentation.
39 */
40@Path("docs")
41public class ApiDocResource extends AbstractInjectionResource {
42
43 private static final String CONTENT_TYPE = "Content-Type";
44 private static final String STYLESHEET = "text/css";
45 private static final String SCRIPT = "text/javascript";
46 private static final String DOCS = "/docs/";
47
48 private static final String INJECT_START = "<!-- {API-START} -->";
49 private static final String INJECT_END = "<!-- {API-END} -->";
50
51 /**
52 * Get all registered REST API docs.
53 * Returns array of all registered API docs.
54 *
55 * @return 200 OK
56 */
57 @GET
58 @Path("apis")
59 public Response getApiList() {
60 ObjectNode root = mapper().createObjectNode();
61 ArrayNode apis = newArray(root, "apis");
62 get(ApiDocService.class).getDocProviders().forEach(p -> apis.add(p.name()));
63 return ok(root.toString()).build();
64 }
65
66 /**
67 * Get Swagger UI JSON.
68 *
69 * @param key REST API web context
70 * @return 200 OK
71 */
72 @GET
73 @Path("apis/{key: .*?}/swagger.json")
74 public Response getApi(@PathParam("key") String key) {
75 String k = key.startsWith("/") ? key : "/" + key;
76 InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k),
77 "REST API not found for " + k).docs();
78 return ok(nullIsNotFound(stream, "REST API docs not found for " + k))
79 .header(CONTENT_TYPE, APPLICATION_JSON).build();
80 }
81
82 /**
83 * Get REST API model schema.
84 *
85 * @param key REST API web context
86 * @return 200 OK
87 */
88 @GET
89 @Path("apis/{key: .*?}/model.json")
90 public Response getApiModel(@PathParam("name") String key) {
91 String k = key.startsWith("/") ? key : "/" + key;
92 InputStream stream = nullIsNotFound(get(ApiDocService.class).getDocProvider(k),
93 "REST API not found for " + k).model();
94 return ok(nullIsNotFound(stream, "REST API model not found for " + k))
95 .header(CONTENT_TYPE, APPLICATION_JSON).build();
96 }
97
98 /**
99 * Get Swagger UI main index page.
100 *
101 * @return 200 OK
102 */
103 @GET
104 @Path("/")
105 public Response getDefault() throws IOException {
106 return getIndex();
107 }
108
109 /**
110 * Get Swagger UI main index page.
111 *
112 * @return 200 OK
113 */
114 @GET
115 @Path("index.html")
116 public Response getIndex() throws IOException {
117 InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + "index.html");
118 nullIsNotFound(stream, "index.html not found");
119
120 String index = new String(toByteArray(stream));
121
122 int p1s = split(index, 0, INJECT_START);
123 int p1e = split(index, p1s, INJECT_END);
124 int p2s = split(index, p1e, null);
125
126 StreamEnumeration streams =
127 new StreamEnumeration(of(stream(index, 0, p1s),
128 includeOptions(get(ApiDocService.class)),
129 stream(index, p1e, p2s)));
130
131 return ok(new SequenceInputStream(streams))
132 .header(CONTENT_TYPE, TEXT_HTML).build();
133 }
134
135 private InputStream includeOptions(ApiDocService service) {
136 StringBuilder sb = new StringBuilder();
137 service.getDocProviders().forEach(p -> {
138 sb.append("<option value=\"").append(p.key()).append("\"")
139 .append(p.key().equals("/onos/v1") ? " selected>" : ">")
140 .append(p.name())
141 .append("</option>");
142 });
143 return new ByteArrayInputStream(sb.toString().getBytes());
144 }
145
146 /**
147 * Get Swagger UI resource.
148 *
149 * @return 200 OK
150 */
151 @GET
152 @Path("{resource: .*}")
153 public Response getResource(@PathParam("resource") String resource) throws IOException {
154 InputStream stream = getClass().getClassLoader().getResourceAsStream(DOCS + resource);
155 return ok(nullIsNotFound(stream, resource + " not found"))
156 .header(CONTENT_TYPE, contentType(resource)).build();
157 }
158
159 static String contentType(String resource) {
160 return resource.endsWith(".html") ? TEXT_HTML :
161 resource.endsWith(".css") ? STYLESHEET :
162 resource.endsWith(".js") ? SCRIPT :
163 APPLICATION_OCTET_STREAM;
164 }
165}