Clean up web development area 89/7889/1
authorAndrew Kim <h.andrew.kim@gmail.com>
Mon, 9 Jun 2014 02:30:30 +0000 (21:30 -0500)
committerAndrew Kim <h.andrew.kim@gmail.com>
Wed, 11 Jun 2014 05:08:23 +0000 (00:08 -0500)
Added samples/ directory to store all sample applications
Added tool/ directory to store node server
Added kit/ directory for provision script

Change-Id: I334f108bd7554c315e5fd0552cd6118648bd70d6
Signed-off-by: Andrew Kim <h.andrew.kim@gmail.com>
37 files changed:
kit/provision.js [new file with mode: 0644]
node/config.js [deleted file]
node/static.js [deleted file]
samples/simple/.gitignore [moved from simple/.gitignore with 100% similarity]
samples/simple/pom.xml [moved from simple/pom.xml with 97% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/ISimple.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/ISimple.java with 100% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/SimpleData.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/SimpleData.java with 100% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/internal/Activator.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/internal/Activator.java with 100% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/internal/Simple.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/internal/Simple.java with 100% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/northbound/AppNorthbound.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/northbound/AppNorthbound.java with 100% similarity]
samples/simple/src/main/java/org/opendaylight/toolkit/simple/web/AppWeb.java [moved from simple/src/main/java/org/opendaylight/toolkit/simple/web/AppWeb.java with 100% similarity]
samples/simple/src/main/resources/META-INF/spring.factories [moved from simple/src/main/resources/META-INF/spring.factories with 100% similarity]
samples/simple/src/main/resources/META-INF/spring.handlers [moved from simple/src/main/resources/META-INF/spring.handlers with 100% similarity]
samples/simple/src/main/resources/META-INF/spring.schemas [moved from simple/src/main/resources/META-INF/spring.schemas with 100% similarity]
samples/simple/src/main/resources/META-INF/spring.tooling [moved from simple/src/main/resources/META-INF/spring.tooling with 100% similarity]
samples/simple/src/main/resources/WEB-INF/AppWeb-servlet.xml [moved from simple/src/main/resources/WEB-INF/AppWeb-servlet.xml with 100% similarity]
samples/simple/src/main/resources/WEB-INF/jsp/main.jsp [moved from simple/src/main/resources/WEB-INF/jsp/main.jsp with 100% similarity]
samples/simple/src/main/resources/WEB-INF/web.xml [moved from simple/src/main/resources/WEB-INF/web.xml with 100% similarity]
samples/simple/src/main/resources/css/simple.css [moved from simple/src/main/resources/css/simple.css with 100% similarity]
samples/simple/src/main/resources/js/app.js [moved from simple/src/main/resources/js/app.js with 100% similarity]
samples/simple/src/main/resources/js/collections/SimpleCollection.js [moved from simple/src/main/resources/js/collections/SimpleCollection.js with 100% similarity]
samples/simple/src/main/resources/js/main.js [moved from simple/src/main/resources/js/main.js with 100% similarity]
samples/simple/src/main/resources/js/models/SimpleModel.js [moved from simple/src/main/resources/js/models/SimpleModel.js with 100% similarity]
samples/simple/src/main/resources/js/templates/simple.html [moved from simple/src/main/resources/js/templates/simple.html with 100% similarity]
samples/simple/src/main/resources/js/views/View.js [moved from simple/src/main/resources/js/views/View.js with 100% similarity]
tool/node/config.js [new file with mode: 0644]
tool/node/css [moved from node/css with 100% similarity]
tool/node/img [moved from node/img with 100% similarity]
tool/node/index.html [moved from node/index.html with 100% similarity]
tool/node/js [moved from node/js with 100% similarity]
tool/node/server.js [moved from node/server.js with 100% similarity]
tool/node/simple/web/css [moved from node/simple/web/css with 100% similarity]
tool/node/simple/web/js [moved from node/simple/web/js with 100% similarity]
tool/node/static.js [new file with mode: 0644]
web/pom.xml
web/src/main/java/org/opendaylight/toolkit/web/CorsFilter.java
web/src/main/java/org/opendaylight/toolkit/web/bean/CorsBean.java [new file with mode: 0644]

