Thomas Vachuska

Adding support for user interface extensions.

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