support for client and target to handle multi-user

client and target now accept an "id" after a hash character (#)
in places where URLs are expected, like the primary client URL,
and the URL for the target script you inject.  This id will
be used at connection time to scope per-user sessions on a
server that supports multiple users.
diff --git a/weinre.server/src/weinre/server/http/HttpSocketHandler.java b/weinre.server/src/weinre/server/http/HttpSocketHandler.java
index caaa194..4e39082 100644
--- a/weinre.server/src/weinre/server/http/HttpSocketHandler.java
+++ b/weinre.server/src/weinre/server/http/HttpSocketHandler.java
@@ -13,7 +13,6 @@
 import java.io.Reader;
 import java.util.List;
 
-import javax.management.RuntimeErrorException;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
diff --git a/weinre.web/demo/weinre-demo-min.html b/weinre.web/demo/weinre-demo-min.html
index 9adcc3b..65e393b 100644
--- a/weinre.web/demo/weinre-demo-min.html
+++ b/weinre.web/demo/weinre-demo-min.html
@@ -10,13 +10,13 @@
 <meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
 <title>weinre demo</title>
 <link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
 <script src="/target/target-script-min.js"></script>
 
 <script type="text/javascript">
     require("weinre/common/Weinre").showNotImplemented()
 </script>
 
-<script src="weinre-demo.js"></script>
 </head>
 
 <body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo-pieces.html b/weinre.web/demo/weinre-demo-pieces.html
index 2b87785..c7473b5 100644
--- a/weinre.web/demo/weinre-demo-pieces.html
+++ b/weinre.web/demo/weinre-demo-pieces.html
@@ -10,6 +10,7 @@
 <meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
 <title>weinre demo</title>
 <link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
 <script src="/modjewel-require.js"></script>
 <script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>
 <script src="/scooj.transportd.js"></script>
@@ -48,8 +49,6 @@
     require("weinre/common/Weinre").showNotImplemented()
     require('weinre/target/Target').main()
 </script>
-
-<script src="weinre-demo.js"></script>
 </head>
 
 <body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo.html b/weinre.web/demo/weinre-demo.html
index ebdd2de..6a57672 100644
--- a/weinre.web/demo/weinre-demo.html
+++ b/weinre.web/demo/weinre-demo.html
@@ -10,13 +10,12 @@
 <meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
 <title>weinre demo</title>
 <link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
 <script src="/target/target-script.js"></script>
 
 <script type="text/javascript">
     require("weinre/common/Weinre").showNotImplemented()
 </script>
-
-<script src="weinre-demo.js"></script>
 </head>
 
 <body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo.js b/weinre.web/demo/weinre-demo.js
index 6be2622..e0b95e3 100644
--- a/weinre.web/demo/weinre-demo.js
+++ b/weinre.web/demo/weinre-demo.js
@@ -13,6 +13,11 @@
 var outputElement 
 var storageIndex = 0
 
+// set the id based on the hash
+var hash = location.href.split("#")[1]
+if (!hash) hash = "anonymous"
+window.WeinreServerId = hash
+
 //------------------------------------------------------------------------------
 function onLoad() {
     if (!buttonStartStuff)  buttonStartStuff  = document.getElementById("button-start-stuff")
diff --git a/weinre.web/index.html b/weinre.web/index.html
index ac7e757..1b18726 100644
--- a/weinre.web/index.html
+++ b/weinre.web/index.html
@@ -33,6 +33,9 @@
 textarea {
     width:                  100%;
 }
+pre, .indent {
+    margin-left:            2em;
+}
 </style>
 </head>
 <body>
@@ -47,15 +50,36 @@
 <tr><td>target demo:                 <td> <span id="url-target-demo-min">???</span> <br><i>(<span id="url-target-demo-pieces"></span>)</i>
 </table>
 
+<h2>Target Script</h2>
+
+<p>You can use this script to inject the weinre target code into your web page.
+
+<p class="indent"><code><span id="url-target-script">???</span></code>
+
+<p>Example:
+
+<pre>
+&ltscript src="<span id="url-target-script-raw">???</span>"&gt;&lt;/script&gt;
+</pre>
+
 <h2>Target Bookmarklet</h2>
 
-<p>link: <span id="url-target-bookmarklet">???</span> (drag to your bookmarks)
+<p>You can use this bookmarklet to inject the weinre target code into any 
+web page you are viewing.
+
+<p>link you can drag to your bookmarks: 
+
+<div class="indent">
+<span id="url-target-bookmarklet">???</span> 
+</div>
 
 <p>bookmarklet url in a pre: 
 <pre id="target-bookmarklet-src-pre"></pre>
 
 <p>bookmarklet url in a textarea: 
+<div class="indent">
 <textarea id="target-bookmarklet-src-text-area"></textarea> 
+</div>
 
 <h2>Development</h2>
 
diff --git a/weinre.web/index.js b/weinre.web/index.js
index b42f890..d8b66f5 100644
--- a/weinre.web/index.js
+++ b/weinre.web/index.js
@@ -9,12 +9,19 @@
 var weinre_host     = location.hostname
 var weinre_port     = location.port
 var weinre_pathname = location.pathname
+var weinre_id       = "anonymous"
 
-replaceURL("url-client-ui",              buildHttpURL("client/"))
+var hash = location.href.split("#")[1]
+if (hash) {
+    weinre_id = hash
+}
+
+replaceURL("url-client-ui",              buildHttpURL("client/#" + weinre_id))
 replaceURL("url-interfaces",             buildHttpURL("interfaces/interfaces.html"))
-replaceURL("url-target-demo",            buildHttpURL("demo/weinre-demo.html"))
-replaceURL("url-target-demo-min",        buildHttpURL("demo/weinre-demo-min.html"))
-replaceURL("url-target-demo-pieces",     buildHttpURL("demo/weinre-demo-pieces.html"), "pieces version")
+replaceURL("url-target-demo",            buildHttpURL("demo/weinre-demo.html#" + weinre_id))
+replaceURL("url-target-demo-min",        buildHttpURL("demo/weinre-demo-min.html#" + weinre_id))
+replaceURL("url-target-demo-pieces",     buildHttpURL("demo/weinre-demo-pieces.html#" + weinre_id), "pieces version")
+replaceURL("url-target-script",          buildHttpURL("target/target-script-min.js#" + weinre_id))
 replaceURL("url-target-bookmarklet",     getTargetBookmarklet(), "weinre target debug")
 replaceURL("url-target-documentation",   buildHttpURL("doc/"))
 //replaceURL("url-client-protocol",        buildHttpURL("ws/client/"))
@@ -34,6 +41,8 @@
 replaceText("target-bookmarklet-src-pre",       getTargetBookmarklet())
 replaceText("target-bookmarklet-src-text-area", getTargetBookmarklet())
 
+replaceText("url-target-script-raw",  buildHttpURL("target/target-script-min.js#" + weinre_id))
+
 //---------------------------------------------------------------------
 function buildHttpURL(uri) {
     var port     = weinre_port
@@ -70,7 +79,7 @@
     script = script.replace(/\n/g,   "")
     script = script.replace("targetBookmarkletFunction","")
     script = script.replace(/\s*/g, "")
-    script = script.replace("???", buildHttpURL("target/target-script-min.js"))
+    script = script.replace("???", buildHttpURL("target/target-script-min.js#" + weinre_id))
     script = "(" + script + ')(document.createElement("script"));void(0);'
     return 'javascript:' + script
 }
diff --git a/weinre.web/modules/weinre/client/Client.scoop b/weinre.web/modules/weinre/client/Client.scoop
index 91d50bc..584d0d3 100644
--- a/weinre.web/modules/weinre/client/Client.scoop
+++ b/weinre.web/modules/weinre/client/Client.scoop
@@ -38,7 +38,7 @@
     window.addEventListener("load", Binding(this, "onLoaded"), false)
 
     // create the socket
-    var messageDispatcher = new MessageDispatcher("../ws/client")
+    var messageDispatcher = new MessageDispatcher("../ws/client", this._getId())
     Weinre.messageDispatcher = messageDispatcher
 
     // finish setting up InspectorBackend
@@ -55,6 +55,12 @@
     WebInspector.mainResource.url = location.href
 
 //-----------------------------------------------------------------------------
+method _getId
+    var hash = location.href.split("#")[1]
+    if (hash) return hash
+    return "anonymous"
+
+//-----------------------------------------------------------------------------
 method uiAvailable
     return WebInspector.panels && WebInspector.panels.remote
     
diff --git a/weinre.web/modules/weinre/common/MessageDispatcher.scoop b/weinre.web/modules/weinre/common/MessageDispatcher.scoop
index 36c2e06..c207e01 100644
--- a/weinre.web/modules/weinre/common/MessageDispatcher.scoop
+++ b/weinre.web/modules/weinre/common/MessageDispatcher.scoop
@@ -14,8 +14,13 @@
 requireClass ./Callback
 
 //-----------------------------------------------------------------------------
-class MessageDispatcher(url)
+class MessageDispatcher(url, id)
+    if (!id) {
+        id = "anonymous"
+    }
+
     this._url        = url
+    this._id         = id
     
     this.error       = null
     this._opening    = false
@@ -48,7 +53,7 @@
     if (this._closed) throw new Ex(arguments, "socket has already been closed")
     
     this._opening = true 
-    this._socket = new WebSocketXhr(this._url)
+    this._socket = new WebSocketXhr(this._url, this._id)
     this._socket.addEventListener("open",    Binding(this, "_handleOpen"))
     this._socket.addEventListener("error",   Binding(this, "_handleError"))
     this._socket.addEventListener("message", Binding(this, "_handleMessage"))
diff --git a/weinre.web/modules/weinre/common/WebSocketXhr.scoop b/weinre.web/modules/weinre/common/WebSocketXhr.scoop
index 4524084..813e6a9 100644
--- a/weinre.web/modules/weinre/common/WebSocketXhr.scoop
+++ b/weinre.web/modules/weinre/common/WebSocketXhr.scoop
@@ -12,8 +12,8 @@
 requireClass ./Native
 
 //-----------------------------------------------------------------------------
-class WebSocketXhr(url)
-    this.initialize(url)
+class WebSocketXhr(url, id)
+    this.initialize(url, id)
     
 //-----------------------------------------------------------------------------
 init
@@ -25,9 +25,14 @@
     WebSocketXhr.CLOSED     = 3
 
 //-----------------------------------------------------------------------------
-method initialize(url)
+method initialize(url, id)
+    if (!id) {
+        id = "anonymous"
+    }
+    
     this.readyState      = WebSocketXhr.CONNECTING 
     this._url            = url
+    this._id             = id
     this._urlChannel     = null
     this._queuedSends    = []
     this._sendInProgress = true
@@ -43,7 +48,8 @@
 
 //-----------------------------------------------------------------------------
 method _getChannel
-    this._xhr(this._url, "POST", "", this._handleXhrResponseGetChannel)
+    var body = JSON.stringify({ id: this._id})
+    this._xhr(this._url, "POST", body, this._handleXhrResponseGetChannel)
 
 //-----------------------------------------------------------------------------
 method _handleXhrResponseGetChannel(xhr)
diff --git a/weinre.web/modules/weinre/target/Target.scoop b/weinre.web/modules/weinre/target/Target.scoop
index d7e16e5..38ff60b 100644
--- a/weinre.web/modules/weinre/target/Target.scoop
+++ b/weinre.web/modules/weinre/target/Target.scoop
@@ -47,7 +47,34 @@
 //------------------------------------------------------------------------------
 method setWeinreServerURLFromScriptSrc()
     if (window.WeinreServerURL) return
+
+    var element = this.getTargetScriptElement()
+    var pattern = /(http:\/\/(.*?)\/)/
+    var match   = pattern.exec(element.src)
+    if (match) {
+        window.WeinreServerURL = match[1]
+        return 
+    }
     
+    var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead" 
+    alert(message)
+    throw new Ex(arguments, message)
+
+
+//-----------------------------------------------------------------------------
+method setWeinreServerIdFromScriptSrc()
+    if (window.WeinreServerId) return
+
+    var element = this.getTargetScriptElement()
+
+    var hash = element.src.split("#")[1]
+    if (!hash) hash = "anonymous"
+    
+    window.WeinreServerId = hash
+
+//-----------------------------------------------------------------------------
+method getTargetScriptElement
+
     var elements = document.getElementsByTagName("script")
 
     var scripts = ["Target.", "target-script.", "target-script-min."]
@@ -56,23 +83,15 @@
         
         for (j=0; j<scripts.length; j++) {
             if (-1 != element.src.indexOf("/" + scripts[j])) {
-                var pattern = /(http:\/\/(.*?)\/)/
-                var match   = pattern.exec(element.src)
-                if (match) {
-                    window.WeinreServerURL = match[1]
-                    return 
-                }
+                return element
             }
         }
     }
-    
-    var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead" 
-    alert(message)
-    throw new Ex(arguments, message)
 
 //-----------------------------------------------------------------------------
 method initialize()
     this.setWeinreServerURLFromScriptSrc()
+    this.setWeinreServerIdFromScriptSrc()
     
     if (window.WeinreServerURL[window.WeinreServerURL.length-1] != "/") {
         window.WeinreServerURL += "/"
@@ -83,7 +102,7 @@
     
     window.addEventListener("load", Binding(this, "onLoaded"), false)
 
-    var messageDispatcher = new MessageDispatcher(window.WeinreServerURL + "ws/target")
+    var messageDispatcher = new MessageDispatcher(window.WeinreServerURL + "ws/target", window.WeinreServerId)
     Weinre.messageDispatcher = messageDispatcher
 
     Weinre.wi = {}