diff --git a/kit/provision.js b/kit/provision.js
new file mode 100644 (file)
index 0000000..8a832ac
--- /dev/null
@@ -0,0 +1,113 @@
+require('shelljs/global');
+
+// "constants"
+var constants = {
+  opendaylight : {
+    source : pwd()+'/../main/src/main/resources',
+    target : pwd()+'/../main/target/main-osgipackage/opendaylight'
+  }
+};
+constants.opendaylight.cors = {
+  source : constants.opendaylight.source+'/cors.json',
+  target : constants.opendaylight.target+'/cors.json'
+}
+var cors = {};
+
+// help
+var help = 'Usage: node provision.js [ --scaffold <your-ip> | --teardown | --status ]' +
+  '\n\n' +
+  'Options:' +
+  '\n -s, --scaffold <your-ip>     setup cors filter with <your-ip> address' +
+  '\n -t, --teardown               tear down cors filter' +
+  '\n -a, --status                 display current state' +
+  '\n -h, --help                   display this help';
+
+// basic args check
+if (process.argv.length <= 2) {
+  console.log(help);
+  return;
+}
+
+// help args check
+if (process.argv.length === 3
+  && (process.argv[2] == '-h' 
+  || process.argv[2] == '--help')) {
+  console.log(help);
+  return;
+}
+
+// status
+function statusCheck() {
+  if (test('-f', constants.opendaylight.cors.target)) {
+    console.log('Scaffold setup in '+constants.opendaylight.cors.target);
+  } else if (test('-f', constants.opendaylight.cors.source)) {
+    console.log('Scaffold setup in '+constants.opendaylight.cors.source);
+  } else {
+    console.log('Currently not scaffolded');
+  }
+}
+
+if (process.argv.length === 3
+  && (process.argv[2] == '-a'
+  || process.argv[2] == '--status')) {
+  statusCheck();
+  return;
+}
+
+// scaffold
+function scaffold(ip) {
+  cors.address = ip;
+  // check if cors already exists
+  if (test('-f', constants.opendaylight.cors.target)
+    || test('-f', constants.opendaylight.cors.source)) {
+    console.log('Scaffolding already exists');
+    return;
+  }
+  // scaffold
+  if (test('-d', constants.opendaylight.target)) {
+    JSON.stringify(cors).to(constants.opendaylight.cors.target);
+    console.log('Scaffolding initialized in '+constants.opendaylight.cors.target);
+  } else if (test('-d', constants.opendaylight.source)) {
+    JSON.stringify(cors).to(constants.opendaylight.cors.source);
+    console.log('Scaffolding initialized in '+constants.opendaylight.cors.source);
+  } else {
+    console.log('Error: Unable to initialize scaffolding; your distribution directory doesn\'t seem to exist');
+  }
+}
+
+if (process.argv.length === 3
+  && (process.argv[2] == '-s'
+  || process.argv[2] == '--scaffold')) {
+  console.log('Error: specify your IP address');
+  return;
+}
+
+if (process.argv.length === 4
+  && (process.argv[2] == '-s'
+  || process.argv[2] == '--scaffold')) {
+  scaffold(process.argv[3]);
+  return;
+}
+
+// teardown
+function teardown() {
+  if (test('-f', constants.opendaylight.cors.target)
+    || test('-f', constants.opendaylight.cors.source)) {
+    rm('-f', constants.opendaylight.cors.target);
+    rm('-f', constants.opendaylight.cors.source);
+    console.log('Teardown scaffold');
+  } else {
+    console.log('Currently not scaffolded');
+  }
+}
+
+if (process.argv.length === 3
+  && (process.argv[2] == '-t'
+  || process.argv[2] == '--teardown')) {
+  teardown();
+  return;
+}
+
+// assume failed state (invalid args)
+console.log('Error: unrecognized flag '+process.argv[2]+
+'\nTry --help for options');
diff --git a/node/config.js b/node/config.js
deleted file mode 100644 (file)
index 5c0d5e1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Enter all relative paths to your app's files / directories here
-
-var appname = 'simpleappfoo';
-
-var Config = {
- index: "../" + appname + "/src/main/resources/WEB-INF/jsp/main.jsp",
- basepath:  "../web/src/main/resources/",  // common web bundle assets
- apppath: "../" + appname + "/src/main/resources/", // app bundle assets
- appdir_to_remove: appname + "/web",
-
-
-}
-
-module.exports = Config;
diff --git a/node/static.js b/node/static.js
deleted file mode 100644 (file)
index 80806b7..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-var url = require('url'),
-    path = require('path'),
-    fs = require('fs'),
-    mime = require('mime'),
-    config = require('./config');
-
-
-
-String.prototype.endsWith = function(suffix) {
-    return this.indexOf(suffix, this.length - suffix.length) !== -1;
-};
-
-var Static = function(request, response) {
-    var uri = url.parse(request.url).pathname;
-    var cwd =  process.cwd();
-    var found = false;
-
-    if (uri.endsWith("/")) {
-        if (uri == "/") {
-            found = true;
-            return returnFile(request, response, path.join(cwd, config.index), "text/html");
-        } else {
-            uri =  uri + "index.html";
-        }
-    }
-
-    var fn = "";
-    if (uri.indexOf("/" + config.appdir_to_remove) > -1) {
-        uri = uri.replace("/" + config.appdir_to_remove, "");
-        fn = path.join(path.join(cwd, config.apppath), uri);
-    } else {
-        fn = path.join(path.join(cwd, config.basepath), uri);
-    }
-
-    if (fs.existsSync(fn)) {
-        return returnFile(request, response, fn);
-    } else {
-
-        console.log("404 - " + uri);
-        response.writeHead(404, {"Content-Type": "text/plain"});
-        response.write("404 Not Found\n");
-        response.end();
-    }
-}
-
-function returnFile(request, response, filename, mimetype) {
-
-    var mimetyp = typeof mimetype !== 'undefined' ? mimetype : mime.lookup(filename);
-
-    fs.readFile(filename, "binary", function(err, file) {
-        if(err) {
-            console.log("500 " + filename);
-            response.writeHead(500, {"Content-Type": "text/plain"});
-            response.write(err + "\n");
-            response.end();
-            return;
-        }
-
-        console.log("200 " + filename);
-        response.writeHead(200, {
-            "Content-Type": mimetyp,
-            "Access-Control-Allow-Origin": "*",
-        });
-        response.write(file, "binary");
-        response.end();
-    });
-
-}
-module.exports = Static;
similarity index 100%
rename from simple/.gitignore
rename to samples/simple/.gitignore
similarity index 97%
rename from simple/pom.xml
rename to samples/simple/pom.xml
index e4a45df9cc8e89d3ae05cab1f5cd4d1719a943b9..681f43cb6cb3d32181628f81b3de0064654a1ba2 100644 (file)
@@ -89,7 +89,7 @@
                </Bundle-Activator>
           </instructions>
           <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
