Merge "Added an archetype odl-model-project"
authorGiovanni Meo <gmeo@cisco.com>
Wed, 28 Aug 2013 10:24:02 +0000 (10:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 28 Aug 2013 10:24:02 +0000 (10:24 +0000)
39 files changed:
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPEvent.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPRequest.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java
opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterContainerServices.java
opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterGlobalServices.java
opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java
opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java
opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java
opendaylight/northbound/flowprogrammer/pom.xml
opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/hosttracker/pom.xml
opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/northbound/networkconfiguration/bridgedomain/pom.xml
opendaylight/northbound/networkconfiguration/bridgedomain/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/staticrouting/pom.xml
opendaylight/northbound/staticrouting/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/statistics/pom.xml
opendaylight/northbound/statistics/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/subnets/pom.xml
opendaylight/northbound/subnets/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/switchmanager/pom.xml
opendaylight/northbound/switchmanager/src/main/resources/WEB-INF/web.xml
opendaylight/northbound/topology/pom.xml
opendaylight/northbound/topology/src/main/resources/WEB-INF/web.xml
opendaylight/samples/northbound/loadbalancer/pom.xml
opendaylight/samples/northbound/loadbalancer/src/main/resources/WEB-INF/web.xml
opendaylight/web/devices/src/main/resources/js/page.js
opendaylight/web/root/pom.xml
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java
opendaylight/web/root/src/main/resources/WEB-INF/web.xml
opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java
opendaylight/web/troubleshoot/src/main/resources/js/page.js
third-party/org.apache.catalina.filters.CorsFilter/README [new file with mode: 0644]
third-party/org.apache.catalina.filters.CorsFilter/pom.xml [new file with mode: 0644]
third-party/org.apache.catalina.filters.CorsFilter/src/main/java/org/apache/catalina/filters/CorsFilter.java [new file with mode: 0644]

index fb92e8df854ce6cd464fd46ae494d976cf5c4e92..f676a79d4951043d22d45ea237f820ee0efc8476 100644 (file)
@@ -56,4 +56,21 @@ public abstract class ARPEvent implements Serializable{
     public InetAddress getTargetIP() {
         return tIP;
     }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("ARPEvent [");
+        if (tIP != null) {
+            builder.append("tIP=")
+                    .append(tIP);
+        }
+        builder.append("]");
+        return builder.toString();
+    }
 }
index 4ca3e42c7c496a00f07503fd04df974ce243de3f..e4388c598fb0eec94a0bb6cdb8f070b4f328af2c 100644 (file)
@@ -13,6 +13,7 @@ import java.net.InetAddress;
 import java.util.Arrays;
 
 import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.utils.HexEncode;
 /*
  * ARP Reply event wrapper
  */
@@ -92,4 +93,36 @@ public class ARPReply extends ARPEvent {
     public NodeConnector getPort() {
         return port;
     }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("ARPReply [");
+        if (port != null) {
+            builder.append("port=")
+                    .append(port)
+                    .append(", ");
+        }
+        if (tMac != null) {
+            builder.append("tMac=")
+                    .append(HexEncode.bytesToHexString(tMac))
+                    .append(", ");
+        }
+        if (sMac != null) {
+            builder.append("sMac=")
+                    .append(HexEncode.bytesToHexString(sMac))
+                    .append(", ");
+        }
+        if (sIP != null) {
+            builder.append("sIP=")
+                    .append(sIP);
+        }
+        builder.append("]");
+        return builder.toString();
+    }
 }
index 7f88a25e31c08388b57c9c1957a40da9a7311feb..39cd4f7131de5539a92ed5661b1806de59781b7a 100644 (file)
@@ -82,4 +82,26 @@ public class ARPRequest extends ARPEvent {
     public HostNodeConnector getHost() {
         return host;
     }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("ARPRequest [");
+        if (subnet != null) {
+            builder.append("subnet=")
+                    .append(subnet)
+                    .append(", ");
+        }
+        if (host != null) {
+            builder.append("host=")
+                    .append(host);
+        }
+        builder.append("]");
+        return builder.toString();
+    }
 }
index f3b22c75d8102a76beeb78229e7faabb89e60bd5..627ab267399978950d66f7dd1625f25a2c405021 100644 (file)
@@ -76,7 +76,8 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     private ConcurrentMap<InetAddress, Short> countDownTimers;
     private Timer periodicTimer;
     private BlockingQueue<ARPCacheEvent> ARPCacheEvents = new LinkedBlockingQueue<ARPCacheEvent>();
