# OpenDaylight Toolkit
+App Web Development with NodeJS
+-------------------------------
+
+1) web/src/main/java/org/opendaylight/toolkit/web/CorsFilter.java and replace *your-ip* (e.g. http://localhost:8000)
+
+2) mvn clean install project's root directory
+
+3) Go to simple/ and issue mvn clean install
+
+4) Run the controller main/target/main-osgipackage/opendaylight/run.sh
+
+5) In a new window, go to node/ and run the node server *node server.js*
+
+>Note: you may need to install missing modules *npm install module_name*
+
+6) Go to http://your-ip:8000 in your browser and start developing from simple/
+
+>Disclaimer: you may point node to any app you wish to develop on top of, not just simple, but that will have to be done manually for now
+
+>Note: ensure bower components are installed for web/, refer to section below
+
+
Quick HowTo
-----------
7) *[optional]* If you installed the bower components, you can access the toolkit web UI at <code>http://localhost:8080</code>
+
Troubleshooting
---------------
--- /dev/null
+../web/src/main/resources/css
\ No newline at end of file
--- /dev/null
+../web/src/main/resources/img
\ No newline at end of file
--- /dev/null
+../simple/src/main/resources/WEB-INF/jsp/main.jsp
\ No newline at end of file
--- /dev/null
+../web/src/main/resources/js
\ No newline at end of file
--- /dev/null
+var http = require('http'),
+static = require('./static');
+
+/* Server start */
+var server = http.createServer(function(req, res) {
+ static(req, res); // if no matches, then serve a static file
+}).listen(8000);
--- /dev/null
+../../../simple/src/main/resources/css
\ No newline at end of file
--- /dev/null
+../../../simple/src/main/resources/js
\ No newline at end of file
--- /dev/null
+var url = require('url'),
+path = require('path'),
+fs = require('fs'),
+mime = require('mime');
+
+var Static = function(request, response) {
+ var uri = url.parse(request.url).pathname, filename = path.join(process.cwd(), uri);
+ fs.exists(filename, function(exists) {
+ if(!exists) {
+ response.writeHead(404, {"Content-Type": "text/plain"});
+ response.write("404 Not Found\n");
+ response.end();
+ return;
+ }
+
+ if (fs.statSync(filename).isDirectory()) filename += '/index.html';
+
+ fs.readFile(filename, "binary", function(err, file) {
+ if(err) {
+ response.writeHead(500, {"Content-Type": "text/plain"});
+ response.write(err + "\n");
+ response.end();
+ return;
+ }
+
+ console.log(request.url);
+ response.writeHead(200, {
+ "Content-Type": mime.lookup(filename),
+ "Access-Control-Allow-Origin": "*",
+ });
+ response.write(file, "binary");
+ response.end();
+ });
+ });
+}
+
+module.exports = Static;
<module>common</module>
<module>main</module>
<module>web</module>
+ <module>simple</module>
</modules>
<build>
</plugin>
</plugins>
</build>
-</project>
+</project>
\ No newline at end of file
--- /dev/null
+/target-ide
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.toolkit</groupId>
+ <artifactId>common</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>../common</relativePath>
+ </parent>
+
+ <artifactId>simple</artifactId>
+
+ <groupId>org.bar.foo</groupId>
+ <version>1.0-SNAPSHOT</version>
+
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.toolkit.web,
+ org.opendaylight.controller.sal.authorization,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ javax.annotation,
+ javax.naming,
+ javax.servlet,
+ javax.servlet.annotation,
+ javax.servlet.http,
+ javax.servlet.jsp,
+ javax.servlet.jsp.el,
+ javax.servlet.jsp.jstl.core,
+ javax.servlet.jsp.jstl.fmt,
+ javax.servlet.jsp.jstl.tlv,
+ javax.servlet.jsp.tagext,
+ javax.servlet.resources,
+ javax.xml.parsers,
+ javax.xml.transform,
+ org.apache.commons.logging,
+ org.apache.taglibs.standard.functions,
+ org.apache.taglibs.standard.resources,
+ org.apache.taglibs.standard.tag.common.core,
+ org.apache.taglibs.standard.tag.common.fmt,
+ org.apache.taglibs.standard.tag.rt.core,
+ org.apache.taglibs.standard.tag.rt.fmt,
+ org.apache.taglibs.standard.tei,
+ org.apache.taglibs.standard.tlv,
+ org.osgi.framework,
+ org.slf4j,
+ org.springframework.beans,
+ org.springframework.beans.factory.xml,
+ org.springframework.context.config,
+ org.springframework.stereotype,
+ org.springframework.ui,
+ org.springframework.web,
+ org.springframework.web.bind.annotation,
+ org.springframework.web.servlet,
+ org.springframework.web.servlet.config,
+ org.springframework.web.servlet.view,
+ org.springframework.web.filter,
+ org.springframework.web.context,
+
+ org.apache.felix.dm,
+
+ org.opendaylight.controller.northbound.commons,
+ org.opendaylight.controller.northbound.commons.exception,
+ org.opendaylight.controller.northbound.commons.utils,
+ com.sun.jersey.spi.container.servlet,
+ com.fasterxml.jackson.annotation,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind,
+ javax.xml.bind.annotation,
+ org.apache.catalina.filters,
+ com.fasterxml.jackson.jaxrs.base,
+ com.fasterxml.jackson.jaxrs.json,
+ !org.codehaus.enunciate.jaxrs
+ </Import-Package>
+ <Export-Package></Export-Package>
+ <Web-ContextPath>/simple</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
+ <Bundle-Activator>
+ org.bar.foo.internal.Activator
+ </Bundle-Activator>
+ </instructions>
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+ <buildDirectory>../main/target/main-osgipackage/opendaylight/plugins/</buildDirectory> <!-- TODO use pom var -->
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.toolkit</groupId>
+ <artifactId>web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+
+package org.bar.foo;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.opendaylight.controller.sal.utils.Status;
+
+public interface ISimple {
+ public UUID createData(SimpleData datum);
+ public SimpleData readData(UUID uuid);
+ public Map<UUID, SimpleData> readData();
+ public Status updateData(UUID uuid, SimpleData data);
+ public Status deleteData(UUID uuid);
+}
--- /dev/null
+
+package org.bar.foo;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class SimpleData {
+ @XmlElement
+ private String uuid;
+ @XmlElement
+ private String foo;
+ @XmlElement
+ private String bar;
+
+ public String getUuid() {
+ return uuid;
+ }
+ public String getFoo() {
+ return foo;
+ }
+ public String getBar() {
+ return bar;
+ }
+ public SimpleData() {
+ super();
+ }
+ public SimpleData(String uuid, String foo, String bar) {
+ super();
+ this.uuid = uuid;
+ this.foo = foo;
+ this.bar = bar;
+ }
+}
--- /dev/null
+
+package org.bar.foo.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Set;
+
+import org.apache.felix.dm.Component;
+import org.bar.foo.ISimple;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Activator extends ComponentActivatorAbstractBase {
+ protected static final Logger log = LoggerFactory.getLogger(Activator.class);
+
+ /**
+ * Function called when the activator starts just after some initializations
+ * are done by the ComponentActivatorAbstractBase.
+ *
+ */
+ @Override
+ public void init() {
+ }
+
+ /**
+ * Function called when the activator stops just before the cleanup done by
+ * ComponentActivatorAbstractBase
+ *
+ */
+ @Override
+ public void destroy() {
+ }
+
+ /**
+ * Function that is used to communicate to dependency manager the list of
+ * known implementations for services inside a container
+ *
+ *
+ * @return An array containing all the CLASS objects that will be
+ * instantiated in order to get an fully working implementation
+ * Object
+ */
+ @Override
+ public Object[] getGlobalImplementations() {
+ Object[] res = { Simple.class };
+ return res;
+ }
+
+ /**
+ * Function that is called when configuration of the dependencies is
+ * required.
+ *
+ * @param c
+ * dependency manager Component object, used for configuring the
+ * dependencies exported and imported
+ * @param imp
+ * Implementation class that is being configured, needed as long
+ * as the same routine can configure multiple implementations
+ * @param containerName
+ * The containerName being configured, this allow also optional
+ * per-container different behavior if needed, usually should not
+ * be the case though.
+ */
+ @Override
+ public void configureGlobalInstance(Component c, Object imp) {
+ if (imp.equals(Simple.class)) {
+ Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+ String interfaces[] = null;
+ interfaces = new String[] { ISimple.class.getName() };
+ c.setInterface(interfaces, props);
+ }
+ }
+}
--- /dev/null
+
+package org.bar.foo.internal;
+
+import org.bar.foo.ISimple;
+import org.bar.foo.SimpleData;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.UUID;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+public class Simple implements ISimple {
+ private Map<UUID, SimpleData> data;
+ protected static final Logger log = LoggerFactory.getLogger(Simple.class);
+ @Override
+ public UUID createData(SimpleData datum) {
+ UUID uuid = UUID.randomUUID();
+ SimpleData sData = new SimpleData(uuid.toString(), datum.getFoo(), datum.getBar());
+ data.put(uuid, sData);
+ return uuid;
+ }
+ @Override
+ public SimpleData readData(UUID uuid) {
+ return data.get(uuid);
+ }
+ @Override
+ public Map<UUID, SimpleData> readData() {
+ return data;
+ }
+ @Override
+ public Status updateData(UUID uuid, SimpleData datum) {
+ data.put(uuid, datum);
+ return new Status(StatusCode.SUCCESS);
+ }
+ @Override
+ public Status deleteData(UUID uuid) {
+ data.remove(uuid);
+ return new Status(StatusCode.SUCCESS);
+ }
+ void init() {
+ log.info("Initializing Simple application");
+ data = new ConcurrentHashMap<UUID, SimpleData>();
+ }
+ void start() {
+ log.info("Simple application starting");
+ }
+
+ void stop() {
+ log.info("Simple application stopping");
+ }
+}
--- /dev/null
+
+package org.bar.foo.northbound;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.bar.foo.ISimple;
+import org.bar.foo.SimpleData;
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
+import org.opendaylight.controller.sal.authorization.Privilege;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * Northbound REST API
+ *
+ * This entire web class can be accessed via /northbound prefix as specified in
+ * web.xml
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default.
+ */
+@Path("/")
+public class AppNorthbound {
+ @Context
+ private UriInfo _uriInfo;
+ private String username;
+
+ @Context
+ public void setSecurityContext(SecurityContext context) {
+ if (context != null && context.getUserPrincipal() != null) {
+ username = context.getUserPrincipal().getName();
+ }
+ }
+
+ protected String getUserName() {
+ return username;
+ }
+
+ /**
+ *
+ * Sample GET REST API call
+ *
+ * @return A response string
+ *
+ * <pre>
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/app/northbound/simple
+ *
+ * Response body in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * Sample Northbound API
+ *
+ * Response body in JSON:
+ * Sample Northbound API
+ * </pre>
+ */
+ @Path("/simple")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @StatusCodes()
+ public List<SimpleData> getData() {
+ if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation");
+ }
+ ISimple simple = (ISimple) ServiceHelper.getGlobalInstance(ISimple.class, this);
+ if (simple == null) {
+ throw new ServiceUnavailableException("Simple Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Map<UUID, SimpleData> sDataMap = simple.readData();
+ if (sDataMap != null) {
+ return new ArrayList<SimpleData>(sDataMap.values());
+ }
+ return new ArrayList<SimpleData>();
+ }
+
+ @Path("/simple/{uuid}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(SimpleData.class)
+ @StatusCodes()
+ public SimpleData getData(@PathParam("uuid") String uuid) {
+ if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation");
+ }
+ ISimple simple = (ISimple) ServiceHelper.getGlobalInstance(ISimple.class, this);
+ if (simple == null) {
+ throw new ServiceUnavailableException("Simple Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ return simple.readData(UUID.fromString(uuid));
+ }
+
+ /**
+ *
+ * Sample POST REST API call
+ *
+ * @return A response string
+ *
+ * <pre>
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/app/northbound/simple
+ *
+ * Response body in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * Sample Northbound API
+ *
+ * Response body in JSON:
+ * Sample Northbound API
+ * </pre>
+ */
+ @Path("/simple")
+ @POST
+ @StatusCodes({ @ResponseCode(code = 201, condition = "Data Inserted successfully"),
+ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+ @ResponseCode(code = 500, condition = "Error inserting data"),
+ @ResponseCode(code = 503, condition = "One or more of service is unavailable")})
+ @Consumes({ MediaType.APPLICATION_JSON})
+ public Response createData(@TypeHint(SimpleData.class) SimpleData data) {
+ if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation");
+ }
+ ISimple simple = (ISimple) ServiceHelper.getGlobalInstance(ISimple.class, this);
+ if (simple == null) {
+ throw new ServiceUnavailableException("Simple Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ UUID uuid = simple.createData(data);
+ if (uuid == null) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ return Response.status(Response.Status.CREATED)
+ .header("Location", String.format("%s/%s", _uriInfo.getAbsolutePath().toString(),
+ uuid.toString()))
+ .entity(uuid.toString())
+ .build();
+ }
+
+ /**
+ *
+ * Sample PUT REST API call
+ *
+ * @return A response string
+ *
+ * <pre>
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/app/northbound/simple/{uuid}
+ *
+ * Response body in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * Sample Northbound API
+ *
+ * Response body in JSON:
+ * Sample Northbound API
+ * </pre>
+ */
+ @Path("/simple/{uuid}")
+ @PUT
+ @StatusCodes({ @ResponseCode(code = 200, condition = "Data Updated successfully"),
+ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+ @ResponseCode(code = 500, condition = "Error updating data"),
+ @ResponseCode(code = 503, condition = "One or more of service is unavailable")})
+ @Consumes({ MediaType.APPLICATION_JSON})
+ public Response updateData(@PathParam("uuid") String uuid, @TypeHint(SimpleData.class) SimpleData data) {
+ if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation");
+ }
+ ISimple simple = (ISimple) ServiceHelper.getGlobalInstance(ISimple.class, this);
+ if (simple == null) {
+ throw new ServiceUnavailableException("Simple Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Status status = simple.updateData(UUID.fromString(uuid), data);
+ if (!status.isSuccess()) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ return Response.status(Response.Status.OK).build();
+ }
+
+ /**
+ *
+ * Sample Delete REST API call
+ *
+ * @return A response string
+ *
+ * <pre>
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/app/northbound/simple/{uuid}
+ *
+ * Response body in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * Sample Northbound API
+ *
+ * Response body in JSON:
+ * Sample Northbound API
+ * </pre>
+ */
+ @Path("/simple/{uuid}")
+ @DELETE
+ @StatusCodes({ @ResponseCode(code = 200, condition = "Data Deleted successfully"),
+ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+ @ResponseCode(code = 500, condition = "Error deleting data"),
+ @ResponseCode(code = 503, condition = "One or more of service is unavailable")})
+ @Consumes({ MediaType.APPLICATION_JSON})
+ public Response updateData(@PathParam("uuid") String uuid) {
+ if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation");
+ }
+ ISimple simple = (ISimple) ServiceHelper.getGlobalInstance(ISimple.class, this);
+ if (simple == null) {
+ throw new ServiceUnavailableException("Simple Service " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Status status = simple.deleteData(UUID.fromString(uuid));
+ if (!status.isSuccess()) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ return Response.status(Response.Status.OK).build();
+ }
+
+}
--- /dev/null
+package org.bar.foo.web;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opendaylight.controller.sal.authorization.UserLevel;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.toolkit.web.IDaylightWeb;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * This entire web class can be accessed via /web prefix as specified in web.xml
+ */
+@Controller
+@RequestMapping("/")
+public class AppWeb implements IDaylightWeb {
+ private static final String WEB_NAME = "simple App";
+ private static final String WEB_ID = "simple";
+ private static final short WEB_ORDER = 1;
+ private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
+
+ public AppWeb() {
+ ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
+ }
+
+ @RequestMapping(value = "")
+ public String index(Model model, HttpServletRequest request) {
+ return "main";
+ }
+
+ @Override
+ public String getWebName() {
+ return WEB_NAME;
+ }
+
+ @Override
+ public String getWebId() {
+ return WEB_ID;
+ }
+
+ @Override
+ public short getWebOrder() {
+ return WEB_ORDER;
+ }
+
+ @Override
+ public boolean isAuthorized(UserLevel userLevel) {
+ return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
+ }
+
+ @RequestMapping(value = "login")
+ public String login(final HttpServletRequest request, final HttpServletResponse response) {
+ return "forward:" + "/";
+ }
+
+}
--- /dev/null
+org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
--- /dev/null
+http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
+http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
+http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
+http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
+http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
+http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
+http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
+http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
+http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
+http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
--- /dev/null
+http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
+http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
+http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
+http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
+http\://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd
+http\://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd
+http\://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
+http\://www.springframework.org/schema/context/spring-context-3.2.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.1.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.2.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.1.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.2.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd
+http\://www.springframework.org/schema/task/spring-task-3.1.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd
+http\://www.springframework.org/schema/task/spring-task-3.2.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.1.xsd=org/springframework/cache/config/spring-cache-3.1.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.2.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/security/spring-security-3.1.xsd=org/springframework/security/config/spring-security-3.1.xsd
+http\://www.springframework.org/schema/security/spring-security-3.2.xsd=org/springframework/security/config/spring-security-3.2.xsd
+
--- /dev/null
+# Tooling related information for the beans namespace
+http\://www.springframework.org/schema/beans@name=beans Namespace
+http\://www.springframework.org/schema/beans@prefix=beans
+http\://www.springframework.org/schema/beans@icon=org/springframework/beans/factory/xml/spring-beans.gif
+
+# Tooling related information for the util namespace
+http\://www.springframework.org/schema/util@name=util Namespace
+http\://www.springframework.org/schema/util@prefix=util
+http\://www.springframework.org/schema/util@icon=org/springframework/beans/factory/xml/spring-util.gif
+
+# Tooling related information for the context namespace
+http\://www.springframework.org/schema/context@name=context Namespace
+http\://www.springframework.org/schema/context@prefix=context
+http\://www.springframework.org/schema/context@icon=org/springframework/context/config/spring-context.gif
+
+# Tooling related information for the jee namespace
+http\://www.springframework.org/schema/jee@name=jee Namespace
+http\://www.springframework.org/schema/jee@prefix=jee
+http\://www.springframework.org/schema/jee@icon=org/springframework/ejb/config/spring-jee.gif
+
+# Tooling related information for the scheduling namespace
+http\://www.springframework.org/schema/task@name=task Namespace
+http\://www.springframework.org/schema/task@prefix=task
+http\://www.springframework.org/schema/task@icon=org/springframework/scheduling/config/spring-task.gif
+
+# Tooling related information for the lang namespace
+http\://www.springframework.org/schema/lang@name=lang Namespace
+http\://www.springframework.org/schema/lang@prefix=lang
+http\://www.springframework.org/schema/lang@icon=org/springframework/scripting/config/spring-lang.gif
+
+# Tooling related information for the cache namespace
+http\://www.springframework.org/schema/cache@name=cache Namespace
+http\://www.springframework.org/schema/cache@prefix=cache
+http\://www.springframework.org/schema/cache@icon=org/springframework/cache/config/spring-cache.gif
+
+# Tooling related information for the mvc namespace
+http\://www.springframework.org/schema/mvc@name=mvc Namespace
+http\://www.springframework.org/schema/mvc@prefix=mvc
+http\://www.springframework.org/schema/mvc@icon=org/springframework/web/servlet/config/spring-mvc.gif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+ <context:component-scan base-package="org.bar.foo"/>
+
+ <mvc:resources mapping="/js/**" location="/js/" />
+ <mvc:resources mapping="/css/**" location="/css/" />
+ <mvc:resources mapping="/img/**" location="/img/" />
+ <mvc:annotation-driven/>
+
+ <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+ <property name="prefix" value="/WEB-INF/jsp/"/>
+ <property name="suffix" value=".jsp"/>
+ </bean>
+</beans>
--- /dev/null
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <title>App</title>
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <!-- style -->
+ <link rel="stylesheet" href="/css/ext/pure/pure.css"/>
+ <link rel="stylesheet" href="/css/phoenix.css"/>
+
+ <!-- style app -->
+ <link rel="stylesheet" href="/simple/web/css/simple.css"/>
+
+ <!-- scripts -->
+ <script data-main="/simple/web/js/main" src="/js/ext/requirejs/require.js"></script>
+ </head>
+ <body>
+ <h1>FOO</h1>
+ <h1>Simple OpenDaylight App</h1>
+ <form class="pure-form pure-form-stacked" onsubmit="return false;">
+ <legend>Simple Form</legend>
+ <input type="text" placeholder="Foo" id="foo"/>
+ <input type="text" placeholder="Bar" id="bar"/>
+ <button type="submit" class="pure-button pure-button-primary">Submit</button>
+ </form>
+
+ <table class="pure-table">
+ <thead>
+ <tr>
+ <th>UUID</th>
+ <th>Foo</th>
+ <th>Bar</th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+
+ <filter>
+ <filter-name>CorsFilter</filter-name>
+ <!-- <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> -->
+ <filter-class>org.opendaylight.toolkit.web.CorsFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>CorsFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <security-constraint>
+ <display-name>App</display-name>
+ <web-resource-collection>
+ <web-resource-name>AppWeb</web-resource-name>
+ <url-pattern>/web/js/*</url-pattern>
+ <url-pattern>/web/images/*</url-pattern>
+ <url-pattern>/web/css/*</url-pattern>
+ <url-pattern>/web/favicon.ico</url-pattern>
+ </web-resource-collection>
+ <web-resource-collection>
+ <web-resource-name>AppNorthbound</web-resource-name>
+ <url-pattern>/northbound/*</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ <http-method>PUT</http-method>
+ <http-method>PATCH</http-method>
+ <http-method>DELETE</http-method>
+ <http-method>HEAD</http-method>
+ <http-method>OPTIONS</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>System-Admin</role-name>
+ <role-name>Network-Admin</role-name>
+ <role-name>Network-Operator</role-name>
+ <role-name>Container-User</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>System-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Operator</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Container-User</role-name>
+ </security-role>
+
+ <!-- <login-config> // enabling this auto directs to login page, considering removing this
+ <auth-method>FORM</auth-method>
+ <form-login-config>
+ <form-login-page>/WEB-INF/jsp/login.jsp</form-login-page>
+ <form-error-page>/WEB-INF/jsp/error.jsp</form-error-page>
+ </form-login-config>
+ </login-config>-->
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>opendaylight</realm-name>
+ </login-config>
+
+ <!-- <error-page>
+ <error-code>403</error-code>
+ <location>/WEB-INF/jsp/autherror.jsp</location>
+ </error-page> -->
+
+ <!-- web -->
+ <servlet>
+ <servlet-name>AppWeb</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>AppWeb</servlet-name>
+ <url-pattern>/web/*</url-pattern>
+ </servlet-mapping>
+
+ <listener>
+ <listener-class>org.opendaylight.toolkit.web.ControllerUISessionManager</listener-class>
+ </listener>
+
+ <!-- <session-config> // needs further testing
+ <cookie-config>
+ <path>/</path>
+ </cookie-config>
+ </session-config>-->
+
+ <!-- northbound -->
+ <servlet>
+ <servlet-name>AppNorthbound</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>AppNorthbound</servlet-name>
+ <url-pattern>/northbound/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
--- /dev/null
+/* pure */
+.selected {
+ background: #F3F781
+}
+
+.button-success,
+.button-error {
+ color: white;
+ border-radius: 4px;
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
+}
+
+.button-success {
+ background: rgb(28, 184, 65); /* this is a green */
+}
+
+.button-error {
+ background: rgb(202, 60, 60); /* this is a maroon */
+}
+
+table {
+ width: 100%;
+ margin-bottom: 20px;
+}
+
+fieldset {
+}
+
+fieldset > label {
+ display: block;
+}
+
+fieldset > input {
+ width: 100%;
+}
+
+#simpleContainer {
+ margin-top: 15px;
+}
+
+form {
+ width: 250px;
+ border: 1px dotted #000;
+ padding: 10px;
+ margin: 10px;
+}
--- /dev/null
+// Filename: app.js
+
+define([
+ // These are path alias that we configured in our bootstrap
+ 'jquery',
+ 'jquery-ui',
+ 'underscore'
+], function($, _){
+ // ajax settings
+ $.ajaxSetup({
+ type: 'POST',
+ data: {},
+ dataType: 'json',
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ success: 'callback',
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ function populateTable(data) {
+ var $tbody = $('table tbody');
+ $.each(data, function(idx, d) {
+ var $tr = $(document.createElement('tr'));
+ var $uuid = $(document.createElement('td')).append(d.uuid);
+ var $foo = $(document.createElement('td')).append(d.foo);
+ var $bar = $(document.createElement('td')).append(d.bar);
+ $tr.append($uuid).append($foo).append($bar);
+ $tbody.append($tr);
+ });
+ }
+
+ // bind form submit
+ $('button').click(function() {
+ var simple = {};
+ simple.foo = $('#foo').val();
+ simple.bar = $('#bar').val();
+ $.post('http://10.152.52.197:8080/simple/northbound/simple', JSON.stringify(simple), function(result) {
+ console.log(result);
+ });
+ });
+
+ // populate table
+ $.getJSON('http://10.152.52.197:8080/simple/northbound/simple', function(result) {
+ populateTable(result);
+ });
+
+});
--- /dev/null
+define(
+ [
+ 'backbone',
+ 'underscore',
+ '/simple/web/js/models/SimpleModel.js'
+ ], function(Backbone, _, SimpleModel) {
+ var SimpleCollection = Backbone.Collection.extend({
+ model : SimpleModel,
+ url : '/simple/northbound/simple'
+ });
+ return SimpleCollection;
+ });
--- /dev/null
+// Filename: main.js
+
+require.config({
+ paths: {
+ 'jquery': '/js/ext/jquery/dist/jquery',
+ 'jquery-ui': '/js/ext/jquery-ui/ui/minified/jquery-ui.min',
+ 'underscore': '/js/ext/underscore/underscore'
+ },
+ shim: {
+ 'jquery-ui' : {
+ exports: '$',
+ deps: ['jquery']
+ }
+ }
+});
+
+require([
+ 'app'
+], function(App) {
+});
--- /dev/null
+define(['backbone', 'underscore'], function(Backbone, _) {
+ var SimpleModel = Backbone.Model.extend({
+ idAttribute : 'uuid',
+ defaults : {
+ foo : '',
+ bar : ''
+ },
+ initialize : function() {
+ },
+ setUrlRoot: function() {
+ this.urlRoot = '/simple/northbound/simple';
+ }
+ });
+ return SimpleModel;
+});
--- /dev/null
+<script type="text/template" id="simpleContainer">
+ <div id="simpleDiv" style="margin-left:20px; float: left;">
+ <h3>Connection Application</h3>
+ <table id="simpleTable" class="pure-table pure-table-bordered">
+ <thead>
+ <tr>
+ <th>UUID</th>
+ <th>A</th>
+ <th>B</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% _.each(simple, function(simpleton) { %>
+ <tr data-id="<%= simpleton.id %>">
+ <td><%= simpleton.attributes.uuid %></td>
+ <td><%= simpleton.attributes.foo %></td>
+ <td><%= simpleton.attributes.bar %></td>
+ </tr>
+ <% }); %>
+ </tbody>
+ </table>
+ <form class="pure-form">
+ <fieldset>
+ <legend>Connection Form</legend>
+ <label for="simpleFooInput">Input A</label>
+ <input type="text" id="simpleFooInput" placeholder="Input A" />
+ <label for="simpleBarInput">Input B</label>
+ <input type="text" id="simpleBarInput" placeholder="Input B" />
+ <div id="simpleContainer">
+ <button id="simpleButton" class="pure-button button-success" onclick="return false;">Submit</button>
+ <button id="simpleRemoveButton" class="pure-button button-error" onclick="return false;">Remove</button>
+ <button class="pure-button" onclick="return false;">Cancel</button>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+</script>
--- /dev/null
+define(
+ [
+ 'jquery',
+ 'backbone',
+ 'underscore',
+ '/simple/web/js/collections/SimpleCollection.js',
+ '/simple/web/js/models/SimpleModel.js',
+ '/js/ext/text/text.js!/simple/web/js/templates/simple.html'
+ ], function($, Backbone, _, SimpleCollection, SimpleModel, Template) {
+ var View = Backbone.View.extend({
+ el: $("#main"),
+ initialize: function() {
+ var self = this;
+ this.collection = new SimpleCollection();
+ this.collection.url = 'http://10.152.52.197:8080/simple/northbound/simple';
+ this.collection.fetch({
+ success : function(call, response) {
+ self.render();
+ }
+ });
+ },
+ render: function() {
+ var that = this;
+ var compiledTemplate = _.template(Template,
+ {
+ simple : that.collection.models
+ });
+ $(this.el).append($(compiledTemplate).html());
+ },
+ events : {
+ 'click #simpleContainer button' : 'handleSimpleButton',
+ 'click #simpleTable tbody tr' : 'tableRowClicked'
+ },
+ handleSimpleButton : function(evt) {
+ var self = this;
+ var $button = $(evt.currentTarget);
+ if ($button.attr('id') == 'simpleButton') {
+ var simpleModel = new SimpleModel({
+ foo : $('#simpleFooInput').val(),
+ bar : $('#simpleBarInput').val()
+ });
+ simpleModel.urlRoot = '/simple/northbound/simple';
+ simpleModel.save(null, {
+ dataType: 'text',
+ success: function(model, response) {
+ $('#main').empty();
+ self.updateView();
+ }
+ });
+ } else if ($button.attr('id') == 'simpleRemoveButton') {
+ var id = $('#simpleTable tbody tr.selected').attr('data-id');
+ var simpleModel = self.collection.get(id);
+ simpleModel.setUrlRoot();
+ simpleModel.destroy({
+ dataType: 'text',
+ success: function() {
+ $('#main').empty();
+ self.updateView();
+ },
+ error: function() {
+ $('#main').empty();
+ self.updateView();
+ }
+ });
+ } else {
+ // cancel button
+ $('#simpleInput').val('');
+ }
+ },
+ tableRowClicked : function(evt) {
+ $('#simpleTable tbody tr.selected').removeClass('selected');
+ var $tr = $(evt.currentTarget);
+ $tr.addClass('selected');
+ },
+ updateView : function() {
+ $('#simpleContainer').remove();
+ this.initialize();
+ }
+ });
+ return View;
+ });
--- /dev/null
+package org.opendaylight.toolkit.web;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.springframework.security.web.context.SecurityContextPersistenceFilter;
+
+public class ControllerCustomFilter extends SecurityContextPersistenceFilter {
+
+ @Override
+ public void doFilter(ServletRequest arg0, ServletResponse arg1,
+ FilterChain arg2) throws IOException, ServletException {
+ System.out.println("SPRING");
+ }
+
+}
--- /dev/null
+package org.opendaylight.toolkit.web;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Temporary workaround because built-in tomcat cors filter
+ * isn't working at the moment
+ *
+ * @author Andrew Kim
+ *
+ */
+public class CorsFilter implements Filter {
+ public static String VALID_METHODS = "DELETE, HEAD, GET, OPTIONS, POST, PUT";
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletResponse response = (HttpServletResponse) res;
+ /* Uncomment next line */
+ //response.setHeader("Access-Control-Allow-Origin", "http://<<your-ip>>:8000");
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+ response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
+ response.setHeader("Access-Control-Max-Age", "3600");
+ response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ // TODO Auto-generated method stub
+ }
+
+}
<?xml version="1.0" encoding="ISO-8859-1"?>
-<!-- <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4"> -->
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
- <filter>
- <filter-name>CorsFilter</filter-name>
- <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
- <init-param>
- <param-name>cors.allowed.origins</param-name>
- <param-value>*</param-value>
- </init-param>
- <init-param>
- <param-name>cors.allowed.methods</param-name>
- <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
- </init-param>
- <init-param>
- <param-name>cors.allowed.headers</param-name>
- <param-value>Content-Type,X-Requested-With,accept,authorization, origin,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
- </init-param>
- <init-param>
- <param-name>cors.exposed.headers</param-name>
- <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
- </init-param>
- <init-param>
- <param-name>cors.support.credentials</param-name>
- <param-value>true</param-value>
- </init-param>
- <init-param>
- <param-name>cors.preflight.maxage</param-name>
- <param-value>10</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>CorsFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
+ <filter>
+ <filter-name>CorsFilter</filter-name>
+ <!-- <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>-->
+ <filter-class>org.opendaylight.toolkit.web.CorsFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>CorsFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>free access</web-resource-name>
- <url-pattern>/js/*</url-pattern>
- <url-pattern>/img/*</url-pattern>
- <url-pattern>/css/*</url-pattern>
- <url-pattern>/favicon.ico</url-pattern>
- <url-pattern>/versionProperty/*</url-pattern>
- </web-resource-collection>
- </security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>free access</web-resource-name>
+ <url-pattern>/js/*</url-pattern>
+ <url-pattern>/img/*</url-pattern>
+ <url-pattern>/css/*</url-pattern>
+ <url-pattern>/favicon.ico</url-pattern>
+ <url-pattern>/versionProperty/*</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
- <security-constraint>
- <display-name>RootApp</display-name>
- <web-resource-collection>
- <web-resource-name>RootGUI</web-resource-name>
- <url-pattern>/*</url-pattern>
- <http-method>POST</http-method>
- <http-method>GET</http-method>
- <http-method>PUT</http-method>
- <http-method>DELETE</http-method>
- <http-method>HEAD</http-method>
- </web-resource-collection>
- <auth-constraint>
- <role-name>System-Admin</role-name>
- <role-name>Network-Admin</role-name>
- <role-name>Network-Operator</role-name>
- <role-name>Container-User</role-name>
- </auth-constraint>
- </security-constraint>
+ <security-constraint>
+ <display-name>RootApp</display-name>
+ <web-resource-collection>
+ <web-resource-name>RootGUI</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ <http-method>PUT</http-method>
+ <http-method>DELETE</http-method>
+ <http-method>HEAD</http-method>
+ <http-method>OPTIONS</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>System-Admin</role-name>
+ <role-name>Network-Admin</role-name>
+ <role-name>Network-Operator</role-name>
+ <role-name>Container-User</role-name>
+ </auth-constraint>
+ </security-constraint>
- <security-role>
- <role-name>System-Admin</role-name>
- </security-role>
- <security-role>
- <role-name>Network-Admin</role-name>
- </security-role>
- <security-role>
- <role-name>Network-Operator</role-name>
- </security-role>
- <security-role>
- <role-name>Container-User</role-name>
- </security-role>
+ <security-role>
+ <role-name>System-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Operator</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Container-User</role-name>
+ </security-role>
+ <login-config>
+ <auth-method>FORM</auth-method>
+ <form-login-config>
+ <form-login-page>/WEB-INF/jsp/login.jsp</form-login-page>
+ <form-error-page>/WEB-INF/jsp/error.jsp</form-error-page>
+ </form-login-config>
+ </login-config>
- <login-config>
- <auth-method>FORM</auth-method>
- <form-login-config>
- <form-login-page>/WEB-INF/jsp/login.jsp</form-login-page>
- <form-error-page>/WEB-INF/jsp/error.jsp</form-error-page>
- </form-login-config>
- </login-config>
+ <error-page>
+ <error-code>403</error-code>
+ <location>/WEB-INF/jsp/autherror.jsp</location>
+ </error-page>
- <error-page>
- <error-code>403</error-code>
- <location>/WEB-INF/jsp/autherror.jsp</location>
- </error-page>
+ <servlet>
+ <servlet-name>RootGUI</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <init-param>
+ <param-name>dispatchOptionsRequest</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
- <servlet>
- <servlet-name>RootGUI</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
+ <servlet-mapping>
+ <servlet-name>RootGUI</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>
- <servlet-mapping>
- <servlet-name>RootGUI</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
+ <display-name>OpenDaylight Toolkit</display-name>
+ <description>OpenDaylight Toolkit</description>
- <display-name>OpenDaylight Toolkit</display-name>
- <description>OpenDaylight Toolkit</description>
+ <listener>
+ <listener-class>org.opendaylight.toolkit.web.ControllerUISessionManager</listener-class>
+ </listener>
- <listener>
- <listener-class>org.opendaylight.toolkit.web.ControllerUISessionManager</listener-class>
- </listener>
-
- <session-config>
- <cookie-config>
- <path>/</path>
- </cookie-config>
- </session-config>
+ <session-config>
+ <cookie-config>
+ <path>/</path>
+ </cookie-config>
+ </session-config>
</web-app>
"name" : "OpenDaylight Phoenix External JS",
"version" : "0.0.1",
"dependencies" : {
- "jquery" : "2.1.0",
+ "jquery" : "2.1.1",
+ "jquery-ui" : "1.10.4",
"backbone" : "1.1.2",
"underscore" : "1.6.0",
"requirejs" : "2.1.11",