-          <buildDirectory>../main/target/main-osgipackage/opendaylight/plugins/</buildDirectory> <!-- TODO use pom var -->
+          <buildDirectory>../../main/target/main-osgipackage/opendaylight/plugins/</buildDirectory> <!-- TODO use pom var -->
         </configuration>
       </plugin>
     </plugins>
diff --git a/tool/node/config.js b/tool/node/config.js
new file mode 100644 (file)
index 0000000..99b7c30
--- /dev/null
@@ -0,0 +1,14 @@
+// Enter all relative paths to your app's files / directories here
+
+// TODO andrew - init app name from file
+
+var appname = 'simple';
+
+var Config = {
+ index: '../../samples/' + appname + '/src/main/resources/WEB-INF/jsp/main.jsp',
+ basepath:  '../../web/src/main/resources/',  // common web bundle assets
+ apppath: '../../samples/' + appname + '/src/main/resources/', // app bundle assets
+ appdir_to_remove: appname + '/web',
+}
+
+module.exports = Config;
similarity index 100%
rename from node/css
rename to tool/node/css
similarity index 100%
rename from node/img
rename to tool/node/img
similarity index 100%
rename from node/index.html
rename to tool/node/index.html
similarity index 100%
rename from node/js
rename to tool/node/js
similarity index 100%
rename from node/server.js
rename to tool/node/server.js
similarity index 100%
rename from node/simple/web/css
rename to tool/node/simple/web/css
similarity index 100%
rename from node/simple/web/js
rename to tool/node/simple/web/js
diff --git a/tool/node/static.js b/tool/node/static.js
new file mode 100644 (file)
index 0000000..c99e549
--- /dev/null
@@ -0,0 +1,68 @@
+var url = require('url'),
+path = require('path'),
+fs = require('fs'),
+mime = require('mime'),
+config = require('./config');
+
+// functions
+String.prototype.endsWith = function(suffix) {
+  return this.indexOf(suffix, this.length - suffix.length) !== -1;
+};
+
+function returnFile(request, response, filename, mimetype) {
+  var mimetyp = typeof mimetype !== 'undefined' ? mimetype : mime.lookup(filename);
+
+  fs.readFile(filename, 'binary', function(err, file) {
+    if (err) {
+      console.log('500 ' + filename);
+      response.writeHead(500, {'Content-Type': 'text/plain'});
+      response.write(err + "\n");
+      response.end();
+      return;
+    }
+
+    console.log('200 ' + filename);
+    response.writeHead(200, {
+      'Content-Type': mimetyp,
+      'Access-Control-Allow-Origin': '*',
+    });
+
+    response.write(file, 'binary');
+    response.end();
+  });
+}
+
+// Static
+var Static = function(request, response) {
+  var uri = url.parse(request.url).pathname;
+  var cwd =  process.cwd();
+  var found = false;
+
+  if (uri.endsWith('/')) {
+    if (uri == '/') {
+      found = true;
+      return returnFile(request, response, path.join(cwd, config.index), 'text/html');
+    } else {
+      uri += 'index.html';
+    }
+  }
+
+  var fn = '';
+  if (uri.indexOf('/' + config.appdir_to_remove) > -1) {
+    uri = uri.replace('/' + config.appdir_to_remove, '');
+    fn = path.join(path.join(cwd, config.apppath), uri);
+  } else {
+    fn = path.join(path.join(cwd, config.basepath), uri);
+  }
+
+  if (fs.existsSync(fn)) {
+    return returnFile(request, response, fn);
+  } else {
+    console.log('404 ' + uri);
+    response.writeHead(404, {'Content-Type': 'text/plain'});
+    response.write('404 Not Found\n');
+    response.end();
+  }
+}
+
+module.exports = Static;
index 04b46b63991cbbe5fac87196c14584640467fcba..267922ba80cf47406def3d17a5d2a9da6f5ed1c7 100644 (file)
@@ -31,6 +31,7 @@
               org.opendaylight.controller.connectionmanager,
               org.opendaylight.controller.switchmanager,
               com.google.gson,
