Thomas Vachuska

Adding support for user interface extensions.

Change-Id: I1e41d16efc11be31ad4c2fb0c09e86e3dfd26706
Showing 36 changed files with 1085 additions and 19 deletions
1 +/*
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 + */
16 +package org.onosproject.ui;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +
20 +import java.io.InputStream;
21 +import java.util.List;
22 +
23 +import static com.google.common.base.Preconditions.checkNotNull;
24 +
25 +/**
26 + * User interface extension.
27 + */
28 +public class UiExtension {
29 +
30 + private final String prefix;
31 + private final ClassLoader classLoader;
32 + private final List<UiView> views;
33 +
34 + /**
35 + * Creates a user interface extension for loading CSS and JS injections
36 + * from {@code css.html} and {@code js.html} resources, respectively.
37 + *
38 + * @param classLoader class-loader for user interface resources
39 + */
40 + public UiExtension(List<UiView> views, ClassLoader classLoader) {
41 + this(views, null, classLoader);
42 + }
43 +
44 + /**
45 + * Creates a user interface extension using custom resource prefix. It
46 + * loads CSS and JS injections from {@code path/css.html} and
47 + * {@code prefix/js.html} resources, respectively.
48 + *
49 + * @param views list of user interface views
50 + * @param path resource path prefix
51 + * @param classLoader class-loader for user interface resources
52 + */
53 + public UiExtension(List<UiView> views, String path, ClassLoader classLoader) {
54 + this.views = checkNotNull(ImmutableList.copyOf(views), "Views cannot be null");
55 + this.prefix = path != null ? (path + "/") : "";
56 + this.classLoader = checkNotNull(classLoader, "Class loader must be specified");
57 + }
58 +
59 + /**
60 + * Returns input stream containing CSS inclusion statements.
61 + *
62 + * @return CSS inclusion statements
63 + */
64 + public InputStream css() {
65 + return classLoader.getResourceAsStream(prefix + "css.html");
66 + }
67 +
68 + /**
69 + * Returns input stream containing JavaScript inclusion statements.
70 + *
71 + * @return JavaScript inclusion statements
72 + */
73 + public InputStream js() {
74 + return classLoader.getResourceAsStream(prefix + "js.html");
75 + }
76 +
77 + /**
78 + * Returns list of user interface views contributed by this extension.
79 + *
80 + * @return contributed view descriptors
81 + */
82 + public List<UiView> views() {
83 + return views;
84 + }
85 +
86 + /**
87 + * Returns input stream containing specified view-specific resource.
88 + *
89 + * @param viewId view identifier
90 + * @param path resource path, relative to the view directory
91 + * @return resource input stream
92 + */
93 + public InputStream resource(String viewId, String path) {
94 + InputStream is = classLoader.getResourceAsStream(prefix + "views/" + viewId + "/" + path);
95 + return is;
96 + }
97 +
98 +}
1 +/*
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 + */
16 +package org.onosproject.ui;
17 +
18 +import java.util.List;
19 +
20 +/**
21 + * Service for registering user interface extensions.
22 + */
23 +public interface UiExtensionService {
24 +
25 + /**
26 + * Registers the specified user interface extension.
27 + *
28 + * @param extension GUI extension to register
29 + */
30 + void register(UiExtension extension);
31 +
32 + /**
33 + * Unregisters the specified user interface extension.
34 + *
35 + * @param extension GUI extension to unregister
36 + */
37 + void unregister(UiExtension extension);
38 +
39 + /**
40 + * Returns the list of user interface extensions.
41 + *
42 + * @return list of extensions
43 + */
44 + List<UiExtension> getExtensions();
45 +
46 + /**
47 + * Returns the user interface extension that contributed the specified view.
48 + *
49 + * @param viewId view identifier
50 + * @return user interface extension
51 + */
52 + UiExtension getViewExtension(String viewId);
53 +}
1 +/*
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 + */
16 +package org.onosproject.ui;
17 +
18 +import com.google.common.base.MoreObjects;
19 +
20 +import java.util.Objects;
21 +
22 +/**
23 + * Represents user interface view addition.
24 + */
25 +public class UiView {
26 +
27 + private final String id;
28 + private final String label;
29 +
30 + /**
31 + * Creates a new user interface view descriptor.
32 + *
33 + * @param id view identifier
34 + * @param label view label
35 + */
36 + public UiView(String id, String label) {
37 + this.id = id;
38 + this.label = label;
39 + }
40 +
41 + /**
42 + * Returns the view identifier.
43 + *
44 + * @return view id
45 + */
46 + public String id() {
47 + return id;
48 + }
49 +
50 + /**
51 + * Returns the view label.
52 + *
53 + * @return view label
54 + */
55 + public String label() {
56 + return label;
57 + }
58 +
59 + @Override
60 + public int hashCode() {
61 + return Objects.hash(id);
62 + }
63 +
64 + @Override
65 + public boolean equals(Object obj) {
66 + if (this == obj) {
67 + return true;
68 + }
69 + if (obj == null || getClass() != obj.getClass()) {
70 + return false;
71 + }
72 + final UiView other = (UiView) obj;
73 + return Objects.equals(this.id, other.id);
74 + }
75 +
76 + @Override
77 + public String toString() {
78 + return MoreObjects.toStringHelper(this)
79 + .add("id", id)
80 + .add("label", label)
81 + .toString();
82 + }
83 +}
1 +/*
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 + */
16 +
17 +/**
18 + * Mechanism for managing dynamically registered user interface extensions.
19 + */
20 +package org.onosproject.ui;
1 +/*
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 + */
16 +package org.onosproject.ui;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +import org.junit.Test;
20 +
21 +import java.io.IOException;
22 +
23 +import static com.google.common.io.ByteStreams.toByteArray;
24 +import static org.junit.Assert.assertEquals;
25 +import static org.junit.Assert.assertTrue;
26 +
27 +/**
28 + * Tests the default user interface extension descriptor.
29 + */
30 +public class UiExtensionTest {
31 +
32 + @Test
33 + public void basics() throws IOException {
34 + UiExtension ext = new UiExtension(ImmutableList.of(new UiView("foo", "Foo View")),
35 + getClass().getClassLoader());
36 + String css = new String(toByteArray(ext.css()));
37 + assertTrue("incorrect css stream", css.contains("foo-css"));
38 + String js = new String(toByteArray(ext.js()));
39 + assertTrue("incorrect js stream", js.contains("foo-js"));
40 + assertEquals("incorrect views stream", "foo", ext.views().get(0).id());
41 + }
42 +
43 + @Test
44 + public void withPath() throws IOException {
45 + UiExtension ext = new UiExtension(ImmutableList.of(new UiView("foo", "Foo View")),
46 + "custom", getClass().getClassLoader());
47 + String css = new String(toByteArray(ext.css()));
48 + assertTrue("incorrect css stream", css.contains("custom-css"));
49 + String js = new String(toByteArray(ext.js()));
50 + assertTrue("incorrect js stream", js.contains("custom-js"));
51 + assertEquals("incorrect views stream", "foo", ext.views().get(0).id());
52 + }
53 +}
...\ No newline at end of file ...\ No newline at end of file
1 +foo-css
2 +bar-css
...\ No newline at end of file ...\ No newline at end of file
1 +custom-js
...\ No newline at end of file ...\ No newline at end of file
1 +foo-js
2 +bar-js
...\ No newline at end of file ...\ No newline at end of file
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
93 <group> 93 <group>
94 <title>GUI, REST &amp; Command-Line</title> 94 <title>GUI, REST &amp; Command-Line</title>
95 <packages> 95 <packages>
96 - org.onosproject.gui:org.onosproject.rest:org.onosproject.cli:org.onosproject.gui.*:org.onosproject.rest.*:org.onosproject.cli.*:org.onosproject.codec.impl 96 + org.onosproject.gui:org.onosproject.rest:org.onosproject.cli:org.onosproject.ui.*:org.onosproject.rest.*:org.onosproject.cli.*:org.onosproject.codec.impl
97 </packages> 97 </packages>
98 </group> 98 </group>
99 <group> 99 <group>
......
...@@ -53,4 +53,36 @@ ...@@ -53,4 +53,36 @@
53 <classifier>tests</classifier> 53 <classifier>tests</classifier>
54 </dependency> 54 </dependency>
55 </dependencies> 55 </dependencies>
56 +
57 + <build>
58 + <plugins>
59 + <plugin>
60 + <artifactId>maven-resources-plugin</artifactId>
61 + <version>2.7</version>
62 + <executions>
63 + <execution>
64 + <id>copy-resources</id>
65 + <phase>prepare-package</phase>
66 + <goals>
67 + <goal>copy-resources</goal>
68 + </goals>
69 + <configuration>
70 + <outputDirectory>${basedir}/target/classes/WEB-INF/classes/app/view</outputDirectory>
71 + <resources>
72 + <resource>
73 + <directory>src/main/webapp/app/view</directory>
74 + <filtering>true</filtering>
75 + <excludes>
76 + <exclude>_sdh/**</exclude>
77 + <exclude>test/**</exclude>
78 + </excludes>
79 + </resource>
80 + </resources>
81 + </configuration>
82 + </execution>
83 + </executions>
84 + </plugin>
85 + </plugins>
86 + </build>
87 +
56 </project> 88 </project>
......
1 +/*
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 + */
16 +package org.onosproject.ui.impl;
17 +
18 +import org.onlab.rest.BaseResource;
19 +
20 +import java.io.ByteArrayInputStream;
21 +import java.io.InputStream;
22 +import java.util.Enumeration;
23 +import java.util.Iterator;
24 +import java.util.List;
25 +
26 +import static com.google.common.base.Preconditions.checkArgument;
27 +
28 +/**
29 + * Resource for serving semi-static resources.
30 + */
31 +public class AbstractInjectionResource extends BaseResource {
32 +
33 + /**
34 + * Returns the index into the supplied string where the end of the
35 + * specified pattern is located.
36 + *
37 + * @param string string to split
38 + * @param start index where to start looking for pattern
39 + * @param stopPattern optional pattern where to stop
40 + */
41 + protected int split(String string, int start, String stopPattern) {
42 + int i = stopPattern != null ? string.indexOf(stopPattern, start) : string.length();
43 + checkArgument(i > 0, "Unable to locate stop pattern %s", stopPattern);
44 + return i + (stopPattern != null ? stopPattern.length() : 0);
45 + }
46 +
47 + /**
48 + * Produces an input stream from the bytes of the specified sub-string.
49 + *
50 + * @param string source string
51 + * @param start index where to start stream
52 + * @param end index where to end stream
53 + */
54 + protected InputStream stream(String string, int start, int end) {
55 + return new ByteArrayInputStream(string.substring(start, end).getBytes());
56 + }
57 +
58 + /**
59 + * Auxiliary enumeration to sequence input streams.
60 + */
61 + protected class StreamEnumeration implements Enumeration<InputStream> {
62 + private final Iterator<InputStream> iterator;
63 +
64 + StreamEnumeration(List<InputStream> streams) {
65 + this.iterator = streams.iterator();
66 + }
67 +
68 + @Override
69 + public boolean hasMoreElements() {
70 + return iterator.hasNext();
71 + }
72 +
73 + @Override
74 + public InputStream nextElement() {
75 + return iterator.next();
76 + }
77 + }
78 +}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.gui; 17 +package org.onosproject.ui.impl;
18 18
19 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.gui; 17 +package org.onosproject.ui.impl;
18 18
19 import org.onosproject.net.Device; 19 import org.onosproject.net.Device;
20 import org.onosproject.net.device.DeviceService; 20 import org.onosproject.net.device.DeviceService;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import org.eclipse.jetty.websocket.WebSocket; 18 import org.eclipse.jetty.websocket.WebSocket;
19 import org.eclipse.jetty.websocket.WebSocketServlet; 19 import org.eclipse.jetty.websocket.WebSocketServlet;
......
1 +/*
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 + */
16 +package org.onosproject.ui.impl;
17 +
18 +import org.onosproject.ui.UiExtension;
19 +import org.onosproject.ui.UiExtensionService;
20 +import org.onosproject.ui.UiView;
21 +
22 +import javax.ws.rs.GET;
23 +import javax.ws.rs.Path;
24 +import javax.ws.rs.Produces;
25 +import javax.ws.rs.core.MediaType;
26 +import javax.ws.rs.core.Response;
27 +import java.io.ByteArrayInputStream;
28 +import java.io.IOException;
29 +import java.io.InputStream;
30 +import java.io.SequenceInputStream;
31 +
32 +import static com.google.common.collect.ImmutableList.of;
33 +import static com.google.common.io.ByteStreams.toByteArray;
34 +
35 +/**
36 + * Resource for serving the dynamically composed onos.js.
37 + */
38 +@Path("/")
39 +public class MainExtResource extends AbstractInjectionResource {
40 +
41 + private static final String MAIN_JS = "/onos-template.js";
42 + private static final String NAV_HTML = "/nav-template.html";
43 +
44 + private static final String INJECT_VIEW_IDS = "// {INJECTED-VIEW-IDS}";
45 + private static final String INJECT_VIEW_ITEMS = "<!-- {INJECTED-VIEW-NAV} -->";
46 +
47 + private static final String NAV_FORMAT =
48 + " <li> <a ng-click=\"navCtrl.hideNav()\" href=\"#/%s\">%s</a></li>";
49 +
50 + @Path("/onos.js")
51 + @GET
52 + @Produces(MediaType.TEXT_HTML)
53 + public Response getMainModule() throws IOException {
54 + UiExtensionService service = get(UiExtensionService.class);
55 + InputStream jsTemplate = getClass().getClassLoader().getResourceAsStream(MAIN_JS);
56 + String js = new String(toByteArray(jsTemplate));
57 +
58 + int p1 = split(js, 0, INJECT_VIEW_IDS);
59 + int p2 = split(js, p1, null);
60 +
61 + StreamEnumeration streams =
62 + new StreamEnumeration(of(stream(js, 0, p1),
63 + includeViewIds(service),
64 + stream(js, p1, p2)));
65 +
66 + return Response.ok(new SequenceInputStream(streams)).build();
67 + }
68 +
69 + // Produces an input stream including view id injections from all extensions.
70 + private InputStream includeViewIds(UiExtensionService service) {
71 + StringBuilder sb = new StringBuilder("\n");
72 + for (UiExtension extension : service.getExtensions()) {
73 + for (UiView view : extension.views()) {
74 + sb.append(" '").append(view.id()).append("',");
75 + }
76 + }
77 + return new ByteArrayInputStream(sb.toString().getBytes());
78 + }
79 +
80 + @Path("/nav/nav.html")
81 + @GET
82 + @Produces(MediaType.TEXT_HTML)
83 + public Response getNavigation() throws IOException {
84 + UiExtensionService service = get(UiExtensionService.class);
85 + InputStream navTemplate = getClass().getClassLoader().getResourceAsStream(NAV_HTML);
86 + String js = new String(toByteArray(navTemplate));
87 +
88 + int p1 = split(js, 0, INJECT_VIEW_ITEMS);
89 + int p2 = split(js, p1, null);
90 +
91 + StreamEnumeration streams =
92 + new StreamEnumeration(of(stream(js, 0, p1),
93 + includeNavItems(service),
94 + stream(js, p1, p2)));
95 +
96 + return Response.ok(new SequenceInputStream(streams)).build();
97 + }
98 +
99 + // Produces an input stream including nav item injections from all extensions.
100 + private InputStream includeNavItems(UiExtensionService service) {
101 + StringBuilder sb = new StringBuilder("\n");
102 + for (UiExtension extension : service.getExtensions()) {
103 + for (UiView view : extension.views()) {
104 + sb.append(String.format(NAV_FORMAT, view.id(), view.label()));
105 + }
106 + }
107 + return new ByteArrayInputStream(sb.toString().getBytes());
108 + }
109 +}
1 +/*
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 + */
16 +package org.onosproject.ui.impl;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +import org.onosproject.ui.UiExtension;
20 +import org.onosproject.ui.UiExtensionService;
21 +
22 +import javax.ws.rs.GET;
23 +import javax.ws.rs.Path;
24 +import javax.ws.rs.Produces;
25 +import javax.ws.rs.core.MediaType;
26 +import javax.ws.rs.core.Response;
27 +import java.io.IOException;
28 +import java.io.InputStream;
29 +import java.io.SequenceInputStream;
30 +
31 +import static com.google.common.collect.ImmutableList.of;
32 +import static com.google.common.io.ByteStreams.toByteArray;
33 +
34 +/**
35 + * Resource for serving the dynamically composed index.html.
36 + */
37 +@Path("/")
38 +public class MainIndexResource extends AbstractInjectionResource {
39 +
40 + private static final String INDEX = "/index-template.html";
41 +
42 + private static final String INJECT_CSS = "<!-- {INJECTED-STYLESHEETS} -->";
43 + private static final String INJECT_JS = "<!-- {INJECTED-JAVASCRIPT} -->";
44 +
45 + @Path("/")
46 + @GET
47 + @Produces(MediaType.TEXT_HTML)
48 + public Response getMainIndex() throws IOException {
49 + UiExtensionService service = get(UiExtensionService.class);
50 + InputStream indexTemplate = getClass().getClassLoader().getResourceAsStream(INDEX);
51 + String index = new String(toByteArray(indexTemplate));
52 +
53 + int p1 = split(index, 0, INJECT_JS);
54 + int p2 = split(index, p1, INJECT_CSS);
55 + int p3 = split(index, p2, null);
56 +
57 + StreamEnumeration streams =
58 + new StreamEnumeration(of(stream(index, 0, p1),
59 + includeJs(service),
60 + stream(index, p1, p2),
61 + includeCss(service),
62 + stream(index, p2, p3)));
63 +
64 + return Response.ok(new SequenceInputStream(streams)).build();
65 + }
66 +
67 + // Produces an input stream including CSS injections from all extensions.
68 + private InputStream includeCss(UiExtensionService service) {
69 + ImmutableList.Builder<InputStream> builder = ImmutableList.builder();
70 + for (UiExtension extension : service.getExtensions()) {
71 + builder.add(extension.css());
72 + }
73 + return new SequenceInputStream(new StreamEnumeration(builder.build()));
74 + }
75 +
76 + // Produces an input stream including JS injections from all extensions.
77 + private InputStream includeJs(UiExtensionService service) {
78 + ImmutableList.Builder<InputStream> builder = ImmutableList.builder();
79 + for (UiExtension extension : service.getExtensions()) {
80 + builder.add(extension.js());
81 + }
82 + return new SequenceInputStream(new StreamEnumeration(builder.build()));
83 + }
84 +
85 +}
1 +/*
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 + */
16 +package org.onosproject.ui.impl;
17 +
18 +import org.onosproject.ui.UiExtension;
19 +import org.onosproject.ui.UiExtensionService;
20 +
21 +import javax.ws.rs.GET;
22 +import javax.ws.rs.Path;
23 +import javax.ws.rs.PathParam;
24 +import javax.ws.rs.core.Response;
25 +import java.io.IOException;
26 +
27 +import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
28 +import static javax.ws.rs.core.MediaType.TEXT_HTML;
29 +
30 +/**
31 + * Resource for serving the dynamically composed onos.js.
32 + */
33 +@Path("/")
34 +public class MainViewResource extends AbstractInjectionResource {
35 +
36 + private static final String CONTENT_TYPE = "Content-Type";
37 + private static final String STYLESHEET = "text/css";
38 + private static final String SCRIPT = "text/javascript";
39 +
40 + @Path("{view}/{resource}")
41 + @GET
42 + public Response getViewResource(@PathParam("view") String viewId,
43 + @PathParam("resource") String resource) throws IOException {
44 + UiExtensionService service = get(UiExtensionService.class);
45 + UiExtension extension = service.getViewExtension(viewId);
46 + return extension != null ?
47 + Response.ok(extension.resource(viewId, resource))
48 + .header(CONTENT_TYPE, contentType(resource)).build() :
49 + Response.status(Response.Status.NOT_FOUND).build();
50 + }
51 +
52 + static String contentType(String resource) {
53 + return resource.endsWith(".html") ? TEXT_HTML :
54 + resource.endsWith(".css") ? STYLESHEET :
55 + resource.endsWith(".js") ? SCRIPT :
56 + APPLICATION_OCTET_STREAM;
57 + }
58 +
59 +}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.gui; 17 +package org.onosproject.ui.impl;
18 18
19 import java.util.Comparator; 19 import java.util.Comparator;
20 20
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.gui; 17 +package org.onosproject.ui.impl;
18 18
19 19
20 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import org.onosproject.net.ConnectPoint; 18 import org.onosproject.net.ConnectPoint;
19 import org.onosproject.net.Device; 19 import org.onosproject.net.Device;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.gui; 16 +package org.onosproject.ui.impl;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
......
1 +/*
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 + */
16 +package org.onosproject.ui.impl;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +import com.google.common.collect.Lists;
20 +import com.google.common.collect.Maps;
21 +import org.apache.felix.scr.annotations.Activate;
22 +import org.apache.felix.scr.annotations.Component;
23 +import org.apache.felix.scr.annotations.Deactivate;
24 +import org.apache.felix.scr.annotations.Service;
25 +import org.onosproject.ui.UiExtension;
26 +import org.onosproject.ui.UiExtensionService;
27 +import org.onosproject.ui.UiView;
28 +import org.slf4j.Logger;
29 +import org.slf4j.LoggerFactory;
30 +
31 +import java.util.List;
32 +import java.util.Map;
33 +
34 +import static com.google.common.collect.ImmutableList.of;
35 +import static java.util.stream.Collectors.toSet;
36 +
37 +/**
38 + * Manages the user interface extensions.
39 + */
40 +@Component(immediate = true)
41 +@Service
42 +public class UiExtensionManager implements UiExtensionService {
43 +
44 + private final Logger log = LoggerFactory.getLogger(getClass());
45 +
46 + // List of all extensions
47 + private final List<UiExtension> extensions = Lists.newArrayList();
48 +
49 + // Map of views to extensions
50 + private final Map<String, UiExtension> views = Maps.newHashMap();
51 +
52 + // Core views & core extension
53 + private final List<UiView> coreViews = of(new UiView("sample", "Sample"),
54 + new UiView("topo", "Topology View"),
55 + new UiView("device", "Devices"));
56 +
57 + private final UiExtension core = new UiExtension(coreViews, getClass().getClassLoader());
58 +
59 + @Activate
60 + public void activate() {
61 + register(core);
62 + log.info("Started");
63 + }
64 +
65 + @Deactivate
66 + public void deactivate() {
67 + unregister(core);
68 + log.info("Stopped");
69 + }
70 +
71 + @Override
72 + public synchronized void register(UiExtension extension) {
73 + if (!extensions.contains(extension)) {
74 + extensions.add(extension);
75 + for (UiView view : extension.views()) {
76 + views.put(view.id(), extension);
77 + }
78 + }
79 + }
80 +
81 + @Override
82 + public synchronized void unregister(UiExtension extension) {
83 + extensions.remove(extension);
84 + extension.views().stream().map(UiView::id).collect(toSet()).forEach(views::remove);
85 + }
86 +
87 + @Override
88 + public synchronized List<UiExtension> getExtensions() {
89 + return ImmutableList.copyOf(extensions);
90 + }
91 +
92 + @Override
93 + public synchronized UiExtension getViewExtension(String viewId) {
94 + return views.get(viewId);
95 + }
96 +}
...@@ -17,4 +17,4 @@ ...@@ -17,4 +17,4 @@
17 /** 17 /**
18 * Set of resources providing data for the ONOS GUI. 18 * Set of resources providing data for the ONOS GUI.
19 */ 19 */
20 -package org.onosproject.gui; 20 +package org.onosproject.ui.impl;
......
1 +<link rel="stylesheet" href="app/view/sample/sample.css">
2 +<link rel="stylesheet" href="app/view/topo/topo.css">
3 +<link rel="stylesheet" href="app/view/device/device.css">
1 +<!DOCTYPE html>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<html>
18 +<head>
19 + <meta charset="utf-8">
20 + <link rel="shortcut icon" href="data/img/onos-logo.png">
21 + <title>ONOS Angular</title>
22 +
23 + <!-- Third party library code included here -->
24 + <!--TODO: use minified versions, once debugging is complete -->
25 + <script src="tp/angular.js"></script>
26 + <script src="tp/angular-route.js"></script>
27 +
28 + <script src="tp/d3.js"></script>
29 + <script src="tp/topojson.v1.min.js"></script>
30 +
31 + <!-- ONOS UI Framework included here -->
32 + <!-- TODO: use a single catenated-minified file here -->
33 + <script src="dyn/onos.js"></script>
34 + <script src="app/directives.js"></script>
35 +
36 + <script src="app/fw/util/util.js"></script>
37 + <script src="app/fw/util/fn.js"></script>
38 + <script src="app/fw/util/theme.js"></script>
39 + <script src="app/fw/util/keys.js"></script>
40 +
41 + <script src="app/fw/mast/mast.js"></script>
42 + <script src="app/fw/nav/nav.js"></script>
43 +
44 + <script src="app/fw/svg/svg.js"></script>
45 + <script src="app/fw/svg/glyph.js"></script>
46 + <script src="app/fw/svg/icon.js"></script>
47 + <script src="app/fw/svg/geodata.js"></script>
48 + <script src="app/fw/svg/map.js"></script>
49 + <script src="app/fw/svg/zoom.js"></script>
50 + <script src="app/fw/svg/svgUtil.js"></script>
51 +
52 + <script src="app/fw/remote/remote.js"></script>
53 + <script src="app/fw/remote/urlfn.js"></script>
54 + <script src="app/fw/remote/rest.js"></script>
55 + <script src="app/fw/remote/websocket.js"></script>
56 + <script src="app/fw/remote/wsevent.js"></script>
57 +
58 + <script src="app/fw/widget/widget.js"></script>
59 + <script src="app/fw/widget/table.js"></script>
60 +
61 + <script src="app/fw/layer/layer.js"></script>
62 + <script src="app/fw/layer/panel.js"></script>
63 +
64 + <!-- Framework and library stylesheets included here -->
65 + <!-- TODO: use a single catenated-minified file here -->
66 + <link rel="stylesheet" href="app/onos.css">
67 + <link rel="stylesheet" href="app/common.css">
68 + <link rel="stylesheet" href="app/fw/mast/mast.css">
69 + <link rel="stylesheet" href="app/fw/svg/glyph.css">
70 + <link rel="stylesheet" href="app/fw/svg/icon.css">
71 + <link rel="stylesheet" href="app/fw/layer/panel.css">
72 + <link rel="stylesheet" href="app/fw/nav/nav.css">
73 +
74 + <!-- This is where contributed javascript will get injected -->
75 + <!-- {INJECTED-JAVASCRIPT} -->
76 +
77 + <!-- This is where contributed stylesheets will get injected -->
78 + <!-- {INJECTED-STYLESHEETS} -->
79 +</head>
80 +<body class="light" ng-app="onosApp">
81 + <div id="frame" ng-controller="OnosCtrl as onosCtrl">
82 + <div id="mast"
83 + ng-controller="MastCtrl as mastCtrl"
84 + ng-include="'app/fw/mast/mast.html'"></div>
85 +
86 + <div id="view" ng-view></div>
87 +
88 + <div id="nav"
89 + ng-controller="NavCtrl as navCtrl"
90 + ng-include="'dyn/nav/nav.html'"></div>
91 +
92 + <div id="floatpanels"></div>
93 + <div id="alerts"></div>
94 + <div id="flash"></div>
95 + <div id="quickhelp"></div>
96 + <div id="deathmask"></div>
97 + </div>
98 +</body>
99 +</html>
1 +<script src="app/view/sample/sample.js"></script>
2 +<script src="app/view/topo/topo.js"></script>
3 +<script src="app/view/topo/topoEvent.js"></script>
4 +<script src="app/view/topo/topoForce.js"></script>
5 +<script src="app/view/topo/topoPanel.js"></script>
6 +<script src="app/view/topo/topoInst.js"></script>
7 +<script src="app/view/device/device.js"></script>
1 +<!-- Navigation partial HTML -->
2 +<h2>Navigation</h2>
3 +<h3>(Note - this is temporary)</h3>
4 +
5 +<ul>
6 + <!-- {INJECTED-VIEW-NAV} -->
7 +</ul>
1 +/*
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 + */
16 +
17 +/*
18 + ONOS GUI -- Main Application Module
19 + */
20 +
21 +(function () {
22 + 'use strict';
23 +
24 + // define core module dependencies here...
25 + var coreDependencies = [
26 + 'ngRoute',
27 + 'onosMast',
28 + 'onosNav',
29 + 'onosUtil',
30 + 'onosSvg',
31 + 'onosRemote',
32 + 'onosLayer',
33 + 'onosWidget'
34 + ];
35 +
36 + // view IDs.. note the first view listed is loaded at startup
37 + var viewIds = [
38 + // TODO: inject view IDs server side
39 + // {INJECTED-VIEW-IDS}
40 + // (end of injected views)
41 +
42 + // dummy entry
43 + ''
44 + ];
45 +
46 + var viewDependencies = [];
47 +
48 + viewIds.forEach(function (id) {
49 + if (id) {
50 + viewDependencies.push('ov' + capitalize(id));
51 + }
52 + });
53 +
54 + var moduleDependencies = coreDependencies.concat(viewDependencies);
55 +
56 + function capitalize(word) {
57 + return word ? word[0].toUpperCase() + word.slice(1) : word;
58 + }
59 +
60 + angular.module('onosApp', moduleDependencies)
61 +
62 + .controller('OnosCtrl', [
63 + '$log', '$route', '$routeParams', '$location',
64 + 'KeyService', 'ThemeService', 'GlyphService', 'PanelService',
65 +
66 + function ($log, $route, $routeParams, $location, ks, ts, gs, ps) {
67 + var self = this;
68 +
69 + self.$route = $route;
70 + self.$routeParams = $routeParams;
71 + self.$location = $location;
72 + self.version = '1.1.0';
73 +
74 + // initialize services...
75 + ts.init();
76 + ks.installOn(d3.select('body'));
77 + gs.init();
78 + ps.init();
79 +
80 + $log.log('OnosCtrl has been created');
81 +
82 + $log.debug('route: ', self.$route);
83 + $log.debug('routeParams: ', self.$routeParams);
84 + $log.debug('location: ', self.$location);
85 + }])
86 +
87 + .config(['$routeProvider', function ($routeProvider) {
88 + // If view ID not provided, route to the first view in the list.
89 + $routeProvider
90 + .otherwise({
91 + redirectTo: '/' + viewIds[0]
92 + });
93 +
94 + function viewCtrlName(vid) {
95 + return 'Ov' + capitalize(vid) + 'Ctrl';
96 + }
97 + function viewTemplateUrl(vid) {
98 + return 'view/' + vid + '/' + vid + '.html';
99 + }
100 +
101 + // Add routes for each defined view.
102 + viewIds.forEach(function (vid) {
103 + if (vid) {
104 + $routeProvider.when('/' + vid, {
105 + controller: viewCtrlName(vid),
106 + controllerAs: 'ctrl',
107 + templateUrl: viewTemplateUrl(vid)
108 + });
109 + }
110 + });
111 + }]);
112 +}());
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
14 ~ See the License for the specific language governing permissions and 14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License. 15 ~ limitations under the License.
16 --> 16 -->
17 -<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 17 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
18 - xmlns="http://java.sun.com/xml/ns/javaee" 18 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
19 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 19 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 id="ONOS" version="2.5"> 20 id="ONOS" version="2.5">
21 <display-name>ONOS GUI</display-name> 21 <display-name>ONOS GUI</display-name>
...@@ -24,12 +24,78 @@ ...@@ -24,12 +24,78 @@
24 <welcome-file>index.html</welcome-file> 24 <welcome-file>index.html</welcome-file>
25 </welcome-file-list> 25 </welcome-file-list>
26 26
27 + <!--
28 + <servlet>
29 + <servlet-name>Index Page</servlet-name>
30 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
31 + <init-param>
32 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
33 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
34 + </init-param>
35 + <init-param>
36 + <param-name>com.sun.jersey.config.property.classnames</param-name>
37 + <param-value>org.onosproject.gui.impl.MainIndexResource</param-value>
38 + </init-param>
39 + <load-on-startup>1</load-on-startup>
40 + </servlet>
41 +
42 + <servlet-mapping>
43 + <servlet-name>Index Page</servlet-name>
44 + <url-pattern>/main.html</url-pattern>
45 + </servlet-mapping>
46 +
47 + <servlet>
48 + <servlet-name>Main Module</servlet-name>
49 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
50 + <init-param>
51 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
52 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
53 + </init-param>
54 + <init-param>
55 + <param-name>com.sun.jersey.config.property.classnames</param-name>
56 + <param-value>org.onosproject.gui.impl.MainExtResource</param-value>
57 + </init-param>
58 + <load-on-startup>1</load-on-startup>
59 + </servlet>
60 +
61 + <servlet-mapping>
62 + <servlet-name>Main Module</servlet-name>
63 + <url-pattern>/dyn/*</url-pattern>
64 + </servlet-mapping>
65 +
66 + <servlet>
67 + <servlet-name>View Module</servlet-name>
68 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
69 + <init-param>
70 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
71 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
72 + </init-param>
73 + <init-param>
74 + <param-name>com.sun.jersey.config.property.classnames</param-name>
75 + <param-value>org.onosproject.gui.impl.MainViewResource</param-value>
76 + </init-param>
77 + <load-on-startup>1</load-on-startup>
78 + </servlet>
79 +
80 + <servlet-mapping>
81 + <servlet-name>View Module</servlet-name>
82 + <url-pattern>/app/view/*</url-pattern>
83 + </servlet-mapping>
84 + -->
85 +
27 <servlet> 86 <servlet>
28 <servlet-name>JAX-RS Service</servlet-name> 87 <servlet-name>JAX-RS Service</servlet-name>
29 <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 88 <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
30 <init-param> 89 <init-param>
31 - <param-name>com.sun.jersey.config.property.packages</param-name> 90 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
32 - <param-value>org.onosproject.gui</param-value> 91 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
92 + </init-param>
93 + <init-param>
94 + <param-name>com.sun.jersey.config.property.classnames</param-name>
95 + <param-value>
96 + org.onosproject.ui.impl.TopologyResource,
97 + org.onosproject.ui.impl.DeviceGuiResource
98 + </param-value>
33 </init-param> 99 </init-param>
34 <load-on-startup>1</load-on-startup> 100 <load-on-startup>1</load-on-startup>
35 </servlet> 101 </servlet>
...@@ -41,7 +107,7 @@ ...@@ -41,7 +107,7 @@
41 107
42 <servlet> 108 <servlet>
43 <servlet-name>Web Socket Service</servlet-name> 109 <servlet-name>Web Socket Service</servlet-name>
44 - <servlet-class>org.onosproject.gui.GuiWebSocketServlet</servlet-class> 110 + <servlet-class>org.onosproject.ui.impl.GuiWebSocketServlet</servlet-class>
45 <load-on-startup>2</load-on-startup> 111 <load-on-startup>2</load-on-startup>
46 </servlet> 112 </servlet>
47 113
...@@ -50,5 +116,4 @@ ...@@ -50,5 +116,4 @@
50 <url-pattern>/ws/*</url-pattern> 116 <url-pattern>/ws/*</url-pattern>
51 </servlet-mapping> 117 </servlet-mapping>
52 118
53 -
54 </web-app> 119 </web-app>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.gui; 17 +package org.onosproject.ui.impl;
18 18
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 import com.google.common.collect.ImmutableSet; 20 import com.google.common.collect.ImmutableSet;
......
...@@ -136,6 +136,7 @@ ...@@ -136,6 +136,7 @@
136 com.fasterxml.jackson.databind.node, 136 com.fasterxml.jackson.databind.node,
137 com.google.common.base.*, 137 com.google.common.base.*,
138 com.google.common.collect.*, 138 com.google.common.collect.*,
139 + com.google.common.io.*,
139 org.eclipse.jetty.websocket.*, 140 org.eclipse.jetty.websocket.*,
140 org.onlab.util.*, 141 org.onlab.util.*,
141 org.onlab.osgi.*, 142 org.onlab.osgi.*,
......