Rewritting the archetype to be simpler and more easily modifiable to one's needs
1.1 --- a/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/VerifyArchetypeTest.java Mon Sep 09 15:26:12 2013 +0200
1.2 +++ b/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/VerifyArchetypeTest.java Mon Sep 09 17:34:30 2013 +0200
1.3 @@ -88,7 +88,6 @@
1.4
1.5 ZipFile zf = new ZipFile(zip);
1.6 assertNotNull(zf.getEntry("public_html/index.html"), "index.html found");
1.7 - assertNotNull(zf.getEntry("public_html/twitterExample.css"), "css file found");
1.8
1.9 }
1.10
2.1 --- a/ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon Sep 09 15:26:12 2013 +0200
2.2 +++ b/ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon Sep 09 17:34:30 2013 +0200
2.3 @@ -26,8 +26,8 @@
2.4 <include>**/*.java</include>
2.5 </includes>
2.6 </fileSet>
2.7 - <fileSet filtered="true" packaged="true">
2.8 - <directory>src/main/resources</directory>
2.9 + <fileSet filtered="true" packaged="false">
2.10 + <directory>src/main/webapp/pages</directory>
2.11 <includes>
2.12 <include>**/*.xhtml</include>
2.13 <include>**/*.html</include>
3.1 --- a/ko/archetype/src/main/resources/archetype-resources/pom.xml Mon Sep 09 15:26:12 2013 +0200
3.2 +++ b/ko/archetype/src/main/resources/archetype-resources/pom.xml Mon Sep 09 17:34:30 2013 +0200
3.3 @@ -42,7 +42,7 @@
3.4 <bck2brwsr.version>${project.version}</bck2brwsr.version>
3.5 <bck2brwsr.launcher.version>${project.version}</bck2brwsr.launcher.version>
3.6 <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
3.7 - <brwsr.startpage>\${package.replace('.','/')}/index.html</brwsr.startpage>
3.8 + <brwsr.startpage>pages/index.html</brwsr.startpage>
3.9 </properties>
3.10 <build>
3.11 <plugins>
3.12 @@ -58,8 +58,9 @@
3.13 </execution>
3.14 </executions>
3.15 <configuration>
3.16 - <startpage>\${brwsr.startpage}</startpage>
3.17 - <launcher>\${brwsr}</launcher>
3.18 + <directory>\${basedir}/src/main/webapp/</directory>
3.19 + <startpage>${brwsr.startpage}</startpage>
3.20 + <launcher>${brwsr}</launcher>
3.21 </configuration>
3.22 </plugin>
3.23 <plugin>
4.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml Mon Sep 09 15:26:12 2013 +0200
4.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml Mon Sep 09 17:34:30 2013 +0200
4.3 @@ -29,6 +29,10 @@
4.4 </excludes>
4.5 <outputDirectory>/</outputDirectory>
4.6 </fileSet>
4.7 + <fileSet>
4.8 + <directory>src/main/webapp/pages</directory>
4.9 + <outputDirectory>/</outputDirectory>
4.10 + </fileSet>
4.11 </fileSets>
4.12 <files>
4.13 <file>
5.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml Mon Sep 09 15:26:12 2013 +0200
5.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml Mon Sep 09 17:34:30 2013 +0200
5.3 @@ -20,4 +20,13 @@
5.4 <outputDirectory>/</outputDirectory>
5.5 </file>
5.6 </files>
5.7 + <fileSets>
5.8 + <fileSet>
5.9 + <directory>src/main/webapp/</directory>
5.10 + <outputDirectory>/</outputDirectory>
5.11 + <includes>
5.12 + <include>pages/**</include>
5.13 + </includes>
5.14 + </fileSet>
5.15 + </fileSets>
5.16 </assembly>
5.17 \ No newline at end of file
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/DataModel.java Mon Sep 09 17:34:30 2013 +0200
6.3 @@ -0,0 +1,31 @@
6.4 +package ${package};
6.5 +
6.6 +import net.java.html.json.ComputedProperty;
6.7 +import net.java.html.json.Function;
6.8 +import net.java.html.json.Model;
6.9 +import net.java.html.json.Property;
6.10 +
6.11 +/** Model annotation generates class Data with
6.12 + * one message property, boolean property and read only words property
6.13 + */
6.14 +@Model(className = "Data", properties = {
6.15 + @Property(name = "message", type = String.class),
6.16 + @Property(name = "on", type = boolean.class)
6.17 +})
6.18 +final class DataModel {
6.19 + @ComputedProperty static java.util.List<String> words(String message) {
6.20 + String[] arr = new String[6];
6.21 + String[] words = message == null ? new String[0] : message.split(" ", 6);
6.22 + for (int i = 0; i < 6; i++) {
6.23 + arr[i] = words.length > i ? words[i] : "!";
6.24 + }
6.25 + return java.util.Arrays.asList(arr);
6.26 + }
6.27 +
6.28 + @Function static void turnOn(Data model) {
6.29 + model.setOn(true);
6.30 + }
6.31 + @Function static void turnOff(Data model) {
6.32 + model.setOn(false);
6.33 + }
6.34 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/Main.java Mon Sep 09 17:34:30 2013 +0200
7.3 @@ -0,0 +1,15 @@
7.4 +package ${package};
7.5 +
7.6 +public final class Main {
7.7 + private Main() {
7.8 + }
7.9 +
7.10 + /**
7.11 + * Called when the page is ready.
7.12 + */
7.13 + static {
7.14 + Data d = new Data();
7.15 + d.setMessage("Hello World from HTML and Java!");
7.16 + d.applyBindings();
7.17 + }
7.18 +}
8.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java Mon Sep 09 15:26:12 2013 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,178 +0,0 @@
8.4 -package ${package};
8.5 -
8.6 -import java.util.Arrays;
8.7 -import java.util.List;
8.8 -import net.java.html.json.ComputedProperty;
8.9 -import net.java.html.json.Function;
8.10 -import net.java.html.json.Model;
8.11 -import net.java.html.json.OnPropertyChange;
8.12 -import net.java.html.json.OnReceive;
8.13 -import net.java.html.json.Property;
8.14 -
8.15 -@Model(className="TwitterModel", properties={
8.16 - @Property(name="savedLists", type=Tweeters.class, array = true),
8.17 - @Property(name="activeTweetersName", type=String.class),
8.18 - @Property(name="activeTweeters", type=String.class, array = true),
8.19 - @Property(name="userNameToAdd", type=String.class),
8.20 - @Property(name="loading", type=boolean.class),
8.21 - @Property(name="currentTweets", type=Tweet.class, array = true)
8.22 -})
8.23 -public class TwitterClient {
8.24 - @Model(className = "Tweeters", properties = {
8.25 - @Property(name="name", type = String.class),
8.26 - @Property(name="userNames", type = String.class, array = true)
8.27 - })
8.28 - static class Twttrs {
8.29 - }
8.30 - @Model(className = "Tweet", properties = {
8.31 - @Property(name = "from_user", type = String.class),
8.32 - @Property(name = "from_user_id", type = int.class),
8.33 - @Property(name = "profile_image_url", type = String.class),
8.34 - @Property(name = "text", type = String.class),
8.35 - @Property(name = "created_at", type = String.class),
8.36 - })
8.37 - static final class Twt {
8.38 - @ComputedProperty static String html(String text) {
8.39 - StringBuilder sb = new StringBuilder(320);
8.40 - for (int pos = 0;;) {
8.41 - int http = text.indexOf("http", pos);
8.42 - if (http == -1) {
8.43 - sb.append(text.substring(pos));
8.44 - return sb.toString();
8.45 - }
8.46 - int spc = text.indexOf(' ', http);
8.47 - if (spc == -1) {
8.48 - spc = text.length();
8.49 - }
8.50 - sb.append(text.substring(pos, http));
8.51 - String url = text.substring(http, spc);
8.52 - sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
8.53 - pos = spc;
8.54 - }
8.55 - }
8.56 -
8.57 - @ComputedProperty static String userUrl(String from_user) {
8.58 - return "http://twitter.com/" + from_user;
8.59 - }
8.60 - }
8.61 - @Model(className = "TwitterQuery", properties = {
8.62 - @Property(array = true, name = "results", type = Twt.class)
8.63 - })
8.64 - public static final class TwttrQr {
8.65 - }
8.66 -
8.67 - @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
8.68 - static void queryTweets(TwitterModel page, TwitterQuery q) {
8.69 - page.getCurrentTweets().clear();
8.70 - page.getCurrentTweets().addAll(q.getResults());
8.71 - page.setLoading(false);
8.72 - }
8.73 -
8.74 - @OnPropertyChange("activeTweetersName")
8.75 - static void changeTweetersList(TwitterModel model) {
8.76 - Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());
8.77 - model.getActiveTweeters().clear();
8.78 - model.getActiveTweeters().addAll(people.getUserNames());
8.79 - }
8.80 -
8.81 - @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
8.82 - static void refreshTweets(TwitterModel model) {
8.83 - StringBuilder sb = new StringBuilder();
8.84 - sb.append("rpp=25&q=");
8.85 - String sep = "";
8.86 - for (String p : model.getActiveTweeters()) {
8.87 - sb.append(sep);
8.88 - sb.append("from:");
8.89 - sb.append(p);
8.90 - sep = " OR ";
8.91 - }
8.92 - model.setLoading(true);
8.93 - model.queryTweets("http://search.twitter.com", sb.toString());
8.94 - }
8.95 -
8.96 - static {
8.97 - final TwitterModel model = new TwitterModel();
8.98 - final List<Tweeters> svdLst = model.getSavedLists();
8.99 - svdLst.add(newTweeters("API Design", "JaroslavTulach"));
8.100 - svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
8.101 - svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
8.102 - svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
8.103 - svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
8.104 -
8.105 - model.setActiveTweetersName("NetBeans");
8.106 -
8.107 - model.applyBindings();
8.108 - }
8.109 -
8.110 - @ComputedProperty
8.111 - static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
8.112 - Tweeters tw = findByName(savedLists, activeTweetersName);
8.113 - if (activeTweeters == null) {
8.114 - return false;
8.115 - }
8.116 - return !tw.getUserNames().equals(activeTweeters);
8.117 - }
8.118 -
8.119 - @ComputedProperty
8.120 - static int activeTweetersCount(List<String> activeTweeters) {
8.121 - return activeTweeters.size();
8.122 - }
8.123 -
8.124 - @ComputedProperty
8.125 - static boolean userNameToAddIsValid(
8.126 - String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
8.127 - ) {
8.128 - return userNameToAdd != null &&
8.129 - userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
8.130 - !activeTweeters.contains(userNameToAdd);
8.131 - }
8.132 -
8.133 - @Function
8.134 - static void deleteList(TwitterModel model) {
8.135 - final List<Tweeters> sl = model.getSavedLists();
8.136 - sl.remove(findByName(sl, model.getActiveTweetersName()));
8.137 - if (sl.isEmpty()) {
8.138 - final Tweeters t = new Tweeters();
8.139 - t.setName("New");
8.140 - sl.add(t);
8.141 - }
8.142 - model.setActiveTweetersName(sl.get(0).getName());
8.143 - }
8.144 -
8.145 - @Function
8.146 - static void saveChanges(TwitterModel model) {
8.147 - Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
8.148 - int indx = model.getSavedLists().indexOf(t);
8.149 - if (indx != -1) {
8.150 - t.setName(model.getActiveTweetersName());
8.151 - t.getUserNames().clear();
8.152 - t.getUserNames().addAll(model.getActiveTweeters());
8.153 - }
8.154 - }
8.155 -
8.156 - @Function
8.157 - static void addUser(TwitterModel model) {
8.158 - String n = model.getUserNameToAdd();
8.159 - model.getActiveTweeters().add(n);
8.160 - }
8.161 - @Function
8.162 - static void removeUser(String data, TwitterModel model) {
8.163 - model.getActiveTweeters().remove(data);
8.164 - }
8.165 -
8.166 - private static Tweeters findByName(List<Tweeters> list, String name) {
8.167 - for (Tweeters l : list) {
8.168 - if (l.getName() != null && l.getName().equals(name)) {
8.169 - return l;
8.170 - }
8.171 - }
8.172 - return list.isEmpty() ? new Tweeters() : list.get(0);
8.173 - }
8.174 -
8.175 - private static Tweeters newTweeters(String listName, String... userNames) {
8.176 - Tweeters t = new Tweeters();
8.177 - t.setName(listName);
8.178 - t.getUserNames().addAll(Arrays.asList(userNames));
8.179 - return t;
8.180 - }
8.181 -}
9.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/resources/index.html Mon Sep 09 15:26:12 2013 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,90 +0,0 @@
9.4 -<?xml version="1.0" encoding="UTF-8"?>
9.5 -
9.6 -<!--
9.7 - Copied from knockout.js Twitter example:
9.8 - http://knockoutjs.com/examples/twitter.html
9.9 --->
9.10 -
9.11 -<!DOCTYPE html>
9.12 -<html xmlns="http://www.w3.org/1999/xhtml">
9.13 - <head>
9.14 - <title>Bck2Brwsr's Twitter</title>
9.15 - </head>
9.16 - <body>
9.17 - <link href='twitterExample.css' rel='Stylesheet' ></link>
9.18 -
9.19 - <style type='text/css'>
9.20 - .liveExample select { height: 1.7em; }
9.21 - .liveExample button { height: 2em; }
9.22 - </style>
9.23 -
9.24 -
9.25 - <h2>Bck2Brwsr's Twitter</h2>
9.26 -
9.27 - <p>
9.28 - This code is based on original
9.29 - <a href="http://knockoutjs.com/examples/twitter.html">knockout.js
9.30 - Twitter example</a> and
9.31 - uses almost unmodified HTML page. It just changes the model. The model
9.32 - is written in Java language with the help of
9.33 - <a href="http://bck2brwsr.apidesign.org/javadoc/net.java.html.json/">
9.34 - Knockout/Java binding library
9.35 - </a>. The Java source code has about 180 lines and seems more
9.36 - dense and shorter than the original JavaScript model.
9.37 - </p>
9.38 - <p>
9.39 - The project has two profiles. Either it executes in real Java virtual
9.40 - machine and renders using JavaFX's WebView (use <code>fxbrwsr</code> profile
9.41 - - the default). It can also run directly in a browser via
9.42 - <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a> virtual machine
9.43 - (use <code>bck2brwsr</code> profile).
9.44 - </p>
9.45 -
9.46 - <div class='liveExample'>
9.47 - <div class='configuration'>
9.48 - <div class='listChooser'>
9.49 - <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
9.50 - <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button>
9.51 - <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
9.52 - </div>
9.53 -
9.54 - <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
9.55 - <div class='currentUsers' >
9.56 - <ul data-bind='foreach: activeTweeters'>
9.57 - <li>
9.58 - <button data-bind='click: $root.removeUser'>Remove</button>
9.59 - <div data-bind='text: $data'> </div>
9.60 - </li>
9.61 - </ul>
9.62 - </div>
9.63 -
9.64 - <form data-bind='submit: addUser'>
9.65 - <label>Add user:</label>
9.66 - <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
9.67 - <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
9.68 - </form>
9.69 - </div>
9.70 - <div class='tweets'>
9.71 - <div class='loadingIndicator' data-bind="visible: loading">Loading...</div>
9.72 - <table data-bind='foreach: currentTweets' width='100%'>
9.73 - <tr>
9.74 - <td><img data-bind='attr: { src: profile_image_url }' /></td>
9.75 - <td>
9.76 - <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
9.77 - <span data-bind='html: html'> </span>
9.78 - <div class='tweetInfo' data-bind='text: created_at'> </div>
9.79 - </td>
9.80 - </tr>
9.81 - </table>
9.82 - </div>
9.83 - </div>
9.84 -
9.85 - <script src="bck2brwsr.js"></script>
9.86 - <script type="text/javascript">
9.87 - var vm = bck2brwsr('${artifactId}-${version}.jar');
9.88 - vm.loadClass('${package}.TwitterClient');
9.89 - </script>
9.90 -
9.91 -
9.92 - </body>
9.93 -</html>
10.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css Mon Sep 09 15:26:12 2013 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,32 +0,0 @@
10.4 -/*
10.5 - Copied from knockout.js Twitter example:
10.6 - http://knockoutjs.com/examples/twitter.html
10.7 -*/
10.8 -
10.9 -.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
10.10 -.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
10.11 -.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
10.12 -.tweets table { border-width: 0;}
10.13 -.tweets tr { vertical-align: top; }
10.14 -.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
10.15 -.tweets img { width: 4em; }
10.16 -.tweetInfo { color: Gray; font-size: 0.9em; }
10.17 -.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
10.18 -input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
10.19 -
10.20 -.listChooser select, .listChooser button { vertical-align:top; }
10.21 -.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
10.22 -.listChooser button { width: 19%; height:1.68em; float:right; }
10.23 -
10.24 -.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
10.25 -.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
10.26 -.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
10.27 -.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
10.28 -.currentUsers li div { padding: 0.6em; }
10.29 -.currentUsers li:hover { background-color: #EEC; }
10.30 -
10.31 -.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
10.32 -.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
10.33 -.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
10.34 -
10.35 -.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; }
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/webapp/pages/index.html Mon Sep 09 17:34:30 2013 +0200
11.3 @@ -0,0 +1,63 @@
11.4 +<!DOCTYPE html>
11.5 +<html>
11.6 + <head>
11.7 + <title></title>
11.8 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
11.9 +
11.10 + <style type="text/css">
11.11 + @-webkit-keyframes spin {
11.12 + 0% { -webkit-transform: rotate(0deg); }
11.13 + 100% { -webkit-transform: rotate(360deg); }
11.14 + }
11.15 +
11.16 + .rotate {
11.17 + -webkit-animation-name: spin;
11.18 + -webkit-animation-duration: 3s;
11.19 + -webkit-animation-iteration-count: infinite;
11.20 + -webkit-animation-direction: alternate;
11.21 + }
11.22 +
11.23 + #scene {
11.24 + position: relative;
11.25 + top: 60px;
11.26 + text-align: center;
11.27 + }
11.28 +
11.29 + #words span {
11.30 + border: 1px solid #ccc;
11.31 + background: rgba(255,255,155,0.8);
11.32 + text-align: center;
11.33 + font-size: 30px;
11.34 + -webkit-box-shadow: inset 0 0 40px rgba(0,0,0,0.4);
11.35 + position: absolute;
11.36 + }
11.37 +
11.38 + #words span:nth-child(1) { left: 45%; top: 0px; }
11.39 + #words span:nth-child(2) { left: 25%; top: 100px; }
11.40 + #words span:nth-child(3) { left: 65%; top: 100px; }
11.41 + #words span:nth-child(4) { left: 10%; top: 200px; }
11.42 + #words span:nth-child(5) { left: 45%; top: 200px; }
11.43 + #words span:nth-child(6) { left: 80%; top: 200px; }
11.44 +
11.45 + </style>
11.46 +
11.47 + </head>
11.48 + <body>
11.49 + <h1>Words Demo</h1>
11.50 + <input data-bind="value: message, valueUpdate: 'afterkeydown'" size="80">
11.51 + <br>
11.52 + <button data-bind="enable: !on(), click: $root.turnOn">Start</button>
11.53 + <button data-bind="enable: on, click: $root.turnOff">Stop</button>
11.54 +
11.55 + <div id="scene">
11.56 + <span id="words" data-bind="foreach: words">
11.57 + <span data-bind="text: $data, css: { 'rotate' : $root.on } "></span>
11.58 + </span>
11.59 + </div>
11.60 + <script type="text/javascript" src="bck2brwsr.js"></script>
11.61 + <script>
11.62 + var vm = bck2brwsr('${project.build.finalName}.jar');
11.63 + vm.loadClass('${package}.Main');
11.64 + </script>
11.65 + </body>
11.66 +</html>
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/DataModelTest.java Mon Sep 09 17:34:30 2013 +0200
12.3 @@ -0,0 +1,16 @@
12.4 +package ${package};
12.5 +
12.6 +import static org.testng.Assert.*;
12.7 +import org.testng.annotations.Test;
12.8 +
12.9 +public class DataModelTest {
12.10 + @Test public void areHelloWorldTwoWords() {
12.11 + Data model = new Data();
12.12 + model.setMessage("Hello World!");
12.13 +
12.14 + java.util.List<String> arr = model.getWords();
12.15 + assertEquals(arr.size(), 6, "Six words always");
12.16 + assertEquals("Hello", arr.get(0), "Hello is the first word");
12.17 + assertEquals("World!", arr.get(1), "World is the second word");
12.18 + }
12.19 +}
13.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java Mon Sep 09 15:26:12 2013 +0200
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,50 +0,0 @@
13.4 -package ${package};
13.5 -
13.6 -import java.util.List;
13.7 -import net.java.html.BrwsrCtx;
13.8 -import net.java.html.json.Models;
13.9 -import static org.testng.Assert.*;
13.10 -import org.testng.annotations.BeforeMethod;
13.11 -import org.testng.annotations.Test;
13.12 -
13.13 -/** We can unit test the TwitterModel smoothly.
13.14 - */
13.15 -public class TwitterClientTest {
13.16 - private TwitterModel model;
13.17 -
13.18 -
13.19 - @BeforeMethod
13.20 - public void initModel() {
13.21 - model = Models.bind(new TwitterModel(), BrwsrCtx.EMPTY);
13.22 - }
13.23 -
13.24 - @Test public void testIsValidToAdd() {
13.25 - model.setUserNameToAdd("Joe");
13.26 - Tweeters t = Models.bind(new Tweeters(), BrwsrCtx.EMPTY);
13.27 - t.setName("test");
13.28 - model.getSavedLists().add(t);
13.29 - model.setActiveTweetersName("test");
13.30 -
13.31 - assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
13.32 - TwitterClient.addUser(model);
13.33 - assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
13.34 - assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
13.35 -
13.36 - List<String> mod = model.getActiveTweeters();
13.37 - assertTrue(model.isHasUnsavedChanges(), "We have modifications");
13.38 - assertEquals(mod.size(), 1, "One element in the list");
13.39 - assertEquals(mod.get(0), "Joe", "Its name is Joe");
13.40 -
13.41 - assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
13.42 -
13.43 - TwitterClient.saveChanges(model);
13.44 - assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
13.45 -
13.46 - assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
13.47 - }
13.48 -
13.49 - @Test public void httpAtTheEnd() {
13.50 - String res = TwitterClient.Twt.html("Ahoj http://kuk");
13.51 - assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
13.52 - }
13.53 -}
14.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java Mon Sep 09 15:26:12 2013 +0200
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,73 +0,0 @@
14.4 -package ${package};
14.5 -
14.6 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
14.7 -import org.apidesign.bck2brwsr.vmtest.Http;
14.8 -import org.apidesign.bck2brwsr.vmtest.VMTest;
14.9 -import org.testng.annotations.Factory;
14.10 -
14.11 -public class TwitterProtocolTest {
14.12 - private TwitterModel page;
14.13 - @Http(@Http.Resource(
14.14 - path = "/search.json",
14.15 - mimeType = "application/json",
14.16 - parameters = {"callback"},
14.17 - content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\""
14.18 - + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":"
14.19 - + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\","
14.20 - + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\","
14.21 - + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
14.22 - + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344,"
14.23 - + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
14.24 - + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.25 - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.26 - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.27 - + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + "
14.28 - + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747,"
14.29 - + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872,"
14.30 - + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\","
14.31 - + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
14.32 - + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913,"
14.33 - + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
14.34 - + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.35 - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.36 - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.37 - + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"},"
14.38 - + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\","
14.39 - + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\","
14.40 - + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\","
14.41 - + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":"
14.42 - + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.43 - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.44 - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.45 - + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"},"
14.46 - + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,"
14.47 - + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,"
14.48 - + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":"
14.49 - + "{\"result_type\":\"recent\"},\"profile_image_url\":"
14.50 - + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.51 - + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.52 - + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.53 - + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100,"
14.54 - + "\"since_id\":0,\"since_id_str\":\"0\"})"
14.55 - ))
14.56 - @BrwsrTest public void readFromTwttr() throws InterruptedException {
14.57 - if (page == null) {
14.58 - page = new TwitterModel();
14.59 - page.applyBindings();
14.60 - page.queryTweets("", "q=xyz");
14.61 - }
14.62 -
14.63 - if (page.getCurrentTweets().isEmpty()) {
14.64 - throw new InterruptedException();
14.65 - }
14.66 -
14.67 - assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets();
14.68 -
14.69 - String firstDate = page.getCurrentTweets().get(0).getCreated_at();
14.70 - assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate;
14.71 - }
14.72 -
14.73 - @Factory public static Object[] create() {
14.74 - return VMTest.create(TwitterProtocolTest.class);
14.75 - }
14.76 -}
15.1 --- a/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Sep 09 15:26:12 2013 +0200
15.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Sep 09 17:34:30 2013 +0200
15.3 @@ -148,7 +148,7 @@
15.4 if (classes != null) {
15.5 l.addClassLoader(classes);
15.6 }
15.7 - l.showDirectory(directory, startpage);
15.8 + l.showDirectory(directory, startpage, classes != null);
15.9 return (Closeable) l;
15.10 }
15.11
15.12 @@ -172,7 +172,7 @@
15.13 return Launcher.class.getClassLoader().loadClass(cn);
15.14 }
15.15
15.16 - void showDirectory(File directory, String startpage) throws IOException {
15.17 + void showDirectory(File directory, String startpage, boolean addClasses) throws IOException {
15.18 throw new UnsupportedOperationException();
15.19 }
15.20
16.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon Sep 09 15:26:12 2013 +0200
16.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon Sep 09 17:34:30 2013 +0200
16.3 @@ -125,7 +125,7 @@
16.4 }
16.5 }
16.6
16.7 - void showDirectory(File dir, String startpage) throws IOException {
16.8 + void showDirectory(File dir, String startpage, boolean addClasses) throws IOException {
16.9 if (!startpage.startsWith("/")) {
16.10 startpage = "/" + startpage;
16.11 }
16.12 @@ -134,7 +134,7 @@
16.13 if (last >= 0) {
16.14 prefix = startpage.substring(0, last);
16.15 }
16.16 - HttpServer s = initServer(dir.getPath(), false, prefix);
16.17 + HttpServer s = initServer(dir.getPath(), addClasses, prefix);
16.18 try {
16.19 launchServerAndBrwsr(s, startpage);
16.20 } catch (Exception ex) {
17.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Mon Sep 09 15:26:12 2013 +0200
17.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Mon Sep 09 17:34:30 2013 +0200
17.3 @@ -17,11 +17,14 @@
17.4 */
17.5 package org.apidesign.bck2brwsr.launcher;
17.6
17.7 +import java.io.File;
17.8 import org.apidesign.bck2brwsr.launcher.fximpl.FXBrwsr;
17.9 import java.io.IOException;
17.10 import java.io.InputStream;
17.11 import java.lang.reflect.Method;
17.12 +import java.net.JarURLConnection;
17.13 import java.net.URI;
17.14 +import java.net.URISyntaxException;
17.15 import java.net.URL;
17.16 import java.net.URLClassLoader;
17.17 import java.util.ArrayList;
17.18 @@ -34,6 +37,7 @@
17.19 import java.util.logging.Logger;
17.20 import javafx.application.Platform;
17.21 import org.apidesign.bck2brwsr.launcher.fximpl.JVMBridge;
17.22 +import org.openide.util.Exceptions;
17.23
17.24 /**
17.25 *
17.26 @@ -116,15 +120,29 @@
17.27 String startPage = null;
17.28
17.29 final ClassLoader cl = FXBrwsrLauncher.class.getClassLoader();
17.30 - startPage = findStartPage(cl, startPage);
17.31 + URL[] manifestURL = { null };
17.32 + startPage = findStartPage(cl, startPage, manifestURL);
17.33 if (startPage == null) {
17.34 throw new NullPointerException("Can't find StartPage tag in manifests!");
17.35 }
17.36
17.37 - Launcher.showURL("fxbrwsr", cl, startPage);
17.38 + File dir = new File(".");
17.39 + if (manifestURL[0].getProtocol().equals("jar")) {
17.40 + try {
17.41 + dir = new File(
17.42 + ((JarURLConnection)manifestURL[0].openConnection()).getJarFileURL().toURI()
17.43 + ).getParentFile();
17.44 + } catch (URISyntaxException ex) {
17.45 + LOG.log(Level.WARNING, "Can't find root directory", ex);
17.46 + }
17.47 + }
17.48 +
17.49 + Launcher.showDir("fxbrwsr", dir, cl, startPage);
17.50 }
17.51
17.52 - private static String findStartPage(final ClassLoader cl, String startPage) throws IOException {
17.53 + private static String findStartPage(
17.54 + final ClassLoader cl, String startPage, URL[] startURL
17.55 + ) throws IOException {
17.56 Enumeration<URL> en = cl.getResources("META-INF/MANIFEST.MF");
17.57 while (en.hasMoreElements()) {
17.58 URL url = en.nextElement();
17.59 @@ -139,6 +157,9 @@
17.60 String sp = mf.getMainAttributes().getValue("StartPage");
17.61 if (sp != null) {
17.62 startPage = sp;
17.63 + if (startURL != null) {
17.64 + startURL[0] = url;
17.65 + }
17.66 break;
17.67 }
17.68 }