+              com.google.gson.reflect,
               javax.annotation,
               javax.naming,
               javax.servlet,
index d3d39156ead81d8df9cff675642853f20148aae4..2ce0b0b987168e28a1e809bc55528c3384f5361b 100644 (file)
@@ -1,6 +1,11 @@
 package org.opendaylight.toolkit.web;
 
 import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -8,18 +13,23 @@ 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.opendaylight.toolkit.web.bean.CorsBean;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
 /**
- * Temporary workaround because built-in tomcat cors filter
- * isn't working at the moment
+ * CORS Filter for easier web application development
  * 
  * @author Andrew Kim
  *
  */
 public class CorsFilter implements Filter {
        public static String VALID_METHODS = "DELETE, HEAD, GET, OPTIONS, POST, PUT";
+       private static Type CORS_BEAN = new TypeToken<CorsBean>(){}.getType();
+       private static Gson gson = new Gson();
 
        @Override
        public void destroy() {
@@ -29,12 +39,28 @@ public class CorsFilter implements Filter {
        public void doFilter(ServletRequest req, ServletResponse res,
                        FilterChain chain) throws IOException, ServletException {
                HttpServletResponse response = (HttpServletResponse) res;
-               /* Uncomment next line */
-               //response.setHeader("Access-Control-Allow-Origin", "http://<<your-ip>>:8000");
-               response.setHeader("Access-Control-Allow-Credentials", "true");
-               response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
-               response.setHeader("Access-Control-Max-Age", "3600");
-               response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
+               
+               // determine allowed origin
+               StringBuffer http = new StringBuffer("http://");
+               String allowedOrigin = "localhost";
+               StringBuffer path = new StringBuffer(System.getProperty("user.dir"));
+               path.append("/cors.json");
+               try {
+                       String corsBean = readFile(path.toString());
+                       CorsBean bean = gson.fromJson(corsBean, CORS_BEAN);
+                       allowedOrigin = bean.getAddress();
+                       http.append(allowedOrigin).append(":8000");
+                       response.setHeader("Access-Control-Allow-Origin", http.toString());
+                       
+                       // everything else
+                       response.setHeader("Access-Control-Allow-Credentials", "true");
+                       response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
+                       response.setHeader("Access-Control-Max-Age", "3600");
+                       response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
+               } catch (IOException e) {
+                       // just skip cors if no cors.json found
+                       //System.err.println("Failed to find cors.json in "+path.toString()+" defaulting to localhost");
+               }
                chain.doFilter(req, res);
        }
 
@@ -42,5 +68,10 @@ public class CorsFilter implements Filter {
        public void init(FilterConfig arg0) throws ServletException {
                // TODO Auto-generated method stub
        }
+       
+       private String readFile(String path) throws IOException {
+               byte[] encoded = Files.readAllBytes(Paths.get(path));
+               return new String(encoded, Charset.defaultCharset());
+       }
 
 }
diff --git a/web/src/main/java/org/opendaylight/toolkit/web/bean/CorsBean.java b/web/src/main/java/org/opendaylight/toolkit/web/bean/CorsBean.java
new file mode 100644 (file)
index 0000000..c928107
--- /dev/null
@@ -0,0 +1,16 @@
+package org.opendaylight.toolkit.web.bean;
+
+import java.io.Serializable;
+
+public class CorsBean implements Serializable {
+       private static final long serialVersionUID = 1L;
+       private String address;
+       
+       public void setAddress(String address) {
+               this.address = address;
+       }
+       
+       public String getAddress() {
+               return address;
+       }
+}