-    Thread cacheEventHandler;
+    private Thread cacheEventHandler;
+    private boolean stopping = false;
     /*
      * A cluster allocated cache. Used for synchronizing ARP request/reply
      * events across all cluster controllers. To raise an event, we put() a specific
@@ -224,7 +225,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             try {
                 requestor = new HostNodeConnector(sourceMAC, sourceIP, p, subnet.getVlan());
             } catch (ConstructionException e) {
-                log.debug("Received ARP packet with invalid MAC: {}", sourceMAC);
+                log.debug("Received ARP packet with invalid MAC: {}", HexEncode.bytesToHexString(sourceMAC));
                 return;
             }
             /*
@@ -268,7 +269,8 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                 && (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(targetMAC, getControllerMAC()))) {
             if (connectionManager.isLocal(p.getNode())){
                 if (log.isTraceEnabled()){
-                    log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}", getControllerMAC());
+                    log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}",
+                            HexEncode.bytesToHexString(getControllerMAC()));
                 }
                 sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP);
             } else {
@@ -297,7 +299,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             //Raise a bcast request event, all controllers need to send one
             log.trace("Sending a bcast ARP request for {}", targetIP);
             arpRequestReplyEvent.put(new ARPRequest(targetIP, subnet), false);
-
         } else {
             /*
              * Target host known (across the cluster), send ARP REPLY make sure that targetMAC
@@ -337,6 +338,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
      *  the targetIP as the target Network Address
      */
     protected void sendBcastARPRequest(InetAddress targetIP, Subnet subnet) {
+        log.trace("sendBcatARPRequest targetIP:{} subnet:{}", targetIP, subnet);
         Set<NodeConnector> nodeConnectors;
         if (subnet.isFlatLayer2()) {
             nodeConnectors = new HashSet<NodeConnector>();
@@ -348,11 +350,11 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
 
         for (NodeConnector p : nodeConnectors) {
-
             //fiter out any non-local or internal ports
             if (! connectionManager.isLocal(p.getNode()) || topologyManager.isInternal(p)) {
                 continue;
             }
+            log.trace("Sending toward nodeConnector:{}", p);
             ARP arp = new ARP();
             byte[] senderIP = subnet.getNetworkAddress().getAddress();
             byte[] targetIPByte = targetIP.getAddress();
@@ -393,7 +395,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
      * The sender MAC is the controller's MAC
      */
     protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) {
-
+        log.trace("sendUcastARPRequest host:{} subnet:{}", host, subnet);
         NodeConnector outPort = host.getnodeConnector();
         if (outPort == null) {
             log.error("Failed sending UcastARP because cannot extract output port from Host: {}", host);
@@ -426,6 +428,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         this.dataPacketService.transmitDataPacket(destPkt);
     }
 
+    @Override
     public void find(InetAddress networkAddress) {
         log.trace("Received find IP {}", networkAddress);
 
@@ -445,6 +448,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     /*
      * Probe the host by sending a unicast ARP Request to the host
      */
+    @Override
     public void probe(HostNodeConnector host) {
         log.trace("Received probe host {}", host);
 
@@ -562,6 +566,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
      *
      */
     void destroy() {
+        cacheEventHandler.interrupt();
     }
 
     /**
@@ -571,9 +576,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
      *
      */
     void start() {
+        stopping = false;
         startPeriodicTimer();
         cacheEventHandler.start();
-
     }
 
     /**
@@ -586,6 +591,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     }
 
     void stopping() {
+        stopping = true;
         cancelPeriodicTimer();
     }
 
@@ -666,15 +672,25 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     }
 
     private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC) {
+        if (log.isTraceEnabled()) {
+            log.trace("generateAndSendReply called with params sourceIP:{} sourceMAC:{}", sourceIP,
+                      HexEncode.bytesToHexString(sourceMAC));
+        }
         Set<HostNodeConnector> hosts = arpRequestors.remove(sourceIP);
         if ((hosts == null) || hosts.isEmpty()) {
+            log.trace("Bailing out no requestors Hosts");
             return;
         }
         countDownTimers.remove(sourceIP);
         for (HostNodeConnector host : hosts) {
-            log.trace("Sending ARP Reply with src {}/{}, target {}/{}",
-                    new Object[] { sourceMAC, sourceIP, host.getDataLayerAddressBytes(), host.getNetworkAddress() });
-
+            if (log.isTraceEnabled()) {
+                log.trace("Sending ARP Reply with src {}/{}, target {}/{}",
+                          new Object[] {
+                              HexEncode.bytesToHexString(sourceMAC),
+                              sourceIP,
+                              HexEncode.bytesToHexString(host.getDataLayerAddressBytes()),
+                              host.getNetworkAddress() });
+            }
             if (connectionManager.isLocal(host.getnodeconnectorNode())){
                 sendARPReply(host.getnodeConnector(),
                         sourceMAC,
@@ -682,6 +698,12 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                         host.getDataLayerAddressBytes(),
                         host.getNetworkAddress());
             } else {
+                /*
+                 * In the remote event a requestor moved to another
+                 * controller it may turn out it now we need to send
+                 * the ARP reply from a different controller, this
+                 * cover the case
+                 */
                 arpRequestReplyEvent.put(
                         new ARPReply(
                             host.getnodeConnector(),
@@ -696,6 +718,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
 
     @Override
     public void entryUpdated(ARPEvent key, Boolean new_value, String cacheName, boolean originLocal) {
+        log.trace("Got and entryUpdated for cacheName {} key {} isNew {}", cacheName, key, new_value);
         enqueueARPCacheEvent(key, new_value);
     }
 
@@ -713,6 +736,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             ARPCacheEvent cacheEvent = new ARPCacheEvent(event, new_value);
             if (!ARPCacheEvents.contains(cacheEvent)) {
                 this.ARPCacheEvents.add(cacheEvent);
+                log.trace("Enqueued {}", event);
             }
         } catch (Exception e) {
             log.debug("enqueueARPCacheEvent caught Interrupt Exception for event {}", event);
@@ -725,7 +749,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     private class ARPCacheEventHandler implements Runnable {
         @Override
         public void run() {
-            while (true) {
+            while (!stopping) {
                 try {
                     ARPCacheEvent ev = ARPCacheEvents.take();
                     ARPEvent event = ev.getEvent();
@@ -733,20 +757,23 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                         ARPRequest req = (ARPRequest) event;
                         // If broadcast request
                         if (req.getHost() == null) {
+                            log.trace("Trigger and ARP Broadcast Request upon receipt of {}", req);
                             sendBcastARPRequest(req.getTargetIP(), req.getSubnet());
 
                         //If unicast and local, send reply
                         } else if (connectionManager.isLocal(req.getHost().getnodeconnectorNode())) {
+                            log.trace("ARPCacheEventHandler - sendUcatARPRequest upon receipt of {}", req);
                             sendUcastARPRequest(req.getHost(), req.getSubnet());
                         }
                     } else if (event instanceof ARPReply) {
                         ARPReply rep = (ARPReply) event;
                         // New reply received by controller, notify all awaiting requestors across the cluster
                         if (ev.isNewReply()) {
+                            log.trace("Trigger a generateAndSendReply in response to {}", rep);
                             generateAndSendReply(rep.getTargetIP(), rep.getTargetMac());
-
                         // Otherwise, a specific reply. If local, send out.
                         } else if (connectionManager.isLocal(rep.getPort().getNode())) {
+                            log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep);
                             sendARPReply(rep.getPort(),
                                     rep.getSourceMac(),
                                     rep.getSourceIP(),
index 2f74ec39e4e0b559a2820ed0127c3fc750ba637d..fdf08bcbacdae07bc04fa362958864b1741fc5a4 100644 (file)
@@ -10,7 +10,7 @@
 /**
  * @file   IClusterContainerServices.java
  *
- * @brief  : Set of services and application will expect from the
+ * @brief  : Set of services an application will expect from the
  * clustering services provider. This interface is per-container and so
  * the container parameter is implicitely known
  *
@@ -21,9 +21,9 @@
 package org.opendaylight.controller.clustering.services;
 
 /**
- * Set of services and application will expect from the
- * clustering services provider. This interface is per-container and so
- * the container parameter is implicitly known
+ * Set of services an application will expect from the clustering services
+ * provider. This interface is per-container and so the container parameter is
+ * implicitly known
  *
  */
 public interface IClusterContainerServices extends IClusterServicesCommon {
index 61ad41529d286ae61e4360344f548e9a4461c3f4..58d8c0051b45e2efba4fd9fc587f0a28bc49a1be 100644 (file)
@@ -10,7 +10,7 @@
 /**
  * @file   IClusterGlobalServices.java
  *
- * @brief  : Set of services and application will expect from the
+ * @brief  : Set of services an application will expect from the
  * clustering services provider. This interface is supposed to have
  * Global scope
  *
@@ -21,9 +21,8 @@
 package org.opendaylight.controller.clustering.services;
 
 /**
- * Set of services and application will expect from the
- * clustering services provider. This interface is supposed to have
- * Global scope
+ * Set of services an application will expect from the clustering services
+ * provider. This interface is supposed to have Global scope
  *
  */
 public interface IClusterGlobalServices extends IClusterServicesCommon {
index 68960baa07a0d157b1c101fbdb6832208e54376c..a27b00eb1feb7d433cc8c46bed7ae84aa1baabc5 100644 (file)
@@ -10,7 +10,7 @@
 /**
  * @file   IClusterServices.java
  *
- * @brief  : Set of services and application will expect from the
+ * @brief  : Set of services an application will expect from the
  * clustering services provider
  *
  * Contract between the applications and the clustering service
@@ -33,7 +33,7 @@ import javax.transaction.SystemException;
 import javax.transaction.Transaction;
 
 /**
- * Set of services and application will expect from the
+ * Set of services an application will expect from the
  * clustering services provider
  *
  */
index e292f73e540ee63aa07b7b28f9904c7d993ca28f..6850c64a0ed15774c3808773241659da7b75d7aa 100644 (file)
@@ -10,7 +10,7 @@
 /**
  * @file   IClusterServicesCommon.java
  *
- * @brief  : Set of services and application will expect from the
+ * @brief  : Set of services an application will expect from the
  * clustering services provider. This interface is going to be the
  * base for per-container and Global services and so the container
  * parameter is omitted but who uses knows about it
@@ -35,11 +35,12 @@ import javax.transaction.SystemException;
 import javax.transaction.Transaction;
 
 /**
- * @deprecated for internal use
- * Set of services and application will expect from the
- * clustering services provider. This interface is going to be the
- * base for per-container and Global services and so the container
- * parameter is omitted but who uses knows about it
+ * This WILL NOT BE USED DIRECTLY, but VIA SUBCLASS
+ *
+ * Set of services and application will expect from the clustering services
+ * provider. This interface is going to be the base for per-container and Global
+ * services and so the container parameter is omitted but who uses knows about
+ * it
  *
  */
 public interface IClusterServicesCommon {
index abf508efc2bb308f2727f69d9e4d8cc9b80da35e..4dc4e6fa2e35efee89a617b014eacda9d3678fdf 100644 (file)
@@ -68,6 +68,7 @@
     <module>../../../third-party/net.sf.jung2</module>
     <module>../../../third-party/jersey-servlet</module>
     <module>../../../third-party/commons/thirdparty</module>
+    <module>../../../third-party/org.apache.catalina.filters.CorsFilter</module>
 
     <!-- SAL bundles -->
     <module>../../sal/api</module>
index eac854c10674f796fae64ec174aaef07aad4aed5..1b2128957e9352ffd93a0a0991abf91ec3a354ea 100644 (file)
@@ -232,6 +232,8 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
                     if (future != null) {
                         try {
                             host = future.get();
+                        } catch (InterruptedException ioe) {
+                            log.trace("Thread interrupted {}", ioe);
                         } catch (Exception e) {
                             log.error("", e);
                         }
index 7061954e80e199b2a52c49eeace78ad27b9d4518..283e756cd1b9edab8170158fb4152a6e20d365cc 100644 (file)
@@ -102,12 +102,15 @@ public class Activator implements BundleActivator {
                 this.bundlecontext = ctxt;
         }
 
+        @Override
         public void run () {
             try {
                 this.bundlecontext.getBundle(0).stop();
                 log.debug("shutdown handler thread called");
             } catch (BundleException e) {
                 log.debug("Bundle couldn't be stopped");
+            } catch (Exception e) {
+                log.debug("Unhandled exception");
             }
         }
     }
index 94991c573efa29267d11c6ea800af85a5b99edb6..201bf477ee210aa254e11e8de846c11d9b3aa0d0 100644 (file)
@@ -43,7 +43,8 @@
               org.opendaylight.controller.northbound.commons.utils,
               org.opendaylight.controller.sal.authorization,
               org.opendaylight.controller.usermanager,
-                          com.sun.jersey.spi.container.servlet,
+              com.sun.jersey.spi.container.servlet,
+              org.apache.catalina.filters,
               javax.ws.rs,
               javax.ws.rs.core,
               javax.xml.bind.annotation,
       <artifactId>com.sun.jersey.jersey-servlet</artifactId>
       <version>1.17-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 4cedf2df8975bd6414fd28920dcd8db5c41b3183..5b3cec2292163b1a4ca7836dae4ea35d9e26f630 100644 (file)
           <url-pattern>/*</url-pattern>
         </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
@@ -48,4 +87,4 @@
                 <auth-method>BASIC</auth-method>
                 <realm-name>opendaylight</realm-name>
         </login-config>
-</web-app>
\ No newline at end of file
+</web-app>
index 40aaf462ad8ec1a4f07a0ad36c4db51cf904cd93..b588c0715b222d74927ffd94799bdc51cd01503c 100644 (file)
@@ -51,6 +51,7 @@
               javax.xml.bind.annotation,
               javax.xml.bind,
               org.slf4j,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Web-ContextPath>/controller/nb/v2/host</Web-ContextPath>
       <artifactId>enunciate-core-annotations</artifactId>
       <version>${enunciate.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 0fa8b95dd00368600f7cfcc26196b4eca07adda0..01b8fedce125301acaf2bc3b1c8adf2bbea9d3fa 100644 (file)
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index 6958ecb96ad77e7da668d62d0f0871b6158c5e60..85b77b2f4de000f37b2ebe487623a6aa5fc0df8a 100644 (file)
@@ -1366,6 +1366,8 @@ public class NorthboundIT {
                 mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans", "1.0.0"),
                 mavenBundle("org.opendaylight.controller.thirdparty", "net.sf.jung2", "2.0.1-SNAPSHOT"),
                 mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet", "1.17-SNAPSHOT"),
+                mavenBundle("org.opendaylight.controller.thirdparty", "org.apache.catalina.filters.CorsFilter",
+                            "7.0.42-SNAPSHOT").noStart(),
 
                 // Jersey needs to be started before the northbound application
                 // bundles, using a lower start level
index cba14fdc78e92aeb1da39c5fc947a335ce4d26ec..8cb13200431c1a49d82727aba07025deb332f602 100644 (file)
@@ -52,6 +52,7 @@
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Export-Package>
       <artifactId>com.sun.jersey.jersey-servlet</artifactId>
       <version>1.17-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index b7f35c3f96d97bfa142bd163f94aaa9781b6b8d9..f4de222acc0f33140565c98dec2420ff2f11c9a4 100644 (file)
                 <url-pattern>/*</url-pattern>
         </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>BridgeDomain Configuration NorthBound API</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index bb88465907191dd2bc2fea0d7f7061190a3d1aee..fa9341f681bd62d9941dfc8d581d7a2f9091af85 100644 (file)
@@ -50,6 +50,7 @@
               javax.ws.rs.core,
               javax.xml.bind.annotation,
               javax.xml.bind,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Export-Package>
       <artifactId>com.sun.jersey.jersey-servlet</artifactId>
       <version>1.17-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 4a040c1a1f861e3f38e0bf762cb5170832710b19..0bf186b50e0c6616504c896219252d0f6ef4d52c 100644 (file)
   </servlet>
 
         <servlet-mapping>
-                <servlet-name>JAXRSStaticRouting</servlet-name>
-                <url-pattern>/*</url-pattern>
+          <servlet-name>JAXRSStaticRouting</servlet-name>
+          <url-pattern>/*</url-pattern>
         </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index cad50e299834a633a03b36e95776e93120bd9abe..db4c4a941342a23f8cb34c58c9d0f6c7f1e73b7f 100644 (file)
@@ -58,6 +58,7 @@
                 javax.xml.bind.annotation,
                 javax.xml.bind,
                 org.slf4j,
+                org.apache.catalina.filters,
                 !org.codehaus.enunciate.jaxrs
               </Import-Package>
             <Export-Package>
       <artifactId>enunciate-core-annotations</artifactId>
       <version>${enunciate.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index f152aa75a2b1af7321ccf33d9776563750e82967..db0460ba56db2c4b2541cbecaa94d45df3fe4158 100644 (file)
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index a3931beadd34540de0c3d97cdd84e83ffe6428cd..43b8f9ebb08bb87acbf84639be432352417b8df4 100644 (file)
@@ -65,6 +65,7 @@
               javax.xml.bind,
               javax.xml.bind.annotation,
               org.slf4j,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Export-Package>
       <artifactId>enunciate-core-annotations</artifactId>
       <version>${enunciate.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index f7eccef6666f7d2ec8f0dc2d8b36215e0c9801a1..a5c70ee9d82bc232a9b0578a88bd76f37973fb5f 100644 (file)
     <servlet-name>JAXRSSubnets</servlet-name>
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index 556c964055b2c335d80f57e90839b0adabf48a62..dd7ff9a75b45bf2fe1b42ec2d68e3a99ffe8e2fa 100644 (file)
@@ -51,6 +51,7 @@
               javax.xml.bind.annotation,
               javax.xml.bind,
               org.slf4j,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Web-ContextPath>/controller/nb/v2/switch</Web-ContextPath>
       <artifactId>enunciate-core-annotations</artifactId>
       <version>${enunciate.version}</version>
     </dependency>
-
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 188b21b24d000014c1f498f6f4e101ed8dd25c21..ea6fcc99b2ab475cec28d4d93ee4d778bd36b1ea 100644 (file)
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index 726f7975f0f0f8c9441156cbf8a98886f9faf052..007bdbebdcf053e3365e1462732257ac05b8b7b9 100644 (file)
@@ -54,6 +54,7 @@
               javax.xml.bind,
               javax.xml.bind.annotation,
               org.slf4j,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Web-ContextPath>/controller/nb/v2/topology</Web-ContextPath>
       <artifactId>com.sun.jersey.jersey-servlet</artifactId>
       <version>1.17-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index a46e433054831408b9907b33f7d95443e1cf104e..bc818c8c6d46e1a3d86d46f162a9bd628e51e8a5 100644 (file)
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index dc23940d55ae6cf4ef30a96ac0b35dd2bdab1bb8..ed078a0551e28f49e5f7747de9f52f892155709d 100644 (file)
@@ -51,6 +51,7 @@
               javax.xml.bind.annotation,
               javax.xml.bind,
               org.slf4j,
+              org.apache.catalina.filters,
               !org.codehaus.enunciate.jaxrs
             </Import-Package>
             <Web-ContextPath>/one/nb/v2/lb</Web-ContextPath>
       <artifactId>enunciate-core-annotations</artifactId>
       <version>${enunciate.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index aac4647de669a930dbd0ffa39d30130434946054..0e8f8c1b5646b7eafcb223a7c4d5dd009cda52df 100644 (file)
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+        <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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>NB api</web-resource-name>
-                        <url-pattern>/*</url-pattern>
-                </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>
+          <web-resource-collection>
+            <web-resource-name>NB api</web-resource-name>
+            <url-pattern>/*</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>
+          </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>
index b90e5cbfa03c786e504a78f0ce8a0a003a09d8ce..6cc2b61d1b2a75f9e2636e21e45f3d174b134caf 100644 (file)
@@ -449,7 +449,8 @@ one.f.switchmanager.subnetGatewayConfig = {
             addIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addIP",
             addPorts: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addPorts",
             removeIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_removeIP",
-            datagrid: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_datagrid"
+            datagrid: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_datagrid",
+            selectAll: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_selectAll"
         }, 
         modal: {
             modal: "one_f_switchmanager_subnetGatewayConfig_id_modal_modal",
@@ -496,11 +497,12 @@ one.f.switchmanager.subnetGatewayConfig = {
                         var url = one.f.switchmanager.rootUrl + "/subnetGateway/delete";
                         one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) {
                             if (response.status == true) {
-                                // refresh dashlet by passing dashlet div as param
-                                one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
+                                // refresh dashlet by passing dashlet div as param 
+                                one.lib.alert("Subnet Gateway(s) successfully removed");
                             } else {
-                                alert(response.message);
+                                one.lib.alert(response.message);
                             }
+                            one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
                         });
                     }
                 });
@@ -524,7 +526,25 @@ one.f.switchmanager.subnetGatewayConfig = {
                 }, "table-striped table-condensed");
             $dashlet.append($gridHTML);
             var dataSource = one.f.switchmanager.subnetGatewayConfig.data.devicesgrid(content);
-            $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
+            $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource})
+            .on("loaded", function() {
+                $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).click(function() {
+                    $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find(':checkbox').prop('checked',
+                        $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll).is(':checked'));
+                });
+                $(".subnetGatewayConfig").click(function(){
+                    if (!$('.subnetGatewayConfig[type=checkbox]:not(:checked)').length) {
+                        $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                          true);
+                    } else {
+                        $("#"+one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                         false);
+                    }
+                    event.stopPropagation();
+                });
+             });
         });
     },
     ajax : {
@@ -700,7 +720,8 @@ one.f.switchmanager.subnetGatewayConfig = {
                     columns: [
                         {
                             property: 'selector',
-                            label: ' ',
+                            label: "<input type='checkbox'  id='"
+                                +one.f.switchmanager.subnetGatewayConfig.id.dashlet.selectAll+"'/>",
                             sortable: false
                         },
                         {
@@ -722,7 +743,8 @@ one.f.switchmanager.subnetGatewayConfig = {
                     data: data.nodeData,
                     formatter: function(items) {
                         $.each(items, function(index, tableRow) {
-                            tableRow["selector"] = '<input type="checkbox" id=' + tableRow["name"] + '></input>';
+                            tableRow["selector"] = '<input type="checkbox" class="subnetGatewayConfig" id=' 
+                                + tableRow["name"] + '></input>';
                             var json = tableRow["nodePorts"];
                             var nodePorts = JSON.parse(json);
                             var nodePortHtml = "<div>";
@@ -831,7 +853,8 @@ one.f.switchmanager.staticRouteConfig = {
         dashlet: {
             add: "one_f_switchmanager_staticRouteConfig_id_dashlet_add",
             remove: "one_f_switchmanager_staticRouteConfig_id_dashlet_remove",
-            datagrid: "one_f_switchmanager_staticRouteConfig_id_dashlet_datagrid"
+            datagrid: "one_f_switchmanager_staticRouteConfig_id_dashlet_datagrid",
+            selectAll: "one_f_switchmanager_staticRouteConfig_id_dashlet_selectAll"
         }, 
         modal: {
             modal: "one_f_switchmanager_staticRouteConfig_id_modal_modal",
@@ -875,11 +898,12 @@ one.f.switchmanager.staticRouteConfig = {
                         var url = one.f.switchmanager.rootUrl + "/staticRoute/delete";
                         one.f.switchmanager.staticRouteConfig.ajax.main(url, requestData, function(response) {
                             if (response.status == true) {
-                                // refresh dashlet by passing dashlet div as param
-                                one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet"));
+                                // refresh dashlet by passing dashlet div as param 
+                                one.lib.alert("Static Routes(s) successfully removed");
                             } else {
-                                alert(response.message);
+                                one.lib.alert(response.message);
                             }
+                            one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet"));
                         });
                     }
                 });
@@ -893,7 +917,25 @@ one.f.switchmanager.staticRouteConfig = {
                 }, "table-striped table-condensed");
             $dashlet.append($gridHTML);
             var dataSource = one.f.switchmanager.staticRouteConfig.data.staticRouteConfigGrid(content);
-            $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
+            $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource})
+            .on("loaded", function() {
+                $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).click(function() {
+                    $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find(':checkbox').prop('checked',
+                        $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll).is(':checked'));
+                });
+                $(".staticRoute").click(function(){
+                    if (!$('.staticRoute[type=checkbox]:not(:checked)').length) {
+                        $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                          true);
+                    } else {
+                        $("#"+one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                         false);
+                    }
+                    event.stopPropagation();
+                });
+             });
         });
     },
     // device ajax calls
@@ -981,7 +1023,8 @@ one.f.switchmanager.staticRouteConfig = {
                     columns: [
                         {
                             property: 'selector',
-                            label: ' ',
+                            label: "<input type='checkbox'  id='"
+                                +one.f.switchmanager.staticRouteConfig.id.dashlet.selectAll+"'/>",
                             sortable: false
                         },
                         {
@@ -1003,7 +1046,7 @@ one.f.switchmanager.staticRouteConfig = {
                     data: data.nodeData,
                     formatter: function(items) {
                         $.each(items, function(index, item) {
-                            item["selector"] = '<input type="checkbox" id=' + item["name"] + '></input>';
+                            item["selector"] = '<input type="checkbox" class="staticRoute" id=' + item["name"] + '></input>';
                         });
 
                     },
@@ -1037,7 +1080,8 @@ one.f.switchmanager.spanPortConfig = {
         dashlet: {
             add: "one_f_switchmanager_spanPortConfig_id_dashlet_add",
             remove: "one_f_switchmanager_spanPortConfig_id_dashlet_remove",
-            datagrid: "one_f_switchmanager_spanPortConfig_id_dashlet_datagrid"
+            datagrid: "one_f_switchmanager_spanPortConfig_id_dashlet_datagrid",
+            selectAllFlows: "one_f_switchmanager_spanPortConfig_id_dashlet_selectAllFlows"
         }, 
         modal: {
             modal: "one_f_switchmanager_spanPortConfig_id_modal_modal",
@@ -1087,10 +1131,11 @@ one.f.switchmanager.spanPortConfig = {
                         one.f.switchmanager.spanPortConfig.ajax.main(url, requestData, function(response) {
                             if (response.status == true) {
                                 // refresh dashlet by passing dashlet div as param
-                                one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet"));
+                                one.lib.alert("Span Port(s) successfully removed");
                             } else {
-                                alert(response.message);
+                                one.lib.alert(response.message);
                             }
+                            one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet"));
                         });
                     }
                 });
@@ -1104,10 +1149,25 @@ one.f.switchmanager.spanPortConfig = {
                 }, "table-striped table-condensed");
             $dashlet.append($gridHTML);
             var dataSource = one.f.switchmanager.spanPortConfig.data.spanPortConfigGrid(content);
-            $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
-
-
-
+            $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource})
+            .on("loaded", function() {
+                $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).click(function() {
+                    $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find(':checkbox').prop('checked',
+                        $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll).is(':checked'));
+                });
+                $(".spanPortConfig").click(function(){
+                    if (!$('.spanPortConfig[type=checkbox]:not(:checked)').length) {
+                        $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                          true);
+                    } else {
+                        $("#"+one.f.switchmanager.spanPortConfig.id.dashlet.selectAll)
+                            .prop("checked",
+                         false);
+                    }
+                    event.stopPropagation();
+                });
+             });
         });
     },
     // device ajax calls
@@ -1216,7 +1276,8 @@ one.f.switchmanager.spanPortConfig = {
                     columns: [
                         {
                             property: 'selector',
-                            label: ' ',
+                            label: "<input type='checkbox'  id='"
+                                +one.f.switchmanager.spanPortConfig.id.dashlet.selectAll+"'/>",
                             sortable: false
                         },
                         {
@@ -1233,7 +1294,7 @@ one.f.switchmanager.spanPortConfig = {
                     data: data.nodeData,
                     formatter: function(items) {
                         $.each(items, function(index, item) {
-                            item["selector"] = '<input type="checkbox" spanPort=' + encodeURIComponent(item["json"]) + '></input>';
+                            item["selector"] = '<input type="checkbox" class="spanPortConfig" spanPort=' + encodeURIComponent(item["json"]) + '></input>';
                         });
                     },
                     delay: 0
index ed899c5b5c7e50e74581b13b5f8988fd78a18a69..809751d443e47f74819964df5e4b287248eaaba9 100644 (file)
@@ -73,7 +73,8 @@
               org.springframework.web.servlet.view.json,
               org.springframework.web.filter,
               org.springframework.web.context,
-              org.springframework.util
+              org.springframework.util,
+              org.apache.catalina.filters
             </Import-Package>
             <Export-Package>
               org.opendaylight.controller.web
       <version>3.2.1.RELEASE</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+      <version>7.0.42-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 3add0e6a40b22d0745421d7f0d4db46a82babbfa..4435dcd58b987a6248977a1d7326f6069d34a0eb 100644 (file)
@@ -61,7 +61,7 @@ public class DaylightWebUtil {
     public static void auditlog(String moduleName, String user, String action, String resource,
             String containerName) {
         String auditMsg = "";
-        String mode = "WEB";
+        String mode = "UI";
         if (containerName != null) {
             auditMsg = "Mode: " + mode + " User " + user + " "  + action + " " + moduleName + " " + resource + " in container "
                     + containerName;
index 557b9c74f5a0b3fd28cb53281339105c242d9698..0c5cb3ac2719341726cb1235c2c714490feafdf5 100644 (file)
@@ -6,28 +6,66 @@
         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</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>
+
         <security-constraint>
-                <web-resource-collection>
-                        <web-resource-name>free access</web-resource-name>
-                        <url-pattern>/js/*</url-pattern>
-                        <url-pattern>/images/*</url-pattern>
-                        <url-pattern>/css/*</url-pattern>
-                        <url-pattern>/favicon.ico</url-pattern>
-                </web-resource-collection>
+          <web-resource-collection>
+             <web-resource-name>free access</web-resource-name>
+             <url-pattern>/js/*</url-pattern>
+             <url-pattern>/images/*</url-pattern>
+             <url-pattern>/css/*</url-pattern>
+             <url-pattern>/favicon.ico</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>
-                </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>
+           <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-role>
index 71ba687f2d4b16e22c43de7586f6d75c7119b7ac..eab07418b46fa51ff9fd3524dc0160337537c70c 100644 (file)
@@ -21,7 +21,15 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
 import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.authorization.UserLevel;
 import org.opendaylight.controller.sal.core.Description;
@@ -56,7 +64,7 @@ public class Troubleshoot implements IDaylightWeb {
     private static final List<String> flowStatsColumnNames = Arrays.asList("Node", "In Port",
             "DL Src", "DL Dst", "DL Type", "DL Vlan", "NW Src", "NW Dst",
             "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
-            "Time (s)", "Timeout (s)", "Out Port(s)", "Out Vlan",
+            "Time (s)", "Timeout (s)",
             "Priority");
     private static final List<String> portStatsColumnNames = Arrays.asList("Node Connector",
             "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
@@ -346,29 +354,60 @@ public class Troubleshoot implements IDaylightWeb {
 
         StringBuffer actions = new StringBuffer();
         StringBuffer outPorts = new StringBuffer();
-        String outVlanId = null;
         for (Action action : flow.getActions()) {
-            actions.append(action.getType().toString() + "\n");
+
             if (action instanceof Output) {
                 Output ao = (Output) action;
                 if (outPorts.length() > 0) {
                     outPorts.append(" ");
                 }
-                outPorts.append(ao.getPort().getNodeConnectorIdAsString());
+                actions.append(action.getType().toString() + " = "
+                        + ao.getPort().getNodeConnectorIdAsString() + "<br>");
             } else if (action instanceof SetVlanId) {
                 SetVlanId av = (SetVlanId) action;
-                outVlanId = String.valueOf(av.getVlanId());
+                String outVlanId = String.valueOf(av.getVlanId());
+                actions.append(action.getType().toString() + " = " + outVlanId
+                        + "<br>");
+            } else if (action instanceof SetDlSrc) {
+                SetDlSrc ads = (SetDlSrc) action;
+                actions.append(action.getType().toString() + " = "
+                        + HexEncode.bytesToHexStringFormat(ads.getDlAddress()) + "<br>");
+            } else if (action instanceof SetDlDst) {
+                SetDlDst add = (SetDlDst) action;
+                actions.append(action.getType().toString() + " = "
+                        + HexEncode.bytesToHexStringFormat(add.getDlAddress())
+                        + "<br>");
+            } else if (action instanceof SetNwSrc) {
+                SetNwSrc ans = (SetNwSrc) action;
+                actions.append(action.getType().toString() + " = "
+                        + ans.getAddressAsString() + "<br>");
+            } else if (action instanceof SetNwDst) {
+                SetNwDst and = (SetNwDst) action;
+                actions.append(action.getType().toString() + " = "
+                        + and.getAddressAsString() + "<br>");
+            } else if (action instanceof SetNwTos) {
+                SetNwTos ant = (SetNwTos) action;
+                actions.append(action.getType().toString() + " = "
+                        + ant.getNwTos() + "<br>");
+            } else if (action instanceof SetTpSrc) {
+                SetTpSrc ads = (SetTpSrc) action;
+                actions.append(action.getType().toString() + " = "
+                        + ads.getPort() + "<br>");
+            } else if (action instanceof SetTpDst) {
+                SetTpDst atd = (SetTpDst) action;
+                actions.append(action.getType().toString() + " = "
+                        + atd.getPort() + "<br>");
+            } else if (action instanceof SetVlanPcp) {
+                SetVlanPcp avp = (SetVlanPcp) action;
+                actions.append(action.getType().toString() + " = "
+                        + avp.getPcp() + "<br>");
+                // } else if (action instanceof SetDlSrc) {
+                // SetDlSrc ads = (SetDlSrc) action;
+            } else {
+                actions.append(action.getType().toString() + "<br>");
             }
         }
-        if (outPorts.length() == 0) {
-            outPorts.append("*");
-        }
-        if (outVlanId == null) {
-            outVlanId = "*";
-        }
         row.put("actions", actions.toString());
-        row.put("outPorts", outPorts.toString());
-        row.put("outVlanId", outVlanId);
         row.put("durationSeconds",
                 ((Integer) flowOnNode.getDurationSeconds()).toString());
         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
index 3f0dc9e81231b50dc098011f20dd53f11ffdcfeb..1eb2cf0094ea3a4d801c6dc0a31955b257a5898c 100644 (file)
@@ -400,16 +400,6 @@ one.f.troubleshooting.existingNodes = {
                             label: 'Idle Timeout',
                             sortable: true
                         },
-                        {
-                            property: 'outPorts',
-                            label: 'Out Ports',
-                            sortable: true
-                        },
-                        {
-                            property: 'outVlanId',
-                            label: 'Out VlanId',
-                            sortable: true
-                        },
                         {
                             property: 'priority',
                             label: 'Priority',
@@ -442,8 +432,6 @@ one.f.troubleshooting.existingNodes = {
                     entry.push(value["packetCount"]);
                     entry.push(value["durationSeconds"]);
                     entry.push(value["idleTimeout"]);
-                    entry.push(value["outPorts"]);
-                    entry.push(value["outVlanId"]);
                     entry.push(value["priority"]);
                     tr.entry = entry;
                     result.push(tr);
diff --git a/third-party/org.apache.catalina.filters.CorsFilter/README b/third-party/org.apache.catalina.filters.CorsFilter/README
new file mode 100644 (file)
index 0000000..e2d22ab
--- /dev/null
@@ -0,0 +1,12 @@
+See: http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter
+And: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
+This is done to allow a web page using javascript to be able to make calls
+to our REST APIs even though it does not originate in our domain.
+
+This bundle just rolls up org.apache.catalina.filters.CorsFilter and adds it as a 
+fragment to the org.apache.catalina bundle.
+
+The reason this is necessary is because the CorsFilter class was originally added
+at Tomcat 7.0.42, and we are using 7.0.32.  As the CorsFilter class is a simple one,
+with very few dependencies, this seemed the best way to bring it in.
+
diff --git a/third-party/org.apache.catalina.filters.CorsFilter/pom.xml b/third-party/org.apache.catalina.filters.CorsFilter/pom.xml
new file mode 100644 (file)
index 0000000..0789d50
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <!-- Get some common settings for the project we are using it in -->
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.thirdparty</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+    <relativePath>../commons/thirdparty</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.controller.thirdparty</groupId>
+  <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+  <version>7.0.42-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Fragment-Host>
+              org.apache.catalina
+            </Fragment-Host>
+            <Import-Package>
+              javax.servlet,
+              javax.servlet.http,
+              org.apache.catalina.filters,
+              org.apache.juli.logging,
+              org.apache.tomcat.util.res,
+              org.apache.catalina.comet,
+              org.apache.tomcat.util
+            </Import-Package>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet</artifactId>
+      <version>3.0.0.v201112011016</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.juli.extras</artifactId>
+      <version>7.0.32.v201211081135</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.tomcat.util</artifactId>
+      <version>7.0.32.v201211201952</version>
+    </dependency>
+    <dependency>
+      <groupId>orbit</groupId>
+      <artifactId>org.apache.catalina</artifactId>
+      <version>7.0.32.v201211201336</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/third-party/org.apache.catalina.filters.CorsFilter/src/main/java/org/apache/catalina/filters/CorsFilter.java b/third-party/org.apache.catalina.filters.CorsFilter/src/main/java/org/apache/catalina/filters/CorsFilter.java
new file mode 100644 (file)
index 0000000..8069c99
--- /dev/null
@@ -0,0 +1,1166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.catalina.filters;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+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;
+
+import org.apache.catalina.filters.Constants;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * <p>
+ * A {@link Filter} that enable client-side cross-origin requests by
+ * implementing W3C's CORS (<b>C</b>ross-<b>O</b>rigin <b>R</b>esource
+ * <b>S</b>haring) specification for resources. Each {@link HttpServletRequest}
+ * request is inspected as per specification, and appropriate response headers
+ * are added to {@link HttpServletResponse}.
+ * </p>
+ *
+ * <p>
+ * By default, it also sets following request attributes, that help to
+ * determine the nature of the request downstream.
+ * <ul>
+ * <li><b>cors.isCorsRequest:</b> Flag to determine if the request is a CORS
+ * request. Set to <code>true</code> if a CORS request; <code>false</code>
+ * otherwise.</li>
+ * <li><b>cors.request.origin:</b> The Origin URL, i.e. the URL of the page from
+ * where the request is originated.</li>
+ * <li>
+ * <b>cors.request.type:</b> Type of request. Possible values:
+ * <ul>
+ * <li>SIMPLE: A request which is not preceded by a pre-flight request.</li>
+ * <li>ACTUAL: A request which is preceded by a pre-flight request.</li>
+ * <li>PRE_FLIGHT: A pre-flight request.</li>
+ * <li>NOT_CORS: A normal same-origin request.</li>
+ * <li>INVALID_CORS: A cross-origin request which is invalid.</li>
+ * </ul>
+ * </li>
+ * <li><b>cors.request.headers:</b> Request headers sent as
+ * 'Access-Control-Request-Headers' header, for pre-flight request.</li>
+ * </ul>
+ * </p>
+ *
+ * @see <a href="http://www.w3.org/TR/cors/">CORS specification</a>
+ *
+ */
+public final class CorsFilter implements Filter {
+
+    private static final Log log = LogFactory.getLog(CorsFilter.class);
+
+    private static final StringManager sm =
+            StringManager.getManager(Constants.Package);
+
+
+    /**
+     * A {@link Collection} of origins consisting of zero or more origins that
+     * are allowed access to the resource.
+     */
+    private final Collection<String> allowedOrigins;
+
+    /**
+     * Determines if any origin is allowed to make request.
+     */
+    private boolean anyOriginAllowed;
+
+    /**
+     * A {@link Collection} of methods consisting of zero or more methods that
+     * are supported by the resource.
+     */
+    private final Collection<String> allowedHttpMethods;
+
+    /**
+     * A {@link Collection} of headers consisting of zero or more header field
+     * names that are supported by the resource.
+     */
+    private final Collection<String> allowedHttpHeaders;
+
+    /**
+     * A {@link Collection} of exposed headers consisting of zero or more header
+     * field names of headers other than the simple response headers that the
+     * resource might use and can be exposed.
+     */
+    private final Collection<String> exposedHeaders;
+
+    /**
+     * A supports credentials flag that indicates whether the resource supports
+     * user credentials in the request. It is true when the resource does and
+     * false otherwise.
+     */
+    private boolean supportsCredentials;
+
+    /**
+     * Indicates (in seconds) how long the results of a pre-flight request can
+     * be cached in a pre-flight result cache.
+     */
+    private long preflightMaxAge;
+
+    /**
+     * Determines if the request should be decorated or not.
+     */
+    private boolean decorateRequest;
+
+
+    public CorsFilter() {
+        this.allowedOrigins = new HashSet<String>();
+        this.allowedHttpMethods = new HashSet<String>();
+        this.allowedHttpHeaders = new HashSet<String>();
+        this.exposedHeaders = new HashSet<String>();
+    }
+
+
+    @Override
+    public void doFilter(final ServletRequest servletRequest,
+            final ServletResponse servletResponse, final FilterChain filterChain)
+            throws IOException, ServletException {
+        if (!(servletRequest instanceof HttpServletRequest) ||
+                !(servletResponse instanceof HttpServletResponse)) {
+            throw new ServletException(sm.getString("corsFilter.onlyHttp"));
+        }
+
+        // Safe to downcast at this point.
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+        // Determines the CORS request type.
+        CorsFilter.CORSRequestType requestType = checkRequestType(request);
+
+        // Adds CORS specific attributes to request.
+        if (decorateRequest) {
+            CorsFilter.decorateCORSProperties(request, requestType);
+        }
+        switch (requestType) {
+        case SIMPLE:
+            // Handles a Simple CORS request.
+            this.handleSimpleCORS(request, response, filterChain);
+            break;
+        case ACTUAL:
+            // Handles an Actual CORS request.
+            this.handleSimpleCORS(request, response, filterChain);
+            break;
+        case PRE_FLIGHT:
+            // Handles a Pre-flight CORS request.
+            this.handlePreflightCORS(request, response, filterChain);
+            break;
+        case NOT_CORS:
+            // Handles a Normal request that is not a cross-origin request.
+            this.handleNonCORS(request, response, filterChain);
+            break;
+        default:
+            // Handles a CORS request that violates specification.
+            this.handleInvalidCORS(request, response, filterChain);
+            break;
+        }
+    }
+
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        // Initialize defaults
+        parseAndStore(DEFAULT_ALLOWED_ORIGINS, DEFAULT_ALLOWED_HTTP_METHODS,
+                DEFAULT_ALLOWED_HTTP_HEADERS, DEFAULT_EXPOSED_HEADERS,
+                DEFAULT_SUPPORTS_CREDENTIALS, DEFAULT_PREFLIGHT_MAXAGE,
+                DEFAULT_DECORATE_REQUEST);
+
+        if (filterConfig != null) {
+            String configAllowedOrigins = filterConfig
+                    .getInitParameter(PARAM_CORS_ALLOWED_ORIGINS);
+            String configAllowedHttpMethods = filterConfig
+                    .getInitParameter(PARAM_CORS_ALLOWED_METHODS);
+            String configAllowedHttpHeaders = filterConfig
+                    .getInitParameter(PARAM_CORS_ALLOWED_HEADERS);
+            String configExposedHeaders = filterConfig
+                    .getInitParameter(PARAM_CORS_EXPOSED_HEADERS);
+            String configSupportsCredentials = filterConfig
+                    .getInitParameter(PARAM_CORS_SUPPORT_CREDENTIALS);
+            String configPreflightMaxAge = filterConfig
+                    .getInitParameter(PARAM_CORS_PREFLIGHT_MAXAGE);
+            String configDecorateRequest = filterConfig
+                    .getInitParameter(PARAM_CORS_REQUEST_DECORATE);
+
+            parseAndStore(configAllowedOrigins, configAllowedHttpMethods,
+                    configAllowedHttpHeaders, configExposedHeaders,
+                    configSupportsCredentials, configPreflightMaxAge,
+                    configDecorateRequest);
+        }
+    }
+
+
+    /**
+     * Handles a CORS request of type {@link CORSRequestType}.SIMPLE.
+     *
+     * @param request
+     *            The {@link HttpServletRequest} object.
+     * @param response
+     *            The {@link HttpServletResponse} object.
+     * @param filterChain
+     *            The {@link FilterChain} object.
+     * @throws IOException
+     * @throws ServletException
+     * @see <a href="http://www.w3.org/TR/cors/#resource-requests">Simple
+     *      Cross-Origin Request, Actual Request, and Redirects</a>
+     */
+    protected void handleSimpleCORS(final HttpServletRequest request,
+            final HttpServletResponse response, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        CorsFilter.CORSRequestType requestType = checkRequestType(request);
+        if (!(requestType == CorsFilter.CORSRequestType.SIMPLE ||
+                requestType == CorsFilter.CORSRequestType.ACTUAL)) {
+            throw new IllegalArgumentException(
+                    sm.getString("corsFilter.wrongType2",
+                            CorsFilter.CORSRequestType.SIMPLE,
+                            CorsFilter.CORSRequestType.ACTUAL));
+        }
+
+        final String origin = request
+                .getHeader(CorsFilter.REQUEST_HEADER_ORIGIN);
+        final String method = request.getMethod();
+
+        // Section 6.1.2
+        if (!isOriginAllowed(origin)) {
+            handleInvalidCORS(request, response, filterChain);
+            return;
+        }
+
+        if (!allowedHttpMethods.contains(method)) {
+            handleInvalidCORS(request, response, filterChain);
+            return;
+        }
+
+        // Section 6.1.3
+        // Add a single Access-Control-Allow-Origin header.
+        if (anyOriginAllowed && !supportsCredentials) {
+            // If resource doesn't support credentials and if any origin is
+            // allowed
+            // to make CORS request, return header with '*'.
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                    "*");
+        } else {
+            // If the resource supports credentials add a single
+            // Access-Control-Allow-Origin header, with the value of the Origin
+            // header as value.
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                    origin);
+        }
+
+        // Section 6.1.3
+        // If the resource supports credentials, add a single
+        // Access-Control-Allow-Credentials header with the case-sensitive
+        // string "true" as value.
+        if (supportsCredentials) {
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS,
+                    "true");
+        }
+
+        // Section 6.1.4
+        // If the list of exposed headers is not empty add one or more
+        // Access-Control-Expose-Headers headers, with as values the header
+        // field names given in the list of exposed headers.
+        if ((exposedHeaders != null) && (exposedHeaders.size() > 0)) {
+            String exposedHeadersString = join(exposedHeaders, ",");
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS,
+                    exposedHeadersString);
+        }
+
+        // Forward the request down the filter chain.
+        filterChain.doFilter(request, response);
+    }
+
+
+    /**
+     * Handles CORS pre-flight request.
+     *
+     * @param request
+     *            The {@link HttpServletRequest} object.
+     * @param response
+     *            The {@link HttpServletResponse} object.
+     * @param filterChain
+     *            The {@link FilterChain} object.
+     * @throws IOException
+     * @throws ServletException
+     */
+    protected void handlePreflightCORS(final HttpServletRequest request,
+            final HttpServletResponse response, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        CORSRequestType requestType = checkRequestType(request);
+        if (requestType != CORSRequestType.PRE_FLIGHT) {
+            throw new IllegalArgumentException(
+                    sm.getString("corsFilter.wrongType1",
+                            CORSRequestType.PRE_FLIGHT.name().toLowerCase()));
+        }
+
+        final String origin = request
+                .getHeader(CorsFilter.REQUEST_HEADER_ORIGIN);
+
+        // Section 6.2.2
+        if (!isOriginAllowed(origin)) {
+            handleInvalidCORS(request, response, filterChain);
+            return;
+        }
+
+        // Section 6.2.3
+        String accessControlRequestMethod = request.getHeader(
+                CorsFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD);
+        if (accessControlRequestMethod == null ||
+                !HTTP_METHODS.contains(accessControlRequestMethod.trim())) {
+            handleInvalidCORS(request, response, filterChain);
+            return;
+        } else {
+            accessControlRequestMethod = accessControlRequestMethod.trim();
+        }
+
+        // Section 6.2.4
+        String accessControlRequestHeadersHeader = request.getHeader(
+                CorsFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS);
+        List<String> accessControlRequestHeaders = new LinkedList<String>();
+        if (accessControlRequestHeadersHeader != null &&
+                !accessControlRequestHeadersHeader.trim().isEmpty()) {
+            String[] headers = accessControlRequestHeadersHeader.trim().split(
+                    ",");
+            for (String header : headers) {
+                accessControlRequestHeaders.add(header.trim().toLowerCase());
+            }
+        }
+
+        // Section 6.2.5
+        if (!allowedHttpMethods.contains(accessControlRequestMethod)) {
+            handleInvalidCORS(request, response, filterChain);
+            return;
+        }
+
+        // Section 6.2.6
+        if (!accessControlRequestHeaders.isEmpty()) {
+            for (String header : accessControlRequestHeaders) {
+                if (!allowedHttpHeaders.contains(header)) {
+                    handleInvalidCORS(request, response, filterChain);
+                    return;
+                }
+            }
+        }
+
+        // Section 6.2.7
+        if (supportsCredentials) {
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                    origin);
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS,
+                    "true");
+        } else {
+            if (anyOriginAllowed) {
+                response.addHeader(
+                        CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                        "*");
+            } else {
+                response.addHeader(
+                        CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+                        origin);
+            }
+        }
+
+        // Section 6.2.8
+        if (preflightMaxAge > 0) {
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_MAX_AGE,
+                    String.valueOf(preflightMaxAge));
+        }
+
+        // Section 6.2.9
+        response.addHeader(
+                CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_METHODS,
+                accessControlRequestMethod);
+
+        // Section 6.2.10
+        if ((allowedHttpHeaders != null) && (!allowedHttpHeaders.isEmpty())) {
+            response.addHeader(
+                    CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_HEADERS,
+                    join(allowedHttpHeaders, ","));
+        }
+
+        // Do not forward the request down the filter chain.
+    }
+
+
+    /**
+     * Handles a request, that's not a CORS request, but is a valid request i.e.
+     * it is not a cross-origin request. This implementation, just forwards the
+     * request down the filter chain.
+     *
+     * @param request
+     *            The {@link HttpServletRequest} object.
+     * @param response
+     *            The {@link HttpServletResponse} object.
+     * @param filterChain
+     *            The {@link FilterChain} object.
+     * @throws IOException
+     * @throws ServletException
+     */
+    private void handleNonCORS(final HttpServletRequest request,
+            final HttpServletResponse response, final FilterChain filterChain)
+            throws IOException, ServletException {
+        // Let request pass.
+        filterChain.doFilter(request, response);
+    }
+
+
+    /**
+     * Handles a CORS request that violates specification.
+     *
+     * @param request
+     *            The {@link HttpServletRequest} object.
+     * @param response
+     *            The {@link HttpServletResponse} object.
+     * @param filterChain
+     *            The {@link FilterChain} object.
+     */
+    private void handleInvalidCORS(final HttpServletRequest request,
+            final HttpServletResponse response, final FilterChain filterChain) {
+        String origin = request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN);
+        String method = request.getMethod();
+        String accessControlRequestHeaders = request.getHeader(
+                REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS);
+
+        response.setContentType("text/plain");
+        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+        response.resetBuffer();
+
+        if (log.isDebugEnabled()) {
+            // Debug so no need for i18n
+            StringBuilder message =
+                    new StringBuilder("Invalid CORS request; Origin=");
+            message.append(origin);
+            message.append(";Method=");
+            message.append(method);
+            if (accessControlRequestHeaders != null) {
+                message.append(";Access-Control-Request-Headers=");
+                message.append(accessControlRequestHeaders);
+            }
+            log.debug(message.toString());
+        }
+    }
+
+
+    @Override
+    public void destroy() {
+        // NOOP
+    }
+
+
+    /**
+     * Decorates the {@link HttpServletRequest}, with CORS attributes.
+     * <ul>
+     * <li><b>cors.isCorsRequest:</b> Flag to determine if request is a CORS
+     * request. Set to <code>true</code> if CORS request; <code>false</code>
+     * otherwise.</li>
+     * <li><b>cors.request.origin:</b> The Origin URL.</li>
+     * <li><b>cors.request.type:</b> Type of request. Values:
+     * <code>simple</code> or <code>preflight</code> or <code>not_cors</code> or
+     * <code>invalid_cors</code></li>
+     * <li><b>cors.request.headers:</b> Request headers sent as
+     * 'Access-Control-Request-Headers' header, for pre-flight request.</li>
+     * </ul>
+     *
+     * @param request
+     *            The {@link HttpServletRequest} object.
+     * @param corsRequestType
+     *            The {@link CORSRequestType} object.
+     */
+    protected static void decorateCORSProperties(
+            final HttpServletRequest request,
+            final CORSRequestType corsRequestType) {
+        if (request == null) {
+            throw new IllegalArgumentException(
+                    sm.getString("corsFilter.nullRequest"));
+        }
+
+        if (corsRequestType == null) {
+            throw new IllegalArgumentException(
+                    sm.getString("corsFilter.nullRequestType"));
+        }
+
+        switch (corsRequestType) {
+        case SIMPLE:
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST,
+                    Boolean.TRUE);
+            request.setAttribute(CorsFilter.HTTP_REQUEST_ATTRIBUTE_ORIGIN,
+                    request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN));
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE,
+                    corsRequestType.name().toLowerCase());
+            break;
+        case ACTUAL:
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST,
+                    Boolean.TRUE);
+            request.setAttribute(CorsFilter.HTTP_REQUEST_ATTRIBUTE_ORIGIN,
+                    request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN));
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE,
+                    corsRequestType.name().toLowerCase());
+            break;
+        case PRE_FLIGHT:
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST,
+                    Boolean.TRUE);
+            request.setAttribute(CorsFilter.HTTP_REQUEST_ATTRIBUTE_ORIGIN,
+                    request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN));
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE,
+                    corsRequestType.name().toLowerCase());
+            String headers = request.getHeader(
+                    REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS);
+            if (headers == null) {
+                headers = "";
+            }
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_HEADERS, headers);
+            break;
+        case NOT_CORS:
+            request.setAttribute(
+                    CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST,
+                    Boolean.FALSE);
+            break;
+        default:
+            // Don't set any attributes
+            break;
+        }
+    }
+
+
+    /**
+     * Joins elements of {@link Set} into a string, where each element is
+     * separated by the provided separator.
+     *
+     * @param elements
+     *            The {@link Set} containing elements to join together.
+     * @param joinSeparator
+     *            The character to be used for separating elements.
+     * @return The joined {@link String}; <code>null</code> if elements
+     *         {@link Set} is null.
+     */
+    protected static String join(final Collection<String> elements,
+            final String joinSeparator) {
+        String separator = ",";
+        if (elements == null) {
+            return null;
+        }
+        if (joinSeparator != null) {
+            separator = joinSeparator;
+        }
+        StringBuilder buffer = new StringBuilder();
+        boolean isFirst = true;
+        for (String element : elements) {
+            if (!isFirst) {
+                buffer.append(separator);
+            } else {
+                isFirst = false;
+            }
+
+            if (element != null) {
+                buffer.append(element);
+            }
+        }
+
+        return buffer.toString();
+    }
+
+
+    /**
+     * Determines the request type.
+     *
+     * @param request
+     */
+    protected CORSRequestType checkRequestType(final HttpServletRequest request) {
+        CORSRequestType requestType = CORSRequestType.INVALID_CORS;
+        if (request == null) {
+            throw new IllegalArgumentException(
+                    sm.getString("corsFilter.nullRequest"));
+        }
+        String originHeader = request.getHeader(REQUEST_HEADER_ORIGIN);
+        // Section 6.1.1 and Section 6.2.1
+        if (originHeader != null) {
+            if (originHeader.isEmpty()) {
+                requestType = CORSRequestType.INVALID_CORS;
+            } else if (!isValidOrigin(originHeader)) {
+                requestType = CORSRequestType.INVALID_CORS;
+            } else {
+                String method = request.getMethod();
+                if (method != null && HTTP_METHODS.contains(method)) {
+                    if ("OPTIONS".equals(method)) {
+                        String accessControlRequestMethodHeader =
+                                request.getHeader(
+                                        REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD);
+                        if (accessControlRequestMethodHeader != null &&
+                                !accessControlRequestMethodHeader.isEmpty()) {
+                            requestType = CORSRequestType.PRE_FLIGHT;
+                        } else if (accessControlRequestMethodHeader != null &&
+                                accessControlRequestMethodHeader.isEmpty()) {
+                            requestType = CORSRequestType.INVALID_CORS;
+                        } else {
+                            requestType = CORSRequestType.ACTUAL;
+                        }
+                    } else if ("GET".equals(method) || "HEAD".equals(method)) {
+                        requestType = CORSRequestType.SIMPLE;
+                    } else if ("POST".equals(method)) {
+                        String contentType = request.getContentType();
+                        if (contentType != null) {
+                            contentType = contentType.toLowerCase().trim();
+                            if (SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES
+                                    .contains(contentType)) {
+                                requestType = CORSRequestType.SIMPLE;
+                            } else {
+                                requestType = CORSRequestType.ACTUAL;
+                            }
+                        }
+                    } else if (COMPLEX_HTTP_METHODS.contains(method)) {
+                        requestType = CORSRequestType.ACTUAL;
+                    }
+                }
+            }
+        } else {
+            requestType = CORSRequestType.NOT_CORS;
+        }
+
+        return requestType;
+    }
+
+
+    /**
+     * Checks if the Origin is allowed to make a CORS request.
+     *
+     * @param origin
+     *            The Origin.
+     * @return <code>true</code> if origin is allowed; <code>false</code>
+     *         otherwise.
+     */
+    private boolean isOriginAllowed(final String origin) {
+        if (anyOriginAllowed) {
+            return true;
+        }
+
+        // If 'Origin' header is a case-sensitive match of any of allowed
+        // origins, then return true, else return false.
+        return allowedOrigins.contains(origin);
+    }
+
+
+    /**
+     * Parses each param-value and populates configuration variables. If a param
+     * is provided, it overrides the default.
+     *
+     * @param allowedOrigins
+     *            A {@link String} of comma separated origins.
+     * @param allowedHttpMethods
+     *            A {@link String} of comma separated HTTP methods.
+     * @param allowedHttpHeaders
+     *            A {@link String} of comma separated HTTP headers.
+     * @param exposedHeaders
+     *            A {@link String} of comma separated headers that needs to be
+     *            exposed.
+     * @param supportsCredentials
+     *            "true" if support credentials needs to be enabled.
+     * @param preflightMaxAge
+     *            The amount of seconds the user agent is allowed to cache the
+     *            result of the pre-flight request.
+     * @throws ServletException
+     */
+    private void parseAndStore(final String allowedOrigins,
+            final String allowedHttpMethods, final String allowedHttpHeaders,
+            final String exposedHeaders, final String supportsCredentials,
+            final String preflightMaxAge, final String decorateRequest)
+                    throws ServletException {
+        if (allowedOrigins != null) {
+            if (allowedOrigins.trim().equals("*")) {
+                this.anyOriginAllowed = true;
+            } else {
+                this.anyOriginAllowed = false;
+                Set<String> setAllowedOrigins =
+                        parseStringToSet(allowedOrigins);
+                this.allowedOrigins.clear();
+                this.allowedOrigins.addAll(setAllowedOrigins);
+            }
+        }
+
+        if (allowedHttpMethods != null) {
+            Set<String> setAllowedHttpMethods =
+                    parseStringToSet(allowedHttpMethods);
+            this.allowedHttpMethods.clear();
+            this.allowedHttpMethods.addAll(setAllowedHttpMethods);
+        }
+
+        if (allowedHttpHeaders != null) {
+            Set<String> setAllowedHttpHeaders =
+                    parseStringToSet(allowedHttpHeaders);
+            Set<String> lowerCaseHeaders = new HashSet<String>();
+            for (String header : setAllowedHttpHeaders) {
+                String lowerCase = header.toLowerCase();
+                lowerCaseHeaders.add(lowerCase);
+            }
+            this.allowedHttpHeaders.clear();
+            this.allowedHttpHeaders.addAll(lowerCaseHeaders);
+        }
+
+        if (exposedHeaders != null) {
+            Set<String> setExposedHeaders = parseStringToSet(exposedHeaders);
+            this.exposedHeaders.clear();
+            this.exposedHeaders.addAll(setExposedHeaders);
+        }
+
+        if (supportsCredentials != null) {
+            // For any value other then 'true' this will be false.
+            this.supportsCredentials = Boolean
+                    .parseBoolean(supportsCredentials);
+        }
+
+        if (preflightMaxAge != null) {
+            try {
+                if (!preflightMaxAge.isEmpty()) {
+                    this.preflightMaxAge = Long.parseLong(preflightMaxAge);
+                } else {
+                    this.preflightMaxAge = 0L;
+                }
+            } catch (NumberFormatException e) {
+                throw new ServletException(
+                        sm.getString("corsFilter.invalidPreflightMaxAge"), e);
+            }
+        }
+
+        if (decorateRequest != null) {
+            // For any value other then 'true' this will be false.
+            this.decorateRequest = Boolean.parseBoolean(decorateRequest);
+        }
+    }
+
+    /**
+     * Takes a comma separated list and returns a Set<String>.
+     *
+     * @param data
+     *            A comma separated list of strings.
+     * @return Set<String>
+     */
+    private Set<String> parseStringToSet(final String data) {
+        String[] splits;
+
+        if (data != null && data.length() > 0) {
+            splits = data.split(",");
+        } else {
+            splits = new String[] {};
+        }
+
+        Set<String> set = new HashSet<String>();
+        if (splits.length > 0) {
+            for (String split : splits) {
+                set.add(split.trim());
+            }
+        }
+
+        return set;
+    }
+
+
+    /**
+     * Checks if a given origin is valid or not. Criteria:
+     * <ul>
+     * <li>If an encoded character is present in origin, it's not valid.</li>
+     * <li>Origin should be a valid {@link URI}</li>
+     * </ul>
+     *
+     * @param origin
+     * @see <a href="http://tools.ietf.org/html/rfc952">RFC952</a>
+     */
+    protected static boolean isValidOrigin(String origin) {
+        // Checks for encoded characters. Helps prevent CRLF injection.
+        if (origin.contains("%")) {
+            return false;
+        }
+
+        URI originURI;
+
+        try {
+            originURI = new URI(origin);
+        } catch (URISyntaxException e) {
+            return false;
+        }
+        // If scheme for URI is null, return false. Return true otherwise.
+        return originURI.getScheme() != null;
+
+    }
+
+
+    /**
+     * Determines if any origin is allowed to make CORS request.
+     *
+     * @return <code>true</code> if it's enabled; false otherwise.
+     */
+    public boolean isAnyOriginAllowed() {
+        return anyOriginAllowed;
+    }
+
+
+    /**
+     * Returns a {@link Set} of headers that should be exposed by browser.
+     */
+    public Collection<String> getExposedHeaders() {
+        return exposedHeaders;
+    }
+
+
+    /**
+     * Determines is supports credentials is enabled.
+     */
+    public boolean isSupportsCredentials() {
+        return supportsCredentials;
+    }
+
+
+    /**
+     * Returns the preflight response cache time in seconds.
+     *
+     * @return Time to cache in seconds.
+     */
+    public long getPreflightMaxAge() {
+        return preflightMaxAge;
+    }
+
+
+    /**
+     * Returns the {@link Set} of allowed origins that are allowed to make
+     * requests.
+     *
+     * @return {@link Set}
+     */
+    public Collection<String> getAllowedOrigins() {
+        return allowedOrigins;
+    }
+
+
+    /**
+     * Returns a {@link Set} of HTTP methods that are allowed to make requests.
+     *
+     * @return {@link Set}
+     */
+    public Collection<String> getAllowedHttpMethods() {
+        return allowedHttpMethods;
+    }
+
+
+    /**
+     * Returns a {@link Set} of headers support by resource.
+     *
+     * @return {@link Set}
+     */
+    public Collection<String> getAllowedHttpHeaders() {
+        return allowedHttpHeaders;
+    }
+
+
+    // -------------------------------------------------- CORS Response Headers
+    /**
+     * The Access-Control-Allow-Origin header indicates whether a resource can
+     * be shared based by returning the value of the Origin request header in
+     * the response.
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN =
+            "Access-Control-Allow-Origin";
+
+    /**
+     * The Access-Control-Allow-Credentials header indicates whether the
+     * response to request can be exposed when the omit credentials flag is
+     * unset. When part of the response to a preflight request it indicates that
+     * the actual request can include user credentials.
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS =
+            "Access-Control-Allow-Credentials";
+
+    /**
+     * The Access-Control-Expose-Headers header indicates which headers are safe
+     * to expose to the API of a CORS API specification
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS =
+            "Access-Control-Expose-Headers";
+
+    /**
+     * The Access-Control-Max-Age header indicates how long the results of a
+     * preflight request can be cached in a preflight result cache.
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_MAX_AGE =
+            "Access-Control-Max-Age";
+
+    /**
+     * The Access-Control-Allow-Methods header indicates, as part of the
+     * response to a preflight request, which methods can be used during the
+     * actual request.
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_METHODS =
+            "Access-Control-Allow-Methods";
+
+    /**
+     * The Access-Control-Allow-Headers header indicates, as part of the
+     * response to a preflight request, which header field names can be used
+     * during the actual request.
+     */
+    public static final String RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_HEADERS =
+            "Access-Control-Allow-Headers";
+
+    // -------------------------------------------------- CORS Request Headers
+    /**
+     * The Origin header indicates where the cross-origin request or preflight
+     * request originates from.
+     */
+    public static final String REQUEST_HEADER_ORIGIN = "Origin";
+
+    /**
+     * The Access-Control-Request-Method header indicates which method will be
+     * used in the actual request as part of the preflight request.
+     */
+    public static final String REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD =
+            "Access-Control-Request-Method";
+
+    /**
+     * The Access-Control-Request-Headers header indicates which headers will be
+     * used in the actual request as part of the preflight request.
+     */
+    public static final String REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS =
+            "Access-Control-Request-Headers";
+
+    // ----------------------------------------------------- Request attributes
+    /**
+     * The prefix to a CORS request attribute.
+     */
+    public static final String HTTP_REQUEST_ATTRIBUTE_PREFIX = "cors.";
+
+    /**
+     * Attribute that contains the origin of the request.
+     */
+    public static final String HTTP_REQUEST_ATTRIBUTE_ORIGIN =
+            HTTP_REQUEST_ATTRIBUTE_PREFIX + "request.origin";
+
+    /**
+     * Boolean value, suggesting if the request is a CORS request or not.
+     */
+    public static final String HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST =
+            HTTP_REQUEST_ATTRIBUTE_PREFIX + "isCorsRequest";
+
+    /**
+     * Type of CORS request, of type {@link CORSRequestType}.
+     */
+    public static final String HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE =
+            HTTP_REQUEST_ATTRIBUTE_PREFIX + "request.type";
+
+    /**
+     * Request headers sent as 'Access-Control-Request-Headers' header, for
+     * pre-flight request.
+     */
+    public static final String HTTP_REQUEST_ATTRIBUTE_REQUEST_HEADERS =
+            HTTP_REQUEST_ATTRIBUTE_PREFIX + "request.headers";
+
+    // -------------------------------------------------------------- Constants
+    /**
+     * Enumerates varies types of CORS requests. Also, provides utility methods
+     * to determine the request type.
+     */
+    protected static enum CORSRequestType {
+        /**
+         * A simple HTTP request, i.e. it shouldn't be pre-flighted.
+         */
+        SIMPLE,
+        /**
+         * A HTTP request that needs to be pre-flighted.
+         */
+        ACTUAL,
+        /**
+         * A pre-flight CORS request, to get meta information, before a
+         * non-simple HTTP request is sent.
+         */
+        PRE_FLIGHT,
+        /**
+         * Not a CORS request, but a normal request.
+         */
+        NOT_CORS,
+        /**
+         * An invalid CORS request, i.e. it qualifies to be a CORS request, but
+         * fails to be a valid one.
+         */
+        INVALID_CORS
+    }
+
+    /**
+     * {@link Collection} of HTTP methods. Case sensitive.
+     *
+     * @see  <a href="http://tools.ietf.org/html/rfc2616#section-5.1.1"
+     *       >http://tools.ietf.org/html/rfc2616#section-5.1.1</a>
+     *
+     */
+    public static final Collection<String> HTTP_METHODS =
+            new HashSet<String>(Arrays.asList("OPTIONS", "GET", "HEAD", "POST",
+                    "PUT", "DELETE", "TRACE", "CONNECT"));
+    /**
+     * {@link Collection} of non-simple HTTP methods. Case sensitive.
+     */
+    public static final Collection<String> COMPLEX_HTTP_METHODS =
+            new HashSet<String>(Arrays.asList("PUT", "DELETE", "TRACE",
+                    "CONNECT"));
+    /**
+     * {@link Collection} of Simple HTTP methods. Case sensitive.
+     *
+     * @see  <a href="http://www.w3.org/TR/cors/#terminology"
+     *       >http://www.w3.org/TR/cors/#terminology</a>
+     */
+    public static final Collection<String> SIMPLE_HTTP_METHODS =
+            new HashSet<String>(Arrays.asList("GET", "POST", "HEAD"));
+
+    /**
+     * {@link Collection} of Simple HTTP request headers. Case in-sensitive.
+     *
+     * @see  <a href="http://www.w3.org/TR/cors/#terminology"
+     *       >http://www.w3.org/TR/cors/#terminology</a>
+     */
+    public static final Collection<String> SIMPLE_HTTP_REQUEST_HEADERS =
+            new HashSet<String>(Arrays.asList("Accept", "Accept-Language",
+                    "Content-Language"));
+
+    /**
+     * {@link Collection} of Simple HTTP request headers. Case in-sensitive.
+     *
+     * @see  <a href="http://www.w3.org/TR/cors/#terminology"
+     *       >http://www.w3.org/TR/cors/#terminology</a>
+     */
+    public static final Collection<String> SIMPLE_HTTP_RESPONSE_HEADERS =
+            new HashSet<String>(Arrays.asList("Cache-Control",
+                    "Content-Language", "Content-Type", "Expires",
+                    "Last-Modified", "Pragma"));
+
+    /**
+     * {@link Collection} of Simple HTTP request headers. Case in-sensitive.
+     *
+     * @see  <a href="http://www.w3.org/TR/cors/#terminology"
+     *       >http://www.w3.org/TR/cors/#terminology</a>
+     */
+    public static final Collection<String> SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES =
+            new HashSet<String>(Arrays.asList(
+                    "application/x-www-form-urlencoded",
+                    "multipart/form-data", "text/plain"));
+
+    // ------------------------------------------------ Configuration Defaults
+    /**
+     * By default, all origins are allowed to make requests.
+     */
+    public static final String DEFAULT_ALLOWED_ORIGINS = "*";
+
+    /**
+     * By default, following methods are supported: GET, POST, HEAD and OPTIONS.
+     */
+    public static final String DEFAULT_ALLOWED_HTTP_METHODS =
+            "GET,POST,HEAD,OPTIONS";
+
+    /**
+     * By default, time duration to cache pre-flight response is 30 mins.
+     */
+    public static final String DEFAULT_PREFLIGHT_MAXAGE = "1800";
+
+    /**
+     * By default, support credentials is turned on.
+     */
+    public static final String DEFAULT_SUPPORTS_CREDENTIALS = "true";
+
+    /**
+     * By default, following headers are supported:
+     * Origin,Accept,X-Requested-With, Content-Type,
+     * Access-Control-Request-Method, and Access-Control-Request-Headers.
+     */
+    public static final String DEFAULT_ALLOWED_HTTP_HEADERS =
+            "Origin,Accept,X-Requested-With,Content-Type," +
+            "Access-Control-Request-Method,Access-Control-Request-Headers";
+
+    /**
+     * By default, none of the headers are exposed in response.
+     */
+    public static final String DEFAULT_EXPOSED_HEADERS = "";
+
+    /**
+     * By default, request is decorated with CORS attributes.
+     */
+    public static final String DEFAULT_DECORATE_REQUEST = "true";
+
+    // ----------------------------------------Filter Config Init param-name(s)
+    /**
+     * Key to retrieve allowed origins from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_ALLOWED_ORIGINS =
+            "cors.allowed.origins";
+
+    /**
+     * Key to retrieve support credentials from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_SUPPORT_CREDENTIALS =
+            "cors.support.credentials";
+
+    /**
+     * Key to retrieve exposed headers from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_EXPOSED_HEADERS =
+            "cors.exposed.headers";
+
+    /**
+     * Key to retrieve allowed headers from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_ALLOWED_HEADERS =
+            "cors.allowed.headers";
+
+    /**
+     * Key to retrieve allowed methods from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_ALLOWED_METHODS =
+            "cors.allowed.methods";
+
+    /**
+     * Key to retrieve preflight max age from {@link FilterConfig}.
+     */
+    public static final String PARAM_CORS_PREFLIGHT_MAXAGE =
+            "cors.preflight.maxage";
+
+    /**
+     * Key to determine if request should be decorated.
+     */
+    public static final String PARAM_CORS_REQUEST_DECORATE =
+            "cors.request.decorate";
+}