diff --git a/sw/in_progress/pow/InstallCert.java b/sw/in_progress/pow/InstallCert.java new file mode 100644 index 0000000000..f979cc7868 --- /dev/null +++ b/sw/in_progress/pow/InstallCert.java @@ -0,0 +1,188 @@ + +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @see http://blogs.sun.com/gc/entry/unable_to_find_valid_certification + */ +import java.io.*; + +import java.security.*; +import java.security.cert.*; + +import javax.net.ssl.*; + +public class InstallCert { + + public static void main(String[] args) throws Exception { + String host; + int port; + char[] passphrase; + if ((args.length == 1) || (args.length == 2)) { + String[] c = args[0].split(":"); + host = c[0]; + port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); + String p = (args.length == 1) ? "changeit" : args[1]; + passphrase = p.toCharArray(); + } else { + System.out.println("Usage: java InstallCert [:port] [passphrase]"); + return; + } + + File file = new File("jssecacerts"); + if (file.isFile() == false) { + char SEP = File.separatorChar; + File dir = new File(System.getProperty("java.home") + SEP + + "lib" + SEP + "security"); + file = new File(dir, "jssecacerts"); + if (file.isFile() == false) { + file = new File(dir, "cacerts"); + } + } + System.out.println("Loading KeyStore " + file + "..."); + InputStream in = new FileInputStream(file); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(in, passphrase); + in.close(); + + SSLContext context = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; + SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); + context.init(null, new TrustManager[] {tm}, null); + SSLSocketFactory factory = context.getSocketFactory(); + + System.out.println("Opening connection to " + host + ":" + port + "..."); + SSLSocket socket = (SSLSocket)factory.createSocket(host, port); + socket.setSoTimeout(10000); + try { + System.out.println("Starting SSL handshake..."); + socket.startHandshake(); + socket.close(); + System.out.println(); + System.out.println("No errors, certificate is already trusted"); + } catch (SSLException e) { + System.out.println(); + e.printStackTrace(System.out); + } + + X509Certificate[] chain = tm.chain; + if (chain == null) { + System.out.println("Could not obtain server certificate chain"); + return; + } + + BufferedReader reader = + new BufferedReader(new InputStreamReader(System.in)); + + System.out.println(); + System.out.println("Server sent " + chain.length + " certificate(s):"); + System.out.println(); + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + for (int i = 0; i < chain.length; i++) { + X509Certificate cert = chain[i]; + System.out.println + (" " + (i + 1) + " Subject " + cert.getSubjectDN()); + System.out.println(" Issuer " + cert.getIssuerDN()); + sha1.update(cert.getEncoded()); + System.out.println(" sha1 " + toHexString(sha1.digest())); + md5.update(cert.getEncoded()); + System.out.println(" md5 " + toHexString(md5.digest())); + System.out.println(); + } + + System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); + String line = reader.readLine().trim(); + int k; + try { + k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; + } catch (NumberFormatException e) { + System.out.println("KeyStore not changed"); + return; + } + + X509Certificate cert = chain[k]; + String alias = host + "-" + (k + 1); + ks.setCertificateEntry(alias, cert); + + OutputStream out = new FileOutputStream("jssecacerts"); + ks.store(out, passphrase); + out.close(); + + System.out.println(); + System.out.println(cert); + System.out.println(); + System.out.println + ("Added certificate to keystore 'jssecacerts' using alias '" + + alias + "'"); + } + + private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); + + private static String toHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 3); + for (int b : bytes) { + b &= 0xff; + sb.append(HEXDIGITS[b >> 4]); + sb.append(HEXDIGITS[b & 15]); + sb.append(' '); + } + return sb.toString(); + } + + private static class SavingTrustManager implements X509TrustManager { + + private final X509TrustManager tm; + private X509Certificate[] chain; + + SavingTrustManager(X509TrustManager tm) { + this.tm = tm; + } + + public X509Certificate[] getAcceptedIssuers() { + throw new UnsupportedOperationException(); + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + this.chain = chain; + tm.checkServerTrusted(chain, authType); + } + } + +} diff --git a/sw/in_progress/pow/ServletPow/InstallCert.java b/sw/in_progress/pow/ServletPow/InstallCert.java new file mode 100644 index 0000000000..f979cc7868 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/InstallCert.java @@ -0,0 +1,188 @@ + +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @see http://blogs.sun.com/gc/entry/unable_to_find_valid_certification + */ +import java.io.*; + +import java.security.*; +import java.security.cert.*; + +import javax.net.ssl.*; + +public class InstallCert { + + public static void main(String[] args) throws Exception { + String host; + int port; + char[] passphrase; + if ((args.length == 1) || (args.length == 2)) { + String[] c = args[0].split(":"); + host = c[0]; + port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); + String p = (args.length == 1) ? "changeit" : args[1]; + passphrase = p.toCharArray(); + } else { + System.out.println("Usage: java InstallCert [:port] [passphrase]"); + return; + } + + File file = new File("jssecacerts"); + if (file.isFile() == false) { + char SEP = File.separatorChar; + File dir = new File(System.getProperty("java.home") + SEP + + "lib" + SEP + "security"); + file = new File(dir, "jssecacerts"); + if (file.isFile() == false) { + file = new File(dir, "cacerts"); + } + } + System.out.println("Loading KeyStore " + file + "..."); + InputStream in = new FileInputStream(file); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(in, passphrase); + in.close(); + + SSLContext context = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; + SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); + context.init(null, new TrustManager[] {tm}, null); + SSLSocketFactory factory = context.getSocketFactory(); + + System.out.println("Opening connection to " + host + ":" + port + "..."); + SSLSocket socket = (SSLSocket)factory.createSocket(host, port); + socket.setSoTimeout(10000); + try { + System.out.println("Starting SSL handshake..."); + socket.startHandshake(); + socket.close(); + System.out.println(); + System.out.println("No errors, certificate is already trusted"); + } catch (SSLException e) { + System.out.println(); + e.printStackTrace(System.out); + } + + X509Certificate[] chain = tm.chain; + if (chain == null) { + System.out.println("Could not obtain server certificate chain"); + return; + } + + BufferedReader reader = + new BufferedReader(new InputStreamReader(System.in)); + + System.out.println(); + System.out.println("Server sent " + chain.length + " certificate(s):"); + System.out.println(); + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + for (int i = 0; i < chain.length; i++) { + X509Certificate cert = chain[i]; + System.out.println + (" " + (i + 1) + " Subject " + cert.getSubjectDN()); + System.out.println(" Issuer " + cert.getIssuerDN()); + sha1.update(cert.getEncoded()); + System.out.println(" sha1 " + toHexString(sha1.digest())); + md5.update(cert.getEncoded()); + System.out.println(" md5 " + toHexString(md5.digest())); + System.out.println(); + } + + System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); + String line = reader.readLine().trim(); + int k; + try { + k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; + } catch (NumberFormatException e) { + System.out.println("KeyStore not changed"); + return; + } + + X509Certificate cert = chain[k]; + String alias = host + "-" + (k + 1); + ks.setCertificateEntry(alias, cert); + + OutputStream out = new FileOutputStream("jssecacerts"); + ks.store(out, passphrase); + out.close(); + + System.out.println(); + System.out.println(cert); + System.out.println(); + System.out.println + ("Added certificate to keystore 'jssecacerts' using alias '" + + alias + "'"); + } + + private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); + + private static String toHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 3); + for (int b : bytes) { + b &= 0xff; + sb.append(HEXDIGITS[b >> 4]); + sb.append(HEXDIGITS[b & 15]); + sb.append(' '); + } + return sb.toString(); + } + + private static class SavingTrustManager implements X509TrustManager { + + private final X509TrustManager tm; + private X509Certificate[] chain; + + SavingTrustManager(X509TrustManager tm) { + this.tm = tm; + } + + public X509Certificate[] getAcceptedIssuers() { + throw new UnsupportedOperationException(); + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + this.chain = chain; + tm.checkServerTrusted(chain, authType); + } + } + +} diff --git a/sw/in_progress/pow/ServletPow/JARLIB/commons-codec-1.4.jar b/sw/in_progress/pow/ServletPow/JARLIB/commons-codec-1.4.jar new file mode 100755 index 0000000000..458d432da8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/commons-codec-1.4.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/commons-fileupload-1.2.1.jar b/sw/in_progress/pow/ServletPow/JARLIB/commons-fileupload-1.2.1.jar new file mode 100755 index 0000000000..aa209b3887 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/commons-fileupload-1.2.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/commons-httpclient-3.1.jar b/sw/in_progress/pow/ServletPow/JARLIB/commons-httpclient-3.1.jar new file mode 100755 index 0000000000..7c59774aed Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/commons-httpclient-3.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/commons-io-1.4.jar b/sw/in_progress/pow/ServletPow/JARLIB/commons-io-1.4.jar new file mode 100755 index 0000000000..133dc6cb35 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/commons-io-1.4.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/commons-logging-1.1.1.jar b/sw/in_progress/pow/ServletPow/JARLIB/commons-logging-1.1.1.jar new file mode 100755 index 0000000000..8758a96b70 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/commons-logging-1.1.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/ivy-1.2.13.jar b/sw/in_progress/pow/ServletPow/JARLIB/ivy-1.2.13.jar new file mode 100755 index 0000000000..be51c0e1f0 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/ivy-1.2.13.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/jakarta-regexp-1.5.jar b/sw/in_progress/pow/ServletPow/JARLIB/jakarta-regexp-1.5.jar new file mode 100755 index 0000000000..652bc822c9 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/jakarta-regexp-1.5.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/jdom.jar b/sw/in_progress/pow/ServletPow/JARLIB/jdom.jar new file mode 100755 index 0000000000..65a1b3f737 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/jdom.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/log4j-1.2.16.jar b/sw/in_progress/pow/ServletPow/JARLIB/log4j-1.2.16.jar new file mode 100755 index 0000000000..3f9d847618 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/log4j-1.2.16.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/mysql-connector-java-5.1.12-bin.jar b/sw/in_progress/pow/ServletPow/JARLIB/mysql-connector-java-5.1.12-bin.jar new file mode 100755 index 0000000000..af5847eed4 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/mysql-connector-java-5.1.12-bin.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/pushlet.jar b/sw/in_progress/pow/ServletPow/JARLIB/pushlet.jar new file mode 100755 index 0000000000..6dc1c22e21 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/pushlet.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/pushletclient.jar b/sw/in_progress/pow/ServletPow/JARLIB/pushletclient.jar new file mode 100755 index 0000000000..c699b8b25f Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/pushletclient.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/rome-1.0.jar b/sw/in_progress/pow/ServletPow/JARLIB/rome-1.0.jar new file mode 100755 index 0000000000..7138baaca1 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/rome-1.0.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/serializer.jar b/sw/in_progress/pow/ServletPow/JARLIB/serializer.jar new file mode 100755 index 0000000000..de9b007b4c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/serializer.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/servlet-api.jar b/sw/in_progress/pow/ServletPow/JARLIB/servlet-api.jar new file mode 100755 index 0000000000..a71c371333 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/servlet-api.jar differ diff --git a/sw/in_progress/pow/ServletPow/JARLIB/xerces.jar b/sw/in_progress/pow/ServletPow/JARLIB/xerces.jar new file mode 100755 index 0000000000..e9fe08ad45 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/JARLIB/xerces.jar differ diff --git a/sw/in_progress/pow/ServletPow/ServletPow.war b/sw/in_progress/pow/ServletPow/ServletPow.war new file mode 100755 index 0000000000..0888047d40 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/ServletPow.war differ diff --git a/sw/in_progress/pow/ServletPow/conf apache2/mods_available/jk.load b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/jk.load new file mode 100755 index 0000000000..841cf3d0c2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/jk.load @@ -0,0 +1,6 @@ +LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so + +JkWorkersFile /etc/apache2/workers.properties +JkLogFile /var/log/apache2/mod_jk.log +JkLogLevel debug +JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " diff --git a/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.conf b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.conf new file mode 100755 index 0000000000..9152fe14f6 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.conf @@ -0,0 +1,20 @@ + +AddType application/x-httpd-php .php .phtml .php3 +AddType application/x-httpd-php-source .phps + + + + SetHandler application/x-httpd-php + + + SetHandler application/x-httpd-php-source + + # To re-enable php in user directories comment the following lines + # (from to .) Do NOT set it to On as it + # prevents .htaccess files from disabling it. + + + php_admin_value engine Off + + + diff --git a/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.load b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.load new file mode 100755 index 0000000000..0d6a55eb43 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/php5.load @@ -0,0 +1 @@ +LoadModule php5_module /usr/lib/apache2/modules/libphp5.so \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.conf b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.conf new file mode 100755 index 0000000000..1e4ce40c44 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.conf @@ -0,0 +1,64 @@ + +# +# Pseudo Random Number Generator (PRNG): +# Configure one or more sources to seed the PRNG of the SSL library. +# The seed data should be of good random quality. +# WARNING! On some platforms /dev/random blocks if not enough entropy +# is available. This means you then cannot use the /dev/random device +# because it would lead to very long connection times (as long as +# it requires to make more entropy available). But usually those +# platforms additionally provide a /dev/urandom device which doesn't +# block. So, if available, use this one instead. Read the mod_ssl User +# Manual for more details. +# +SSLRandomSeed startup builtin +SSLRandomSeed startup file:/dev/urandom 512 +SSLRandomSeed connect builtin +SSLRandomSeed connect file:/dev/urandom 512 + +## +## SSL Global Context +## +## All SSL configuration in this context applies both to +## the main server and all SSL-enabled virtual hosts. +## + +# +# Some MIME-types for downloading Certificates and CRLs +# +AddType application/x-x509-ca-cert .crt +AddType application/x-pkcs7-crl .crl + +# Pass Phrase Dialog: +# Configure the pass phrase gathering process. +# The filtering dialog program (`builtin' is a internal +# terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog builtin + +# Inter-Process Session Cache: +# Configure the SSL Session Cache: First the mechanism +# to use and second the expiring timeout (in seconds). +#SSLSessionCache dbm:/var/run/apache2/ssl_scache +SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000) +SSLSessionCacheTimeout 300 + +# Semaphore: +# Configure the path to the mutual exclusion semaphore the +# SSL engine uses internally for inter-process synchronization. +SSLMutex file:/var/run/apache2/ssl_mutex + +# SSL Cipher Suite: +# List the ciphers that the client is permitted to negotiate. +# See the mod_ssl documentation for a complete list. +# enable only secure ciphers: +SSLCipherSuite HIGH:MEDIUM:!ADH +# Use this instead if you want to allow cipher upgrades via SGC facility. +# In this case you also have to use something like +# SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 +# see http://httpd.apache.org/docs/2.2/ssl/ssl_howto.html.en#upgradeenc +#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + +# enable only secure protocols: SSLv3 and TLSv1, but not SSLv2 +SSLProtocol all -SSLv2 + + diff --git a/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.load b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.load new file mode 100755 index 0000000000..ff861daab5 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/mods_available/ssl.load @@ -0,0 +1 @@ +LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so diff --git a/sw/in_progress/pow/ServletPow/conf apache2/ports.conf b/sw/in_progress/pow/ServletPow/conf apache2/ports.conf new file mode 100755 index 0000000000..7830895dc0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/ports.conf @@ -0,0 +1,23 @@ +# If you just change the port or add more ports here, you will likely also +# have to change the VirtualHost statement in +# /etc/apache2/sites-enabled/000-default +# This is also true if you have upgraded from before 2.2.9-3 (i.e. from +# Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and +# README.Debian.gz + +#NameVirtualHost *:80 +Listen 80 + + + # If you add NameVirtualHost *:443 here, you will also have to change + # the VirtualHost statement in /etc/apache2/sites-available/default-ssl + # to + # Server Name Indication for SSL named virtual hosts is currently not + # supported by MSIE on Windows XP. + Listen 443 + + + + Listen 443 + + diff --git a/sw/in_progress/pow/ServletPow/conf apache2/sites-available/default b/sw/in_progress/pow/ServletPow/conf apache2/sites-available/default new file mode 100755 index 0000000000..0559ce148e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/sites-available/default @@ -0,0 +1,42 @@ +NameVirtualHost *:80 + + ServerAdmin webmaster@localhost + + DocumentRoot /var/www + + Options FollowSymLinks + AllowOverride None + + + Options Indexes FollowSymLinks MultiViews + AllowOverride None + Order allow,deny + allow from all + + + ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ + + AllowOverride None + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + + ErrorLog /var/log/apache2/error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog /var/log/apache2/access.log combined + + Alias /doc/ "/usr/share/doc/" + + Options Indexes MultiViews FollowSymLinks + AllowOverride None + Order deny,allow + Deny from all + Allow from 127.0.0.0/255.0.0.0 ::1/128 + + + diff --git a/sw/in_progress/pow/ServletPow/conf apache2/sites-available/powV2_ssl b/sw/in_progress/pow/ServletPow/conf apache2/sites-available/powV2_ssl new file mode 100755 index 0000000000..7a4efcaca3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/sites-available/powV2_ssl @@ -0,0 +1,42 @@ + +NameVirtualHost *:443 + + + ServerAdmin admin@pow.fr + ServerName blanc + + LogLevel warn + + CustomLog /var/log/apache2/access.log combined + ServerSignature On + + SSLEngine on + SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP + #SSLCertificateFile /etc/ssl/private/serveur.cert + #SSLCertificateKeyFile /etc/ssl/private/serveur.key + #SSLCACertificateFile /etc/ssl/private/ca-root.cert + SSLCertificateFile /etc/ssl/server.crt + SSLCertificateKeyFile /etc/ssl/server.key + SSLCACertificatePath /etc/ssl + +#SSLVerifyClient optional_no_ca +#SSLOptions +ExportCertData +StdEnvVars + SetEnvIf User-Agent ".*MSIE.*" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + + JkExtractSSL On + JkOptions +FlushPackets + JkOptions +FlushHeader + JkMount /ServletPow worker1 + JkMount /ServletPow/* worker1 + JkMount /examples/* worker1 + JkMount /examples worker1 + +#Redirect https://www.recherche.enac.fr/TestServletPow https://www.recherche.enac.fr/evaluation/TestServletPow + + + + + + diff --git a/sw/in_progress/pow/ServletPow/conf apache2/workers.properties b/sw/in_progress/pow/ServletPow/conf apache2/workers.properties new file mode 100755 index 0000000000..996a10559b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/conf apache2/workers.properties @@ -0,0 +1,9 @@ +workers.tomcat_home=/users/genin/apache-tomcat-6.0.26 + +workers.java_home=/usr/lib/jvm/java-6-sun +ps=/ +worker.list=worker1 +worker.worker1.port=8009 +worker.worker1.host=localhost +worker.worker1.type=ajp13 +worker.worker1.lbfactor=1 diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.classpath b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.classpath new file mode 100755 index 0000000000..fd0f78ce42 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.classpath @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.project b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.project new file mode 100755 index 0000000000..3470d17f2e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.project @@ -0,0 +1,36 @@ + + + ServletPow + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/.jsdtscope b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/.jsdtscope new file mode 100755 index 0000000000..bbb8e68be8 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/.jsdtscope @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.jdt.core.prefs b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 0000000000..420b6fb9b2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +#Tue Apr 20 15:09:25 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.component b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.component new file mode 100755 index 0000000000..72dafadb28 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.project.facet.core.xml b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100755 index 0000000000..53d628c892 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.container b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100755 index 0000000000..3bd5d0a480 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.name b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100755 index 0000000000..05bd71b6ec --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design.css new file mode 100755 index 0000000000..7903f3723e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design.css @@ -0,0 +1,220 @@ +body +{ + background-color: #CCFFCC; + margin: 0%; + padding: 0%; + outline: 0%; + height: 100%; + overflow:hidden; + max-width:2048px; + font-size : 11; +} + +select{ + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + vertical-align: middle; + background-color: #F5F5DC; +} +input { + background-color:#F5F5DC; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 10px; +} + +label { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#welcome +{ + position:absolute; + top:0; + left:0; + height:3%; + width: 100%; + background-color: #EEEEEE; + text-align: center; + font-weight:bold; + font-size : 12; +} +#usr +{ + position:absolute; + top:0; + right:6%; + height:3%; + width:25%; + background-color: #EEEEEE; + text-align: right; + white-space:nowrap; +} +#page +{ +position:absolute; +top:3%; +left:0; +height:97%; +width: 100%; +} + + +#choicePanel{ + position:absolute; + top:0%; + left:0%; + height: 13%; + width : 15%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#aircraftSelector +{ + text-align: center; + background-color: #EEEEEE; +} + +#trackdiv +{ + text-align: center; + background-color: #EEEEEE; + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + -webkit-border-top-left-radius: 7px; /* pour Chrome */ + -webkit-border-top-right-radius: 7px; /* pour Chrome */ + -webkit-border-bottom-left-radius: 7px; /* pour Chrome */ + -webkit-border-bottom-right-radius: 7px; /* pour Chrome */ + width: 140px; + color: white; + vertical-align:middle; +} + +#active_block +{ + font-size:11; + text-align: center; +} + +#FlightPlan +{ + overflow:auto; + position:absolute; + top:0%; + left:15%; + height: 40%; + width : 14.9%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#FlightParams +{ + position:absolute; + top:13%; + left :0% + text-align: center; + height: 27%; + width : 14.9%; + border: 1px solid black; + background-color: #EEEEEE; +} + +#map_canvas +{ + position:absolute; + top:0; + left:30%; + width:70%; + height: 95%; + border:1px solid black; +} + + +#Settings +{ + overflow:auto; + position:absolute; + left:0%; + top:40%; + text-align: left; + height: 55%; + width: 29.9%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#page_setting { + +} + +#setting { + width: 400px; + height: 250px; + padding: 0.5em; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 8; +} +#param +{ + overflow:auto; +} + +#NewsDiv +{ + position:absolute; + overflow:auto; + left:0%; + top:95%; + height: 5%; + width: 100%; + text-align: left; + vertical-align:top; + background-color: #EEEEEE; + border: 1px solid black; +} + +#info +{ + text-align: left; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#Debug +{ + overflow:auto; + position:absolute; + left:65%; + top:50%; + text-align: center; + height: 50%; + width: 35%; + background-color: #EEEEEE; + border: 1px solid black; + padding-top:20px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#title{ + font-weight:bold; + font-size:18; + text-align:center; +} + +table.param { +border:3px solid #6495ed; +border-collapse:collapse; +width:90%; +margin:auto; +} +td.param { +font-family:sans-serif; +font-size:11px; +border:1px solid #6495ed; +padding:5px; +text-align:left; +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designHelp.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designHelp.css new file mode 100755 index 0000000000..df08745f31 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designHelp.css @@ -0,0 +1,21 @@ +body +{ + width: 90%; + margin-top: 5px; + margin-bottom: 5px; + margin-left:5%; + margin-reight:5%; + background-color: #CCFFCC; + text-align:justify; +} + +h3,h2 +{ + color : navy; + text-align:center; + text-decoration:underline; +} +#problem +{ + color:red; +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designLogOut.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designLogOut.css new file mode 100755 index 0000000000..02a1a63f3f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designLogOut.css @@ -0,0 +1,12 @@ +body +{ + background-color: #CCFFCC; + margin-top: 2%; + padding: 0%; + outline: 0%; + height: 100%; + overflow:hidden; + max-width:2048px; + text-align:center; + font-size:24px; +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designWelcome.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designWelcome.css new file mode 100755 index 0000000000..e6cd8076f0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designWelcome.css @@ -0,0 +1,30 @@ +body +{ + width: 960px; + margin-top: 100px; + margin-bottom: 5px; + background-image: url("Icons/logo.png"); + background-repeat:no-repeat; + background-color: #CCFFCC; + +} + +#signIn +{ + margin: auto; + width: 300px; + height: 140px; + border: 1px solid black; +} + +#log +{ + margin-left: 30px; +} + +a +{ + position:absolute; + right:1%; + top:80%; +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design_admin.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design_admin.css new file mode 100755 index 0000000000..867056a7a6 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/design_admin.css @@ -0,0 +1,99 @@ +body { + background-color: #EEEEEE; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +select{ + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + vertical-align: middle; + background-color: #F5F5DC; +} +input { + border:1px solid black; + background-color:#F5F5DC; + font-size: 11px; +} + +label { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +span { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +td { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#title { + position : absolute; + top : 0%; + left : 0%; + height : 5%; + width : 100%; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + text-align : right; + font-size : 11px; + background-color: #BC8F8F; + border: 1px solid black; +} + +#page { + position : absolute; + top : 15%; + left : 15%; + width : 70%; + height : 65%; + border: 1px solid black; + background-color: #EEEEEE; +} + + +#modifImmat { + position : absolute; + top : 15%; +} + + +#modifPwd { + position : absolute; + top : 15%; +} + + +#modifRight { + position : absolute; + top : 15%; +} + +#modifyUser { + position : absolute; + top : 15%; +} + +#createUser { + position : absolute; + top : 15%; +} + +#mainForm { + position : absolute; + top : 15%; +} + + +#createIvyUser { + position : absolute; + top : 15%; +} + +#listIvyUser { + position : absolute; + top : 15%; +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designbackup.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designbackup.css new file mode 100755 index 0000000000..b9ea91607d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/designbackup.css @@ -0,0 +1,87 @@ +body +{ + background-color: #CCFFCC; + margin: 0%; + padding: 0%; + outline: 0%; + height: 95%; +} +#page +{ + width: 100%; + height: 95%; +} + +#logo +{ + width: 960px; + height: 100px; + background-image: url("banniere.jpg"); + background-repeat: repeat-x; + margin-bottom: 10px; +} + +#leftmenu +{ + /* float: left; /* Le menu flottera à gauche */ + /* width: 120px; *//* Très important : donner une taille au menu */ +} +#welcome +{ + text-align: center; + background-color: #EEEEEE; + border: 2px solid black; + margin-bottom: 10px; /* Pour éviter que les éléments du menu ne soient trop collés */ +} +#choice +{ +float: left; + text-align: center; + background-color: #EEEEEE; + border: 2px solid black; + height: 190px; + width: 20px; +} +#map_canvas +{ + width: 690px; + height: 350px; + margin-left: 125px; +} + +#FlightPlan +{ + float: right; + width: 135px; /* Très important : donner une taille au menu */ + height: 345px; + border: 2px solid black; + background-color: #EEEEEE; +} + + + +#ControlPanel +{ + float: left; + text-align: center; + height: 150px; + width: 600px; + border: 2px solid black; + background-color: #EEEEEE; +} +#FlightParams +{ + text-align: center; + float: right; + height: 150px; + width: 350px; + border: 2px solid black; + background-color: #EEEEEE; +} +table +{ + margin-left: 20px; + margin-bottom: 20px; +} + + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/dtree.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/dtree.css new file mode 100755 index 0000000000..ccc20f8c35 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/dtree.css @@ -0,0 +1,34 @@ +/*--------------------------------------------------| +| dTree 2.05 | www.destroydrop.com/javascript/tree/ | +|---------------------------------------------------| +| Copyright (c) 2002-2003 Geir Landrö | +|--------------------------------------------------*/ + +.dtree { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + color: #666; + white-space: nowrap; +} +.dtree img { + border: 0px; + vertical-align: middle; +} +.dtree a { + color: #333; + text-decoration: none; +} +.dtree a.node, .dtree a.nodeSel { + white-space: nowrap; + padding: 1px 2px 1px 2px; +} +.dtree a.node:hover, .dtree a.nodeSel:hover { + color: #333; + text-decoration: underline; +} +.dtree a.nodeSel { + background-color: #c0d2ec; +} +.dtree .clip { + overflow: hidden; +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/tab.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/tab.css new file mode 100755 index 0000000000..2e9043ed76 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/tab.css @@ -0,0 +1,110 @@ +/* $Id: example.css,v 1.5 2006/03/27 02:44:36 pat Exp $ */ + +/*-------------------------------------------------- + REQUIRED to hide the non-active tab content. + But do not hide them in the print stylesheet! + --------------------------------------------------*/ +.tabberlive .tabbertabhide { + display:none; +} + +/*-------------------------------------------------- + .tabber = before the tabber interface is set up + .tabberlive = after the tabber interface is set up + --------------------------------------------------*/ +.tabber { +} +.tabberlive { + margin-top:1em; +} + +/*-------------------------------------------------- + ul.tabbernav = the tab navigation list + li.tabberactive = the active tab + --------------------------------------------------*/ +ul.tabbernav +{ + margin:0; + padding: 3px 0; + border-bottom: 1px solid #778; + font: bold 12px Verdana, sans-serif; +} + +ul.tabbernav li +{ + list-style: none; + margin: 0; + display: inline; +} + +ul.tabbernav li a +{ + padding: 3px 0.5em; + margin-left: 3px; + border: 1px solid #778; + border-bottom: none; + background: #DDE; + text-decoration: none; +} + +ul.tabbernav li a:link { color: #448; } +ul.tabbernav li a:visited { color: #667; } + +ul.tabbernav li a:hover +{ + color: #000; + background: #AAE; + border-color: #227; +} + +ul.tabbernav li.tabberactive a +{ + background-color: #fff; + border-bottom: 1px solid #fff; +} + +ul.tabbernav li.tabberactive a:hover +{ + color: #000; + background: white; + border-bottom: 1px solid white; +} + +/*-------------------------------------------------- + .tabbertab = the tab content + Add style only after the tabber interface is set up (.tabberlive) + --------------------------------------------------*/ +.tabberlive .tabbertab { + padding:5px; + border:1px solid #aaa; + border-top:0; + + /* If you don't want the tab size changing whenever a tab is changed + you can set a fixed height */ + + /* height:200px; */ + + /* If you set a fix height set overflow to auto and you will get a + scrollbar when necessary */ + + /* overflow:auto; */ +} + +/* If desired, hide the heading since a heading is provided by the tab */ +.tabberlive .tabbertab h2 { + display:none; +} +.tabberlive .tabbertab h3 { + display:none; +} + +/* Example of using an ID to set different styles for the tabs on the page */ +.tabberlive#tab1 { +} +.tabberlive#tab2 { +} +.tabberlive#tab2 .tabbertab { + height:200px; + overflow:auto; +} + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif new file mode 100755 index 0000000000..085ccaecaf Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100755 index 0000000000..954e22dbd9 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100755 index 0000000000..64ece5707d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png new file mode 100755 index 0000000000..abdc01082b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100755 index 0000000000..9b383f4d2e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png new file mode 100755 index 0000000000..a23baad25b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100755 index 0000000000..42ccba269b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100755 index 0000000000..39d5824d6a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100755 index 0000000000..f1273672d2 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png new file mode 100755 index 0000000000..359397acff Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100755 index 0000000000..b273ff111d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png new file mode 100755 index 0000000000..c357355aa7 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png new file mode 100755 index 0000000000..85e63e9f60 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png new file mode 100755 index 0000000000..e117effa3d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100755 index 0000000000..42f8f992c7 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css new file mode 100755 index 0000000000..312dd8043e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css @@ -0,0 +1,489 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } +.ui-widget-content a { color: #333333; } +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable +----------------------------------*/ +.ui-selectable-helper { border:1px dotted black } +/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +/* IE7-/Win - Fix extra vertical space in lists */ +.ui-accordion a { zoom: 1; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete +----------------------------------*/ +.ui-autocomplete { position: absolute; cursor: default; } +.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* Menu +----------------------------------*/ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* Button +----------------------------------*/ + +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ + + + + + +/* Dialog +----------------------------------*/ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 0.8em; height: 0.8em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/E.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/E.png new file mode 100755 index 0000000000..c54150820a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/E.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/N.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/N.png new file mode 100755 index 0000000000..b7a747cd39 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/N.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NE.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NE.png new file mode 100755 index 0000000000..14d39ae0f0 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NE.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NW.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NW.png new file mode 100755 index 0000000000..e57382d0d4 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/NW.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/S.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/S.png new file mode 100755 index 0000000000..edeabb494d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/S.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SE.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SE.png new file mode 100755 index 0000000000..e2e35ba552 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SE.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SW.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SW.png new file mode 100755 index 0000000000..71f3be47ae Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/SW.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/W.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/W.png new file mode 100755 index 0000000000..baa74b59ad Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/W.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow.png new file mode 100755 index 0000000000..3a004f60b5 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow2.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow2.png new file mode 100755 index 0000000000..d2cae73712 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/arrow2.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/blue-dot.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/blue-dot.png new file mode 100755 index 0000000000..98b280d301 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/blue-dot.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/favicon.ico b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/favicon.ico new file mode 100755 index 0000000000..7cd42a2755 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/favicon.ico differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/logo.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/logo.png new file mode 100755 index 0000000000..032f6d16e7 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/logo.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.gif new file mode 100755 index 0000000000..dfadf2d823 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.png new file mode 100755 index 0000000000..0786209c39 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/losange.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/red-dot.png b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/red-dot.png new file mode 100755 index 0000000000..b0f3f0e928 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Icons/red-dot.png differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Interface.jsp b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Interface.jsp new file mode 100755 index 0000000000..3ef63cc678 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/Interface.jsp @@ -0,0 +1,1943 @@ +<%@page import="pow.webserver.Conf,java.util.StringTokenizer,java.util.NoSuchElementException" %> + +<% + if (session.getAttribute("login")==null) { + out.println(""); + } +%> + + + + + + + + POW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "); + } + else { + String login = ((String) (session.getAttribute("login"))).toString(); + String right = ((String) (session.getAttribute("rights"))).toString(); + if (right.equals("visitor")) + { out.println("var usr_right=\"visitor\";"); + out.println("var usr_login=\"nologged\";"); + } + else if (right.equals("admin")) + { + out.println("var usr_right=\"admin\";"); + out.println("var usr_login=\""+login+"\";"); + } + else if (right.equals("user")){ // gestion de la liste des drones controlables + out.println("var usr_right=\"user\";"); + out.println("var usr_login=\""+login+"\";"); + out.println("var drone_ctl=new Array();"); + String droneCtl = ((String) (session.getAttribute("dronectl"))).toString(); + StringTokenizer st = new StringTokenizer(droneCtl,";"); + String d; + for(int i = 0 ; i< st.countTokens() ;i++){ + d=st.nextToken(); + out.println("drone_ctl[\""+ d +"\"]=1;"); + } + try{ + while (st.hasMoreTokens()) { + d=st.nextToken(); + } + } + catch (NoSuchElementException ex){} + + } + } + String default_folder = this.getServletConfig().getServletContext().getRealPath(""); + Conf myconf =new Conf(default_folder,"pow_conf.xml"); + out.println("//10sec after plane_die event remove drone"); + out.println("var dieEventTimeoutTime = "+myconf.getDieEventTimeoutTime()+";"); + out.println("//5sec without any position data about a drone remove drone"); + out.println("var dataEventTimeoutTime = "+myconf.getDataEventTimeoutTime()+";"); + out.println("// time to wait before order was cancelled"); + out.println("var order_response_timeout = "+myconf.getOrderResponseTimeout()+";"); + %> + var noPlaneBefore=true; // pour initialiser au premier push flight param + var ajax_url = "ajaxRqst.srv"; +/* ********** drone state timeout ******** */ + var droneStateDieEvent = new Array(); // timeout en cas d'event die + var droneStateDataEvent = new Array(); // timeout en cas de non evenement data + var waypoint_modif = new Array(); // + var block_jump_timeout=-1; + var setting_change_timeout=-1; + var setting_to_change_id=-1; +/* *************************************************************************** Global variables *************************************************************************************** */ + var map; + + var planes = new Array(); + var nb_planes =0; + var markers = new Array(); + var markers_color = new Array(); // stock les balises de couleurs de chaque drone + var diametre_drone_balise = 50; //50m de base + var selected_plane = ""; + var selected_plane_id = 0; + var selected_index=0; + var tracking = false; + +/* *******************Flight Plan variables :******************** */ + var waypoints = new Array(); + var waypoint_tmp = null; + var index_wpt = 0; + var blocks= new Array(); + var index_block = 0; + var active_block_id=0; + var active_block_name=""; + var fpl_name=""; + var lat0=0; + var lon0=0; + var fpl_alt=0; + var security_height=0; + var fpl_ground_alt=0; + var max_dist=0; + + +/* ********************Planes and waypoints icons******************** */ + var plane_icons = new Array(); + for (var i=0;i<8;i++){ + plane_icons[i] = new GIcon(); + plane_icons[i].shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + plane_icons[i].iconSize = new GSize(60,60); + plane_icons[i].shadowSize = new GSize(22, 20); + plane_icons[i].infoWindowAnchor = new GPoint(50, 1); + plane_icons[i].iconAnchor = new GPoint(30, 30); + } + plane_icons[0].image="Icons/N.png"; + plane_icons[1].image="Icons/NE.png"; + plane_icons[2].image="Icons/E.png"; + plane_icons[3].image="Icons/SE.png"; + plane_icons[4].image="Icons/S.png"; + plane_icons[5].image="Icons/SW.png"; + plane_icons[6].image="Icons/W.png"; + plane_icons[7].image="Icons/NW.png"; + + var wpt_icon=new GIcon(); + wpt_icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + wpt_icon.iconSize = new GSize(20,20); + wpt_icon.shadowSize = new GSize(22, 20); + wpt_icon.infoWindowAnchor = new GPoint(8, 1); + wpt_icon.iconAnchor = new GPoint(6, 20); + //wpt_icon.image="Icons/losange.png"; + wpt_icon.image="Icons/blue-dot.png"; + + var iconMarkerTemp=new GIcon(); + iconMarkerTemp.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + iconMarkerTemp.iconSize = new GSize(20,20); + iconMarkerTemp.shadowSize = new GSize(22, 20); + iconMarkerTemp.infoWindowAnchor = new GPoint(8, 1); + iconMarkerTemp.iconAnchor = new GPoint(6, 20); + iconMarkerTemp.image="Icons/red-dot.png"; +/* *************************************************************************** Functions **************************************************************************************************** */ + +/* ************ prevent user from going back to this page by browser's forward button****************************** */ + +function backButtonOverride() +{ + // Work around a Safari bug + // that sometimes produces a blank page + setTimeout("backButtonOverrideBody()", 1); + +} + +function backButtonOverrideBody() +{ + // Works if we backed up to get here + try { + history.forward(); + } catch (e) { + // OK to ignore + } + // Every quarter-second, try again. The only + // guaranteed method for Opera, Firefox, + // and Safari, which don't always call + // onLoad but *do* resume any timers when + // returning to a page + setTimeout("backButtonOverrideBody()", 500); +} +/* ******************* Useful functions ******************** */ +// Gets an element of the html document by its class name + function getElementsByClass(tag, className){ + var elements = document.getElementsByTagName(tag); + var results = new Array(); + for(var i=0; i< elements.length; i++){ + if(elements[i].className == className){ + results[results.length] = elements[i]; + } + } + return results; + } + + + function pause(time){ + d=new Date(); + diff=0; + while(diff < time){ + n=new Date(); + diff=n-d; + } + } + + + //Creates a GoogleMaps marker + + + + + function createMarker(point, legend, icon){ + var marker = new GMarker(point, icon); + GEvent.addListener(marker, 'click', function() { + marker.openInfoWindowHtml(legend); + }); + return marker; + } + + var old_lat; + var old_lon; + //Creates a draggable marker with an EventListener + function createDraggableMarker(point,namewpt,wpt_icon,index_wpt, bool){ + var fpl_file_name="upload/"+planes[selected_index]["id"]+"/flight_plan.xml"; + var marker = new GMarker(point,{legend: namewpt,icon: wpt_icon,draggable: bool,bouncy:true}); + //var marker = new GMarker(point,{title: name,draggable: bool}); + //var marker = new GMarker(point,{draggable: bool}); + GEvent.addListener(marker, 'click', function() { + marker.openInfoWindowHtml(namewpt); + }); + if (bool){ + GEvent.addListener(marker, 'dragend', function(latlng) { + if (latlng){ + //alert("id wpt="+index_wpt+" name=" +namewpt+" lat="+latlng.lat()+" lon="+latlng.lng()); + var lat = latlng.lat(); + var lon = latlng.lng(); + moveWpt(selected_plane_id,namewpt,lat,lon,false,true,index_wpt); + } + }); + + GEvent.addListener(marker, 'dragstart', function(latlng) { + if (latlng){ + old_lat=latlng.lat(); + old_lon=latlng.lng(); + } + }); + } + + return marker; + } + + + + + +//Converts ditances from (lat0,lon0) given in meters into latitudes or longitudes, and vice versa + function xMetersToDegrees(x,lat0){ + return (x/1852/60+parseFloat(lat0)); + } + function yMetersToDegrees(y,lat,lon0){ + return (y/1852/60*Math.cos(lat)+parseFloat(lon0)); + } + + function xDegreesToMeters(lat,lat0){ + return((lat-lat0)*1852*60); + } + function yDegreesToMeters(lat,lon,lon0){ + return(lat!=0?(lon-lon0)/Math.cos(lat)*1852*60:0); + } + + + function name_from_id(id){ + var match=false; + for (var i=0;i< planes.length;i++){ + if(planes[i]["id"]==id){match=true;break;} + } + if (match){ + return (planes[i]["name"]); + }else{ + return (null); + } + } + /* *************** JQUERY stuffs ***************************** */ + $(function(){ + //init(); + //$("#Settings").draggable();$("#Settings").resizable(); + //$("#map_canvas").draggable();$("#map_canvas").resizable(); + //$("#Debug").draggable();$("#Debug").resizable(); + //$("#choicePanel").draggable();$("#choicePanel").resizable(); + //$("#FlightPlan").draggable();$("#FlightPlan").resizable(); + //$("#FlightParams").draggable();$("#FlightParams").resizable(); + }); +/* ********************* Fonctions de Push ******************** */ + + function initialize_push() { + // alert('go'); + p_join_listen(null, 'stream'); + // TODO il faudra gerer le cas ou cela bloque !!!! et passer en pull + // p_join_listen(null, 'pull'); + p_subscribe('/data/drone/iskill', 'msg from serveur'); + p_subscribe('/data/drones_maj', 'msg from serveur'); + p_subscribe('/data/order/waypoint_moved', 'msg from serveur'); + p_subscribe('/data/order/change_setting', 'msg from serveur'); + p_subscribe('/data/order/plane_die', 'msg from serveur'); + p_subscribe('/data/order/plane_resurect', 'msg from serveur'); + p_subscribe('/data/order/new_plane', 'msg from serveur'); + p_subscribe('/data/order/block_changed', 'msg from serveur'); + p_subscribe('/data/order/other', 'msg from serveur'); + p_subscribe('/data/order/settings', 'msg from serveur'); + + p_subscribe('/chat','msg from web client'); + p_subscribe('/client_action','action from web client'); + } + + function initialize_push_pullmode() { + + p_join_listen(null, 'pull'); + p_subscribe('/data/drone/iskill', 'msg from serveur'); + p_subscribe('/data/drones_maj', 'msg from serveur'); + p_subscribe('/data/order/waypoint_moved', 'msg from serveur'); + p_subscribe('/data/order/change_setting', 'msg from serveur'); + p_subscribe('/data/order/plane_die', 'msg from serveur'); + p_subscribe('/data/order/plane_resurect', 'msg from serveur'); + p_subscribe('/data/order/new_plane', 'msg from serveur'); + p_subscribe('/data/order/block_changed', 'msg from serveur'); + p_subscribe('/data/order/other', 'msg from serveur'); + p_subscribe('/data/order/settings', 'msg from serveur'); + + p_subscribe('/chat','msg from web client'); + p_subscribe('/client_action','action from web client'); + } + + function displayControl(aString) { + document.debugEventDisplay.event.value = aString; + } + // callback on data Events + // call apropirate function according to the received event + + function onData(event) { + var subject = event.get('p_subject'); + + // displayControl(""+ event.toString()); + + if (subject=="/data/drones_maj") { handleDronePositionUpsate(event);} + else if (subject =="/data/order/waypoint_moved") {orderprocessing_waypoint(event);} + else if (subject =="/data/order/block_changed") {orderprocessing_jump2block(event);} + else if (subject =="/data/order/change_setting") {orderprocessing_setting(event);} + else if (subject =="/data/order/plane_die") {orderprocessing_planedie(event);} + else if (subject =="/data/order/plane_resurect"){orderprocessing_planeressurect(event);} + else if (subject =="/data/order/new_plane") {orderprocessing_newplane(event);} + else if (subject =="/data/drone/iskill") {orderprocessing_planekilled(event);} + else if (subject =="/data/order/settings") {orderprocessing_csv_settings(event);} + else if (subject =="/chat") {orderprocessing_chat(event);} + else if (subject =="/client_action") {orderprocessing_client_action(event);} + } + + // callback on all other kind of Events + + <%--function onEvent(event) { + var subject = event.get('p_subject'); + displayControl("EVENT CALLBACK "+subject+"\n" + event.toString()); + + + } + --%> +/* ********************* initilization de l'interface ******************* */ + function initialize_display(){ + var aircraftList = document.getElementById("aircraftForm").aircraftList; + if (nb_planes ==0)//If there is no active aircraft, the list only has one option : No aircraft + {aircraftList.options[0]=new Option("No aircraft");} +} + +/* *********************functions to check airplanes ******************* */ + +/* *********************Processing events ******************* */ + // recherche si l'id de l'avion est deja present dans le tableau des drones deja + function handleDronePositionUpsate(event){ + if (planes.length==0) {noPlaneBefore=true;} + var id = parseInt(event.get('aircraftId')); + var match=false; + var insert=false; + var aircraftList = document.getElementById("aircraftForm").aircraftList; + nb_planes=planes.length; + for (var i=0;i< nb_planes;i++){ + if(planes[i]["id"]> id){insert=true;break;} // on garde le tableau trié + if (planes[i]["id"]==id){match=true;break;} // on recupere en i le drone correspondant à id + } + if(!match){ + var k=0; + if(insert){ // on insert au milieu + k=i; + planes.splice(i,0,new Array()); + markers.splice(i,0,null); + markers_color.splice(i,0,null); + // on insere l'aircraft dan sla liste deroulante + //see http://www.mredkj.com/tutorials/tutorial005.html + var elOptNew = document.createElement('option'); + elOptNew.text = event.get('dbName') + var elOptOld = aircraftList.options[i]; + try { + aircraftList.add(elOptNew, elOptOld); // standards compliant; doesn't work in IE + } + catch(ex) { + aircraftList.add(elOptNew, i); // IE only + } + }else{ // on met à la fin du tableau + k=planes.length; + planes[k] = new Array(); + markers[k]= null; // inutile + markers_color[k]=null; + aircraftList.options[k]=new Option(event.get('dbName')); + } + droneStateDieEvent[k] = -1; // init un timeout vide + // + planes[k]["id"]=id; + planes[k]["name"] =event.get('dbName'); + planes[k]["lat"] = event.get('dbLatitude'); + planes[k]["lon"] = event.get('dbLongitude'); + planes[k]["heading"]= event.get('dbCourse'); + // maj des param pour selected acrf + planes[k]["speed"]= event.get('dbSpeed'); + planes[k]["altitude"]= event.get('dbAmsl'); + planes[k]["vspeed"]= event.get('dbVert_speed'); + planes[k]["height"]= event.get('dbAgl'); + planes[k]["battery"]= event.get('dbStat_battery'); + planes[k]["GPS"]= event.get('dbStat_gps'); + planes[k]["activeBlock"]= event.get('dbActive_block'); + planes[k]["engine"]= event.get('dbEngine_status'); + planes[k]["setting_id"]= event.get('dbId_Setting'); + planes[k]["setting_value"]= event.get('dbSetting_Value'); + planes[k]["drone_color"]= event.get('drone_color'); + // gere si le drone peut etre controlé ou non + if ((usr_right=="admin")||((usr_right=="user")&&(drone_ctl[event.get('dbName')]!=null))){ + planes[k]["rights"]= 1; + } + else + {planes[k]["rights"]=0;} + + var icon; + if (planes[k]["heading"]>=338 || planes[i]["heading"]< 23){ + icon = plane_icons[0]; + }else if (planes[k]["heading"]>=23 && planes[i]["heading"]<68){ + icon = plane_icons[1]; + }else if (planes[k]["heading"]>=68 && planes[i]["heading"]<113){ + icon = plane_icons[2]; + }else if (planes[k]["heading"]>=113 && planes[i]["heading"]<158){ + icon = plane_icons[3]; + }else if (planes[k]["heading"]>=158 && planes[i]["heading"]<203){ + icon = plane_icons[4]; + }else if (planes[k]["heading"]>=203 && planes[i]["heading"]<248){ + icon = plane_icons[5]; + }else if (planes[k]["heading"]>=248 && planes[i]["heading"]<293){ + icon = plane_icons[6]; + }else if (planes[k]["heading"]>=293 && planes[i]["heading"]<337){ + icon = plane_icons[7]; + } + //A marker is created and added on the map + var pos = new GLatLng(planes[k]["lat"],planes[k]["lon"]); + markers[k]=createMarker(pos,planes[k]["name"],icon); + markers_color[k] = GPolygon.Circle(pos,diametre_drone_balise,"#000000",1,1,planes[i]["drone_color"],0.5) + map.addOverlay(markers[k]); + map.addOverlay(markers_color[k]); + droneStateDataEvent[k] = setTimeout("nodataEventCallBack("+id+")",dataEventTimeoutTime); + } + else // l event envoyé correspond à un drone deja dans le tableau + { + if (droneStateDataEvent[i]!=-1) {clearTimeout(droneStateDataEvent[i]);} + var heading_changed; + //Update of the planes array + planes[i]["lat"] = event.get('dbLatitude'); + planes[i]["lon"] = event.get('dbLongitude'); + // maj des param pour selected acrf + planes[i]["speed"]= event.get('dbSpeed'); + planes[i]["altitude"]= event.get('dbAmsl'); + planes[i]["vspeed"]= event.get('dbVert_speed'); + planes[i]["height"]= event.get('dbAgl'); + planes[i]["battery"]= event.get('dbStat_battery'); + planes[i]["GPS"]= event.get('dbStat_gps'); + planes[i]["activeBlock"]= event.get('dbActive_block'); + planes[i]["engine"]= event.get('dbEngine_status'); + planes[i]["setting_id"]= event.get('dbId_Setting'); + planes[i]["setting_value"]= event.get('dbSetting_Value'); + planes[i]["drone_color"]= event.get('drone_color'); + // + var new_heading = event.get('dbCourse'); + var old_heading = planes[i]["heading"]; + //Update of the icons if the heading has changed + if (Math.abs(new_heading-old_heading)>2){ + var image; + if (new_heading>=338 || new_heading< 23){ + image = plane_icons[0].image; + }else if (new_heading>=23 && new_heading<68){ + image = plane_icons[1].image; + }else if (new_heading>=68 && new_heading<113){ + image = plane_icons[2].image; + }else if (new_heading>=113 && new_heading<158){ + image = plane_icons[3].image; + }else if (new_heading>=158 && new_heading<203){ + image = plane_icons[4].image; + }else if (new_heading>=203 && new_heading<248){ + image = plane_icons[5].image; + }else if (new_heading>=248 && new_heading<293){ + image = plane_icons[6].image; + }else if (new_heading>=293 && new_heading<337){ + image = plane_icons[7].image; + } + markers[i].setImage(image); + } + planes[i]["heading"] = new_heading; + //Setting the marker to its new position + var new_pos = new GLatLng(planes[i]["lat"],planes[i]["lon"]); + markers[i].setLatLng(new_pos); + //see http://econym.org.uk/gmap/eshapes.htm + map.removeOverlay(markers_color[i]); + markers_color[i] = GPolygon.Circle(new_pos,diametre_drone_balise,"#000000",1,1,planes[i]["drone_color"],0.5); + map.addOverlay(markers_color[i]); + droneStateDataEvent[i] = setTimeout("nodataEventCallBack("+id+")",dataEventTimeoutTime); + } + nb_planes=planes.length; + + document.getElementById("aircraftList").options.length=planes.length; + if (tracking&&nb_planes!=0){//If tracking is activated, the map is centered on the aircraft + var zoom = map.getZoom(); + var plane_number = aircraftList.selectedIndex; + map.setCenter(new GLatLng(planes[plane_number]["lat"],planes[plane_number]["lon"]),zoom); + } + + if (noPlaneBefore==true){ + noPlaneBefore=false;// !!! interruption possible + active_block_id=planes[0]["activeBlock"]; + aircraftList.options[0].selected=true; + selected_plane = planes[0]["name"]; + selected_plane_id = planes[0]["id"]; + DOMImplementation("upload/"+planes[0]["id"]+"/flight_plan.xml",fplDisplay); + DOMImplementation("upload/"+planes[0]["id"]+"/settings.xml",settingsDisplay); + } + selected_plane_update(selected_plane_id); + } + + +/* ******************** affichage log ******************* */ + +var coloryellow = true; +function addMsgLog(msg) +{ + var element = document.getElementById("info"); + var newinfodiv = document.createElement("div"); + var newinfotxt = document.createTextNode(msg); + if (coloryellow) {newinfodiv.style.background = '#FFE4B5';coloryellow=false;} + else {newinfodiv.style.background = '#D2B48C';coloryellow=true;} + newinfodiv.appendChild(newinfotxt); + element.appendChild(newinfodiv); +} +/* ******************** Initialization of the page ******************* */ + +/* Initialization of the page : map, markers, aircraft list... */ + + + function initialize() { + + if (GBrowserIsCompatible()) { + // initialize_planes_data(); + initialize_display(); + initialize_push(); + map = new GMap2(document.getElementById("map_canvas"));//Map creation + map.setMapType(G_HYBRID_MAP); + var point= new GLatLng(43.46223, 1.27289); + map.setCenter(point,15);//Center the map on a temporary point + map.setUIToDefault(); + // + GEvent.addListener(map, "zoomend", function(oldlevel,newlevel) { + var d = newlevel-oldlevel; + if (d<0) { + diametre_drone_balise=diametre_drone_balise*(-2*d); + } + else + { + diametre_drone_balise=diametre_drone_balise/(2*d); + } + }); + }else{ + alert("Your browser is not compatible with Google Maps !"); + } + } + + + +/* Updating of the selected aircraft flight parameters */ +// recherche la place de l'avion dans le tableau + function seekIndex(plane_id) + { + var i = 0; + var trouve = false; + var res=-1; + while ((ilat y->lon !'); + x = parseFloat(childXML.getAttribute("x")); + y = parseFloat(childXML.getAttribute("y")); + lat=xMetersToDegrees(x,lat0); + lon=yMetersToDegrees(y,lat,lon0); + } + else + { + lat=parseFloat(childXML.getAttribute("lat")); + lon=parseFloat(childXML.getAttribute("long")); + } + var right=planes[selected_index]["rights"]; + waypoints[index_wpt]["marker"]=null; + + if (right==1){ + waypoints[index_wpt]["marker"]=createDraggableMarker(new GLatLng(lat,lon),nameWpt,wpt_icon,index_wpt, true); + }else { + waypoints[index_wpt]["marker"]=createDraggableMarker(new GLatLng(lat,lon),nameWpt,wpt_icon,index_wpt, false); + } + map.addOverlay(waypoints[index_wpt]["marker"]); + + var alt=false; + if (childXML.getAttribute("alt")!=null){ + alt=childXML.getAttribute("alt"); + waypoints[index_wpt]["alt"]=parseFloat(childXML.getAttribute("alt")); + } + var node_url=""; + if (right==1){ + node_url = "javascript:moveWpt("+selected_index+",'"+nameWpt+"',"+lat+","+lon+","+alt+",false,"+(index_wpt)+")"; + } + ///// + index_wpt++; + var newindex = index++; + fpl_tree.add(newindex,index_pere,nameWpt,node_url); + for(var k =0;k< nbr_attrib;k++){ + var newindex_attrib_name = index++; + var newindex_attrib_value = index++; + fpl_tree.add(newindex_attrib_name,newindex,childXML.attributes[k].nodeName); + fpl_tree.add(newindex_attrib_value,newindex_attrib_name,childXML.attributes[k].nodeValue); + //txt = txt + childXML.attributes[k].nodeName + "=" + childXML.attributes[k].nodeValue +" "; + } + } + } + else if (childXML.nodeName=="block") + { var node_url="";var txt_block_name=""; + if(childXML.attributes!=null){ + var block_name=childXML.getAttribute("name");//.replace(/ /g, '_'); + blocks[index_block]=new Array(); + blocks[index_block]["name"]=block_name; + if (active_block_id==index_block){ + active_block_name=block_name; + txt_block_name = ""+block_name+""; + } + else + { + txt_block_name = block_name; + } + var right=planes[selected_index]["rights"]; + + if (right==1){ + node_url="javascript:activateBlock("+selected_index+",'"+block_name+"',"+index_block+")"; + } + index_block++; + var txt = txt_block_name+ " : "; + var nbr_attrib = childXML.attributes.length; + for(var k =0;k< nbr_attrib;k++){ + if (childXML.attributes[k].nodeName!="name"){ + var newindex_attrib_name = index++; + var newindex_attrib_value = index++; + txt = txt + childXML.attributes[k].nodeName + "=" + childXML.attributes[k].nodeValue +" "; + } + } + } + var newindex = index++; + fpl_tree.add(newindex,index_pere,txt,node_url); + } + // recursion + if(childXML.hasChildNodes()) { + var nodes=childXML.childNodes.length; + for(var i=0; i90.0)||(l<-90.0)||isNaN(new_lat)) { + alert('wrong format for a latitude... should be within [-90:+90]'); + return; + } + new_lon=prompt("longitude=",mylon); + if ((new_lon==null)){ + return; + } + l = parseFloat(new_lon); + if ((l>180.0)||(l<-180.0)||isNaN(new_lon)) { + alert('wrong format for a longitude... should be within [-180:+180]'); + return; + } + if (alt){ + new_alt=prompt("altitude=",alt); + if ((new_alt==null)){ + return; + } + l = parseFloat(new_alt); + if ((l<=0.0)||isNaN(new_alt)) { + alert('wrong format for an altitude... should be positive'); + return; + } + } + // + old_lat = waypoints[idwpt]["lat"]; + old_lon = waypoints[idwpt]["lon"]; + }else{ + new_lat=mylat; + new_lon=mylon; + } + + + //Ajax request to edit the flight plan xml file + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + // maj de l'affichage fpl + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("waypoint_to_move")[0]; + var idwpt_requested = parseInt(rep.getAttribute("idwpt"))-1;// cf waypoint fictif ivy + var acid_requested = parseInt(rep.getAttribute("acid")); + var lat_requested = parseFloat(rep.getAttribute("newlat")); + var lon_requested = parseFloat(rep.getAttribute("newlon")); + var was_dragged = rep.getAttribute("dragged"); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + // on ne met à jour visuellement que si le focus est sur le drone selecté + if (acid_requested==selected_plane_id){ + // mettre le waypoint dans un etat intermediaire + // en attendant l'accuse de reception + var right=planes[selected_index]["rights"]; + var marker_tmp; + if (right==1){ + marker_tmp=createDraggableMarker(new GLatLng(old_lat,old_lon),waypoints[idwpt_requested]["name"],wpt_icon,idwpt_requested, true); + }else { + marker_tmp=createDraggableMarker(new GLatLng(old_lat,old_lon),waypoints[idwpt_requested]["name"],wpt_icon,idwpt_requested, false); + } + var name_wpt = waypoints[idwpt_requested]["name"]; + var timer=setTimeout("callback_waypoint("+acid_requested+","+idwpt_requested+")",order_response_timeout); + waypoint_modif[idwpt_requested] = new createWaypoint(acid_requested,idwpt_requested,name_wpt,marker_tmp,timer); + // on efface le marker courant + // meme si elle a ete deplacé par drag & drop + // on cree un marker non draggable avec une icone temporaire + map.removeOverlay(waypoints[idwpt_requested]["marker"]); + waypoints[idwpt_requested]["marker"] = createMarker(new GLatLng(lat_requested,lon_requested),name_wpt,iconMarkerTemp); + if (waypoints[idwpt_requested]["marker"]!=null) map.addOverlay(waypoints[idwpt_requested]["marker"]); + else alert('echec creation wpt tmp'); + addMsgLog("waypoint "+ name_wpt +" for drone " + name_drone +" will be moved"); + } + else + { + addMsgLog("waypoint "+ idwpt_requested +" for drone " + name_drone +" will be moved"); + } + + } + }; + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + // on informe les autres clients de ne pas modifier le waypoint en cours (via pushlet) + p_publish('/client_action', 'login',usr_login,'action', 'lock', 'type_obj', 'waypoint', 'id_obj',idwpt,'webiddrone',selected_plane_id); + // on passe en parametre le index_wpt+1 car dans paparazzi il y a un wpt predefini a zero + + if(alt!=false){ + xhr.send("order=fpl_update&wpt_name="+name+"&aircraft_id=" +selected_plane_id+"&wpt_id="+(idwpt+1)+"&new_lat="+new_lat+"&new_lon="+new_lon+"&new_alt="+new_alt+"&dragged="+dragged+"&new_alt_for_fpl=1"); + //alert("wptid="+i+" lat="+new_lat+"lon="+new_lon+"alt="+new_alt); + }else{ + var alti=document.getElementById("altitude");var h=parseFloat(alti.innerHTML); + xhr.send("order=fpl_update&wpt_name="+name+"&aircraft_id=" +selected_plane_id+"&wpt_id="+(idwpt+1)+"&new_lat="+new_lat+"&new_lon="+new_lon+"&new_alt="+parseFloat(alti.innerHTML)+"&dragged="+dragged+"&new_alt_for_fpl=0"); + //alert("wptid="+i+" lat="+new_lat+"lon="+new_lon+"alt="+h); + } +} + + +/* ******** Activate a flight plan block ******** */ + + + + function activateBlock(ac_webid,blockname,block_id){ + // verifie qu'il n'y pas pas un verrou sur le block posé par un autre client + var k=0; + var trouve = false; + while ((!trouve)&&(k= parseFloat(min)) ){ + correct=true; + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("setting_to_change")[0]; + var idsetting_requested = parseInt(rep.getAttribute("setting_id")); + var acid_requested = parseInt(rep.getAttribute("acid")); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + addMsgLog("request change setting "+ idsetting_requested +" for drone " + name_drone +" has been sent"); + // mise en place d'un timer d'accusé reception + if(acid_requested==planes[selected_index]["id"]){ + setting_change_timeout=setTimeout("callback_setting("+acid_requested+","+idsetting_requested+")",order_response_timeout); + setting_to_change_id = idsetting_requested; + } + } + }; + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + //Send the parameters to the php page : + xhr.send("order=modif_setting&aircraft_id=" +selected_plane_id+"&setting_id="+idsetting+"&value="+new_value); + + }else{ + new_value=prompt("Wrong value, please enter a value between "+min+" and "+max+" with a step of "+step+" :"); + if (new_value==null){return;} + } + } + } + + function changeSetting2(idsetting,new_value){ + + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("setting_to_change")[0]; + var idsetting_requested = parseInt(rep.getAttribute("setting_id")); + var acid_requested = parseInt(rep.getAttribute("acid")); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + addMsgLog("request change setting "+ idsetting_requested +" for drone " + name_drone +" has been sent"); + // mise en place d'un timer d'accusé reception + if(acid_requested==planes[selected_index]["id"]){ + setting_change_timeout=setTimeout("callback_setting("+acid_requested+","+idsetting_requested+")",order_response_timeout); + setting_to_change_id = idsetting_requested; + } + } + }; + // on informe les autres clients de ne pas modifier le setting en cours (via pushlet) + p_publish('/client_action', 'login',usr_login,'action', 'lock', 'type_obj', 'setting', 'id_obj',idsetting,'webiddrone',selected_plane_id); + // + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + //Send the parameters to the servlet : + xhr.send("order=modif_setting&aircraft_id=" +selected_plane_id+"&setting_id="+idsetting+"&value="+new_value); + + } + +/* ************************* handle event orders from server ********************************************* */ + + function orderprocessing_waypoint(event){ + + var acft_id = parseInt(event.get('aircraftId')); + var wpt_id = parseInt(event.get('waypointId'))-1; // cf indentation des waypoint sous ivy + var lat = event.get('latitude'); + var lon = event.get('longitude'); + var alt = event.get('altitude'); + var name=name_from_id(acft_id); + if ((wpt_id>=0)&&(acft_id==selected_plane_id)) { + if (waypoint_modif[wpt_id]!=null) + { + addMsgLog('waypoint ' + wpt_id+' for drone '+name+ ' has been moved to '+lat+"//"+lon+' !'); + clearTimeout(waypoint_modif[wpt_id].timer) + waypoint_modif[wpt_id] = null; + DOMImplementation("upload/"+planes[selected_index]["id"]+"/flight_plan.xml",fplDisplay); + // inform other web client that waypoint can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'waypoint', 'id_obj',wpt_id,'webiddrone',acft_id); + } + } + //document.getElementById("info").innerHTML='waypoint' + wpt_id+' for drone '+name+ ' has been moved !'; + //addMsgLog('waypoint' + wpt_id+' for drone '+name+ ' has been moved !'); + //alert('
waypoint' + wpt_id+' for drone '+name+ ' has been moved !'); + } + + function orderprocessing_jump2block(event) { + var acft_id = event.get('aircraftId'); + var current_block_id = event.get('currentBlockId'); + if (acft_id==selected_plane_id){ + /// maj de l'affichage fpl + var name_block=blocks[current_block_id]["name"]; + var name_drone=name_from_id(acft_id); + clearTimeout(block_jump_timeout); + active_block_id = current_block_id; + active_block_name =name_block; + // inform other web client that block can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'block', 'id_obj',current_block_id,'webiddrone',acft_id); + addMsgLog('drone '+ name_drone + ' has jump to block '+ name_block +' !'); + DOMImplementation("upload/"+planes[selected_index]["id"]+"/flight_plan.xml",fplDisplay); + } + } + + function orderprocessing_setting(event) { + var acft_id = event.get('aircraftId'); + var setting_id = parseInt(event.get('settingId')); + var value = event.get('settingValue'); + if ((acft_id==selected_plane_id)&&(setting_to_change_id==setting_id)){ + clearTimeout(setting_change_timeout); + setting_to_change_id = -1; // reset + var name=name_from_id(acft_id); + //DOMImplementation("upload/"+planes[selected_index]["id"]+"/settings.xml",settingsDisplay); + selected_plane_update(acft_id); + addMsgLog('setting ' + setting_id +' for drone '+ name + ' has been changed to value '+ value +' !'); + // inform other web client that block can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'setting', 'id_obj',setting_id,'webiddrone',acft_id); + } + } + + + function orderprocessing_planedie(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + var name=name_from_id(acft_id); + //document.getElementById('info').innerHTML='drone ' + name+' is not alive !'; + addMsgLog('drone ' + name+' is not alive !'); + var drone_index = seekIndex(acft_id); + if(drone_index!=-1) + { + addMsgLog('drone ' + name+' will be removed in 10 seconds !'); + droneStateDieEvent[drone_index] = setTimeout("droneDieCallback("+acft_id+")", dieEventTimeoutTime); + // on grise l'aircraft sur l'interface + } + } + + function orderprocessing_planeressurect(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + //document.getElementById('info').innerHTML='drone ' +name+' has been resurrected !'; + addMsgLog('drone ' +acft_id+' has been resurrected !'); + var drone_index = seekIndex(acft_id); + if(drone_index!=-1) + { + clearTimeout ( droneStateDieEvent[drone_index] ); + // on remet l'aircraft en couleur + } + } + + function orderprocessing_newplane(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + var name= event.get('aircraftName'); + //document.getElementById('info').innerHTML='drone ' +name+' has been connected !'; + addMsgLog('drone ' +name+' has been connected !'); + } + + + function orderprocessing_planekilled(event){ + var acft_id = event.get('aircraftId'); + var name=name_from_id(acft_id); + addMsgLog("drone " + name + " deconnection caused by death of ivy bus..."); + //document.getElementById('info').innerHTML="drone " + name + " deconnection caused by death of ivy bus..."; + // remove drone...markers.... + removeDroneDisplay(acft_id); + } + + function orderprocessing_csv_settings(event){ + var acft_id = event.get('aircraftId'); + var csv = event.get('csv'); + var index_drone = seekIndex(acft_id); + var name=name_from_id(acft_id); + if (index_drone!=-1) { + planes[index_drone]["csv"]= csv; + //addMsgLog("settings updated for drone " + name); + if(index_drone==selected_index) + { + DOMImplementation("upload/"+planes[selected_index]["id"]+"/settings.xml",settingsDisplay); + } + } + } + + function orderprocessing_chat(event){ + } + + function createLock(id_drone,typ_obj,id_obj,login){ + this.id_drone = id_drone; + this.type_object = typ_obj; + this.id_object = id_obj; + this.request_login = login; + this.lockmsg = function() + {return ("user "+this.request_login+ " has locked "+this.type_object +" " +this.id_object);} + this.unlockmsg = function() + {return ("user "+this.request_login+ " has unlocked "+this.type_object +" " +this.id_object);} + } + + var external_waypoint_lock = new Array(); + var external_block_lock = new Array(); + var external_setting_lock = new Array(); + // set or remove a lock to prevent user to change sthg taht is to be changed by another user + function orderprocessing_client_action(event){ + var rqst_login = event.get('login'); + var rqst_action = event.get('action'); + var rqst_obj_type = event.get('type_obj'); + var rqst_obj_id = event.get('id_obj'); + var rqst_id_drone = event.get('webiddrone'); + if (rqst_action=='lock'){ + var lock_obj = new createLock(rqst_id_drone,rqst_obj_type,rqst_obj_id,rqst_login); + if (rqst_obj_type=='waypoint') {external_waypoint_lock.push(lock_obj);} + else if (rqst_obj_type=='block') {external_block_lock.push(lock_obj);} + else if (rqst_obj_type=='setting') {external_setting_lock.push(lock_obj);} + addMsgLog(lock_obj.lockmsg()); + } + else if (rqst_action =='unlock'){ + var trouve = false; + var cur_id_obj=-1; + var i=0; + if (rqst_obj_type=='waypoint') + { + while((!trouve)&&(i + + + + + + + +
+-------- Paparazzi On the Web ! -------- +
+Welcome, +<% + String log = (String) session.getAttribute("login"); + if(log != null) { + out.print(log + "!"); + String rights = (String) session.getAttribute("rights"); + if (rights.equals("admin")){ + out.println(" | admin page"); + } + out.println(" | \"pull\" mode"); + out.println(" | log out"); + } + else + { + out.println(""); + } + +%> + +
+
+ +
+ +
+
+
+
+ + +
+
+
+
+
+
+

+ +
+

+
+
+
+
+
loading...
+
+
+ +
+loading... +
+ + + +
+
Flight Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
altitude (m)0
height0 m
battery level0V
speed0 km/h
GPS statusOFF
vertical speed0 m/s
engine power0%
+
+ + + + +
+
+ +
+
+
+
+
    +
+
+
+
+
+ +
+
no news..
+
+ + + +
+ + + + + +<% + out.println(""); +%> + + +<%-- --%> + + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/META-INF/MANIFEST.MF b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/META-INF/MANIFEST.MF new file mode 100755 index 0000000000..5e9495128c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/pushlet.properties b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/pushlet.properties new file mode 100755 index 0000000000..ba656e138f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/pushlet.properties @@ -0,0 +1,128 @@ +# +# Pushlet configuration. +# Place this file in the CLASSPATH (e.g. WEB-INF/classes) or directly under WEB-INF. +# +# $Id: pushlet.properties,v 1.13 2007/12/07 12:57:40 justb Exp $ +# + +# +# +# +config.version=1.0.2 + +# +# CLASS FACTORY SPECIFICATION +# +# Change these if you want to override any of the core classes +# within the Pushlet framework with your own custom classes. +# +# Examples: +# - custom SessionManager for authorisation +# - maintain lists of active subjects (topics) +# - send events on subscription +# - plug in custom logging like log4j +# Note that you must maintain the semantics of each class ! +# Below are the default properties for the core classes. +controller.class=nl.justobjects.pushlet.core.Controller +dispatcher.class=nl.justobjects.pushlet.core.Dispatcher +logger.class=nl.justobjects.pushlet.util.Log4jLogger +# logger.class=nl.justobjects.pushlet.util.DefaultLogger +sessionmanager.class=nl.justobjects.pushlet.core.SessionManager +session.class=nl.justobjects.pushlet.core.Session +subscriber.class=nl.justobjects.pushlet.core.Subscriber +subscription.class=nl.justobjects.pushlet.core.Subscription + +# sessionmanager.maxsessions=200 + +# +# DISPATCHER +# + + +# TODO: allow properties to be maintained in +# a user dir +# config.redirect=/etc/pushlet.properties + +# +# LOGGING +# + +# log level (trace(6) debug(5) info (4), warn(3), error(2), fatal(1)) +# default is info(4) +log.level=4 + +# +# LOCAL EVENT SOURCES +# + +# should local sources be loaded ? +sources.activate=true + +# +# SESSION +# + + +# algoritm to generate session key: +# values: "randomstring" (default) or "uuid". +# session.id.generation=uuid +session.id.generation=randomstring + +# length of generated session key when using "randomstring" generation +session.id.size=10 + +# Overall session lease time in minutes +# Mainly used for clients that do not perform +# listening, e.g. when publishing only. +session.timeout.mins=5 + +# +# EVENT QUEUE +# +# Properties for per-client data event queue + +# Size for +queue.size=24 +queue.read.timeout.millis=20000 +queue.write.timeout.millis=20 + +# +# LISTENING MODE +# + +# You may force all clients to use pull mode +# for scalability +listen.force.pull.all=false + +# +# Comma-separated list of User Agent substrings. +# Force these browsers to use pull mode, since they +# don't support JS streaming, matching is done using +# String.indexOf() with lowercased agent strings +# use multiple criteria with &. +# +listen.force.pull.agents=safari + +# +# PULL MODE +# + +# time server should wait on refresing pull client +pull.refresh.timeout.millis=45000 + +# minimum/maximum wait time client should wait before refreshing +# server provides a random time between these values +pull.refresh.wait.min.millis=2000 +pull.refresh.wait.max.millis=6000 + +# +# POLL MODE +# + +# time server should wait on refresing poll client +poll.refresh.timeout.millis=60000 + +# minimum/maximum wait time client should wait before refreshing +# server provides a random time between these values +poll.refresh.wait.min.millis=6000 +poll.refresh.wait.max.millis=10000 diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/sources.properties b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/sources.properties new file mode 100755 index 0000000000..e8aeb36a43 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/classes/sources.properties @@ -0,0 +1,28 @@ +# +# Properties file for EventSource objects to be instantiated. +# +# Place this file in the CLASSPATH (e.g. WEB-INF/classes) or directly under WEB-INF. +# +# $Id: sources.properties,v 1.2 2007/11/10 14:12:16 justb Exp $ +# +# Each EventSource is defined as = +# 1. should be unique within this file but may be any name +# 2. is the full class name +# +# +# Define Pull Sources here. These classes must be derived from +# nl.justobjects.pushlet.core.EventPullSource +# Inner classes are separated with a $ sign from the outer class. +#source1=nl.justobjects.pushlet.test.TestEventPullSources$TemperatureEventPullSource +#source2=nl.justobjects.pushlet.test.TestEventPullSources$SystemStatusEventPullSource +#source3=nl.justobjects.pushlet.test.TestEventPullSources$PushletStatusEventPullSource +#source4=nl.justobjects.pushlet.test.TestEventPullSources$AEXStocksEventPullSource +#source5=nl.justobjects.pushlet.test.TestEventPullSources$WebPresentationEventPullSource +#source6=nl.justobjects.pushlet.test.TestEventPullSources$PingEventPullSource + +source1=pow.webserver.Serveur$IvyEventSource + +# TO BE DONE IN NEXT VERSION +# define Push Sources here. These must implement the interface +# nl.justobjects.pushlet.core.EventSource + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-codec-1.4.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-codec-1.4.jar new file mode 100755 index 0000000000..458d432da8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-codec-1.4.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar new file mode 100755 index 0000000000..aa209b3887 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar new file mode 100755 index 0000000000..7c59774aed Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-io-1.4.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-io-1.4.jar new file mode 100755 index 0000000000..133dc6cb35 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-io-1.4.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar new file mode 100755 index 0000000000..8758a96b70 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/jdom.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/jdom.jar new file mode 100755 index 0000000000..65a1b3f737 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/jdom.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/log4j-1.2.16.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/log4j-1.2.16.jar new file mode 100755 index 0000000000..3f9d847618 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/log4j-1.2.16.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/mysql-connector-java-5.1.12-bin.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/mysql-connector-java-5.1.12-bin.jar new file mode 100755 index 0000000000..af5847eed4 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/mysql-connector-java-5.1.12-bin.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/pushlet.jar b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/pushlet.jar new file mode 100755 index 0000000000..6dc1c22e21 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/lib/pushlet.jar differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/web.xml b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/web.xml new file mode 100755 index 0000000000..16b18bbc06 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/WEB-INF/web.xml @@ -0,0 +1,54 @@ + + + ServletPow + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + + + Greeting + Greeting + pow.webserver.Greeting + + + Greeting + /Greeting.srv + + + + Pushlet + Pushlet + nl.justobjects.pushlet.servlet.Pushlet + 1 + + + Pushlet + /pushlet.srv + + + + Ivy2TomcatHttpServer + Ivy2TomcatHttpServer + pow.webserver.Ivy2TomcatHttpServer + 1 + + + Ivy2TomcatHttpServer + /Ivy2TomcatHttpServer.srv + + + + ajaxRqst + ajaxRqst + pow.webserver.AjaxRqst + + + ajaxRqst + /ajaxRqst.srv + + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/admin.jsp b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/admin.jsp new file mode 100755 index 0000000000..77c8c2fa9c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/admin.jsp @@ -0,0 +1,790 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@page import="java.util.*,pow.webserver.UserTab,pow.webserver.User,javax.xml.parsers.*, org.w3c.dom.*,org.xml.sax.*,java.io.*" %> +<% +// recuperation des données sur le serveur + String default_folder = this.getServletContext().getRealPath(""); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + Iterator itr=logTab.getLoginIterator(); + // + UserTab logIvyTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + Iterator itrIvy=logIvyTab.getLoginIterator(); + // lecture liste des noms de drones ds immat.xml + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + // création d'un constructeur de documents + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // lecture du contenu d'un fichier XML avec DOM + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + + +%> + + + + + + + +Administration page + + + + + + + + + + + + + + + +
+
+
+ +
+
+
Select an item + + + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + +
+
+
+
+
+ Add or Remove a name among drones which may be controlled by users + + + + + + +
+ +
+
+
+
+
+
+
+
+
+ Add or Remove an Ivy User + + + + + + +
+ +
+
+
+
+ + +
+ +
+
+ + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/immat.xml b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/immat.xml new file mode 100755 index 0000000000..42965d30c1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/immat.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/pow_conf.xml b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/pow_conf.xml new file mode 100755 index 0000000000..23600da6cd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/conf/pow_conf.xml @@ -0,0 +1,24 @@ + + + 8535 + 8536 + 1024 + 10000 + pow_sql + truesilentpow_user + pwdpow_user + admin + admin@pow.fr + + 1200000 + + 60000 + + +10000 + +5000 + +30000 + 30000 + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/help.jsp b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/help.jsp new file mode 100755 index 0000000000..cc8eedffa0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/help.jsp @@ -0,0 +1,58 @@ +<%@page import="pow.webserver.Conf" %> + + + + + + Welcome to Paparazzi On the Web + + + + + + + + + +

Welcome on Paparazzi On the Web help page.

+

This page is here to help you to use the Paparazzi On the Web (POW) application. POW is a part of Paparazzi which is a open-project of civil UAV control. With Paparazzi On the Web, you are able to observe and eventually control the UAVs of the system Paparazzi thanks to a browser with your internet connexion. To learn more about Paparazzi project, click here.

+

Paparazzi On the Web is optimised for Firefox browser. If you want to have a better performance, you can dowload Firefox here.

+

Start page

+

If you have a login and a password on Paparazzi On the Web, you can use them to enter the application. Else, click on enter as a guest.

+ +

Main page

+

You are now on Paparazzi On the Web main page. You can see several boxes. We will describe all those boxes and show you the interactions you can have with them.

+ +

Choose an aircraft

+

Here you can select the aircraft you want to observe or control. Click on the arrow to see the list of the aircrafts that are available. Click on the aircraft you want to interacte with.

+

You can also choose to activate or desactivate tracking. When tracking is activated, the map is always centered on the selected aircraft.

+ + + +

The map

+

On the map, you can see all the aircrafts that are available. If tracking is activated, the map will be centered on the selected aircraft. There are also red lozenges which are the waypoints of the selected UAV. If you are autentified on Paparazzi On the Web and if your profile gives you the authorization, you can move those waypoints with drag and drop.

+ +

The flight plan

+

Through this box, you can obtain some informations on the flight plan that is followed by the selected plane. If you move your cursor on the informations tab, you obtain informations on the flightplan. If you put your cursor on the "active block" tab, you can see the list of the flight plan blocks that the plane can follow. The active block is in red. If you are authentified and if you have the authorization, you can change the active block by clicking on its name. The waypoints tab gives you informations on the different waypoints. If you are authentified and if you have the authorization, you can move those waypoints by clicking on "move waypoint". In this case, a new windows is openned where you indicate where you want to move the waypoint. +You can also move a waypoint by dragging the icon on the map to its new position.

+ +

The flight parameters

+

This box displays the flight parameters of the selected aircraft. When a value is out of its normal range, it becomes red.

+ +

The settings

+

In this box you can, if you are allowed to control the selected aircraft, you change some settings of this aircraft by clicking on the name of the setting.

+ +

Any problem ?

+

If you have any display problem, such as a ghost aircraft icon, or an aircraft that is not displayed in the aircrafts list, you might resolve it by reloading the page by pressing F5 key. +For any other problem, please inform +<% +out.print("the administrator"); %>.

+Click here to return to the homepage. + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/idError.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/idError.html new file mode 100755 index 0000000000..a15edb3f6d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/idError.html @@ -0,0 +1,14 @@ + + + + + Welcome to Paparazzi On the Web + + + + + +

Sorry, an error occured during your identification. Click here to return on the homepage.

+ + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/base.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/base.gif new file mode 100755 index 0000000000..9ac0b117b0 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/base.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/cd.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/cd.gif new file mode 100755 index 0000000000..7503819404 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/cd.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/empty.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/empty.gif new file mode 100755 index 0000000000..b5cf52378f Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/empty.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folder.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folder.gif new file mode 100755 index 0000000000..eb129763dc Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folder.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folderopen.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folderopen.gif new file mode 100755 index 0000000000..c5c31102d5 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/folderopen.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/globe.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/globe.gif new file mode 100755 index 0000000000..57123d0e69 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/globe.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/imgfolder.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/imgfolder.gif new file mode 100755 index 0000000000..e6d880347f Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/imgfolder.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/join.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/join.gif new file mode 100755 index 0000000000..34dd47610a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/join.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/joinbottom.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/joinbottom.gif new file mode 100755 index 0000000000..48b81c80a9 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/joinbottom.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/line.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/line.gif new file mode 100755 index 0000000000..1a259eea00 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/line.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minus.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minus.gif new file mode 100755 index 0000000000..3d212a97ae Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minus.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minusbottom.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minusbottom.gif new file mode 100755 index 0000000000..dc3198be27 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/minusbottom.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/musicfolder.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/musicfolder.gif new file mode 100755 index 0000000000..f620789feb Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/musicfolder.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_minus.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_minus.gif new file mode 100755 index 0000000000..2592ac20f3 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_minus.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_plus.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_plus.gif new file mode 100755 index 0000000000..f258ce211a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/nolines_plus.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/page.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/page.gif new file mode 100755 index 0000000000..42d7318c5d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/page.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plus.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plus.gif new file mode 100755 index 0000000000..b2c997233b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plus.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plusbottom.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plusbottom.gif new file mode 100755 index 0000000000..b5671d891a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/plusbottom.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/question.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/question.gif new file mode 100755 index 0000000000..dd4e685078 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/question.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/trash.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/trash.gif new file mode 100755 index 0000000000..cfa0f000e1 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/img/trash.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/index.jsp b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/index.jsp new file mode 100755 index 0000000000..aad5c605b5 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/index.jsp @@ -0,0 +1,69 @@ + + + + + Welcome to Paparazzi On the Web + + + + + + + + + + + +

Welcome to Paparazzi On The Web !

+ +

+ +

+
+
+

Login :

+

Password :

+ +
+

+ + +
+

+
+

or

+ +

+

+ +
+

+help ? + + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/DOMImplementation.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/DOMImplementation.js new file mode 100755 index 0000000000..5e94107932 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/DOMImplementation.js @@ -0,0 +1,24 @@ +function DOMImplementation(sUrl, fCallback) { + var dom; + if(window.ActiveXObject) { + dom = new ActiveXObject("Microsoft.XMLDOM"); + dom.onreadystatechange = function() { + if(dom.readyState == 4) { + //alert("win "+sUrl+" loaded"); + fCallback(dom); + } + }; + } + else if(document.implementation && document.implementation.createDocument) { + dom = document.implementation.createDocument("", "", null); + dom.onload = function() { + //alert("other "+sUrl+" loaded"); + fCallback(dom); + } + } + else { + alert("Votre navigateur ne gère pas l'importation de fichiers XML"); + return; + } + dom.load(sUrl); +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/XHR_object.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/XHR_object.js new file mode 100755 index 0000000000..544a2b1a2e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/XHR_object.js @@ -0,0 +1,20 @@ +function getXMLHttpRequest() { + var xhr = null; + + if (window.XMLHttpRequest || window.ActiveXObject) { + if (window.ActiveXObject) { + try { + xhr = new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + xhr = new ActiveXObject("Microsoft.XMLHTTP"); + } + } else { + xhr = new XMLHttpRequest(); + } + } else { + alert("Votre navigateur ne supporte pas l'objet XMLHTTPRequest..."); + return null; + } + + return xhr; +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/browserdetect.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/browserdetect.js new file mode 100755 index 0000000000..1e0b64da62 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/browserdetect.js @@ -0,0 +1,97 @@ +// Browser Detect Lite v2.1.4 +// http://www.dithered.com/javascript/browser_detect/index.html +// modified by Chris Nott (chris@NOSPAMdithered.com - remove NOSPAM) + + +function BrowserDetectLite() { + var ua = navigator.userAgent.toLowerCase(); + + // browser name + this.isGecko = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1); + this.isMozilla = (this.isGecko && ua.indexOf('gecko/') + 14 == ua.length); + this.isNS = ( (this.isGecko) ? (ua.indexOf('netscape') != -1) : ( (ua.indexOf('mozilla') != -1) && (ua.indexOf('spoofer') == -1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('opera') == -1) && (ua.indexOf('webtv') == -1) && (ua.indexOf('hotjava') == -1) ) ); + this.isIE = ( (ua.indexOf('msie') != -1) && (ua.indexOf('opera') == -1) && (ua.indexOf('webtv') == -1) ); + this.isSafari = (ua.indexOf('safari') != - 1); + this.isOpera = (ua.indexOf('opera') != -1); + this.isKonqueror = (ua.indexOf('konqueror') != -1 && !this.isSafari); + this.isIcab = (ua.indexOf('icab') != -1); + this.isAol = (ua.indexOf('aol') != -1); + + // spoofing and compatible browsers + this.isIECompatible = ( (ua.indexOf('msie') != -1) && !this.isIE); + this.isNSCompatible = ( (ua.indexOf('mozilla') != -1) && !this.isNS && !this.isMozilla); + + // browser version + this.versionMinor = parseFloat(navigator.appVersion); + + // correct version number + if (this.isNS && this.isGecko) { + this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('/') + 1 ) ); + } + else if (this.isIE && this.versionMinor >= 4) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) ); + } + else if (this.isMozilla) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) ); + } + else if (this.isSafari) { + this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('/') + 1 ) ); + } + else if (this.isOpera) { + if (ua.indexOf('opera/') != -1) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera/') + 6 ) ); + } + else { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera ') + 6 ) ); + } + } + else if (this.isKonqueror) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('konqueror/') + 10 ) ); + } + else if (this.isIcab) { + if (ua.indexOf('icab/') != -1) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab/') + 6 ) ); + } + else { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab ') + 6 ) ); + } + } + + this.versionMajor = parseInt(this.versionMinor); + this.geckoVersion = ( (this.isGecko) ? ua.substring( (ua.lastIndexOf('gecko/') + 6), (ua.lastIndexOf('gecko/') + 14) ) : -1 ); + + // dom support + this.isDOM1 = (document.getElementById); + this.isDOM2Event = (document.addEventListener && document.removeEventListener); + + // css compatibility mode + this.mode = document.compatMode ? document.compatMode : 'BackCompat'; + + // platform + this.isWin = (ua.indexOf('win') != -1); + this.isWin32 = (this.isWin && ( ua.indexOf('95') != -1 || ua.indexOf('98') != -1 || ua.indexOf('nt') != -1 || ua.indexOf('win32') != -1 || ua.indexOf('32bit') != -1 || ua.indexOf('xp') != -1) ); + this.isMac = (ua.indexOf('mac') != -1); + this.isUnix = (ua.indexOf('unix') != -1 || ua.indexOf('sunos') != -1 || ua.indexOf('bsd') != -1 || ua.indexOf('x11') != -1) + this.isLinux = (ua.indexOf('linux') != -1); + + // specific browser shortcuts + this.isNS4x = (this.isNS && this.versionMajor == 4); + this.isNS40x = (this.isNS4x && this.versionMinor < 4.5); + this.isNS47x = (this.isNS4x && this.versionMinor >= 4.7); + this.isNS4up = (this.isNS && this.versionMinor >= 4); + this.isNS6x = (this.isNS && this.versionMajor == 6); + this.isNS6up = (this.isNS && this.versionMajor >= 6); + this.isNS7x = (this.isNS && this.versionMajor == 7); + this.isNS7up = (this.isNS && this.versionMajor >= 7); + + this.isIE4x = (this.isIE && this.versionMajor == 4); + this.isIE4up = (this.isIE && this.versionMajor >= 4); + this.isIE5x = (this.isIE && this.versionMajor == 5); + this.isIE55 = (this.isIE && this.versionMinor == 5.5); + this.isIE5up = (this.isIE && this.versionMajor >= 5); + this.isIE6x = (this.isIE && this.versionMajor == 6); + this.isIE6up = (this.isIE && this.versionMajor >= 6); + + this.isIE4xMac = (this.isIE4x && this.isMac); +} +var browser = new BrowserDetectLite(); diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/curvycorners.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/curvycorners.js new file mode 100755 index 0000000000..511c78dd9d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/curvycorners.js @@ -0,0 +1 @@ +function browserdetect(){var A=navigator.userAgent.toLowerCase();this.isIE=A.indexOf("msie")>-1;this.ieVer=this.isIE?/msie\s(\d\.\d)/.exec(A)[1]:0;this.isMoz=A.indexOf("firefox")!=-1;this.isSafari=A.indexOf("safari")!=-1;this.quirksMode=this.isIE&&(!document.compatMode||document.compatMode.indexOf("BackCompat")>-1);this.isOp="opera" in window;this.isWebKit=A.indexOf("webkit")!=-1;if(this.isIE){this.get_style=function(D,F){if(!(F in D.currentStyle)){return""}var C=/^([\d.]+)(\w*)/.exec(D.currentStyle[F]);if(!C){return D.currentStyle[F]}if(C[1]==0){return"0"}if(C[2]&&C[2]!=="px"){var B=D.style.left;var E=D.runtimeStyle.left;D.runtimeStyle.left=D.currentStyle.left;D.style.left=C[1]+C[2];C[0]=D.style.pixelLeft;D.style.left=B;D.runtimeStyle.left=E}return C[0]}}else{this.get_style=function(B,C){C=C.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();return document.defaultView.getComputedStyle(B,"").getPropertyValue(C)}}}var curvyBrowser=new browserdetect;if(curvyBrowser.isIE){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}function curvyCnrSpec(A){this.selectorText=A;this.tlR=this.trR=this.blR=this.brR=0;this.tlu=this.tru=this.blu=this.bru="";this.antiAlias=true}curvyCnrSpec.prototype.setcorner=function(B,C,A,D){if(!B){this.tlR=this.trR=this.blR=this.brR=parseInt(A);this.tlu=this.tru=this.blu=this.bru=D}else{propname=B.charAt(0)+C.charAt(0);this[propname+"R"]=parseInt(A);this[propname+"u"]=D}};curvyCnrSpec.prototype.get=function(D){if(/^(t|b)(l|r)(R|u)$/.test(D)){return this[D]}if(/^(t|b)(l|r)Ru$/.test(D)){var C=D.charAt(0)+D.charAt(1);return this[C+"R"]+this[C+"u"]}if(/^(t|b)Ru?$/.test(D)){var B=D.charAt(0);B+=this[B+"lR"]>this[B+"rR"]?"l":"r";var A=this[B+"R"];if(D.length===3&&D.charAt(2)==="u"){A+=this[B="u"]}return A}throw new Error("Don't recognize property "+D)};curvyCnrSpec.prototype.radiusdiff=function(A){if(A!=="t"&&A!=="b"){throw new Error("Param must be 't' or 'b'")}return Math.abs(this[A+"lR"]-this[A+"rR"])};curvyCnrSpec.prototype.setfrom=function(A){this.tlu=this.tru=this.blu=this.bru="px";if("tl" in A){this.tlR=A.tl.radius}if("tr" in A){this.trR=A.tr.radius}if("bl" in A){this.blR=A.bl.radius}if("br" in A){this.brR=A.br.radius}if("antiAlias" in A){this.antiAlias=A.antiAlias}};curvyCnrSpec.prototype.cloneOn=function(G){var E=["tl","tr","bl","br"];var H=0;var C,A;for(C in E){if(!isNaN(C)){A=this[E[C]+"u"];if(A!==""&&A!=="px"){H=new curvyCnrSpec;break}}}if(!H){H=this}else{var B,D,F=curvyBrowser.get_style(G,"left");for(C in E){if(!isNaN(C)){B=E[C];A=this[B+"u"];D=this[B+"R"];if(A!=="px"){var F=G.style.left;G.style.left=D+A;D=G.style.pixelLeft;G.style.left=F}H[B+"R"]=D;H[B+"u"]="px"}}G.style.left=F}return H};curvyCnrSpec.prototype.radiusSum=function(A){if(A!=="t"&&A!=="b"){throw new Error("Param must be 't' or 'b'")}return this[A+"lR"]+this[A+"rR"]};curvyCnrSpec.prototype.radiusCount=function(A){var B=0;if(this[A+"lR"]){++B}if(this[A+"rR"]){++B}return B};curvyCnrSpec.prototype.cornerNames=function(){var A=[];if(this.tlR){A.push("tl")}if(this.trR){A.push("tr")}if(this.blR){A.push("bl")}if(this.brR){A.push("br")}return A};function operasheet(C){var A=document.styleSheets.item(C).ownerNode.text;A=A.replace(/\/\*(\n|\r|.)*?\*\//g,"");var D=new RegExp("^s*([\\w.#][-\\w.#, ]+)[\\n\\s]*\\{([^}]+border-((top|bottom)-(left|right)-)?radius[^}]*)\\}","mg");var G;this.rules=[];while((G=D.exec(A))!==null){var F=new RegExp("(..)border-((top|bottom)-(left|right)-)?radius:\\s*([\\d.]+)(in|em|px|ex|pt)","g");var E,B=new curvyCnrSpec(G[1]);while((E=F.exec(G[2]))!==null){if(E[1]!=="z-"){B.setcorner(E[3],E[4],E[5],E[6])}}this.rules.push(B)}}operasheet.contains_border_radius=function(A){return/border-((top|bottom)-(left|right)-)?radius/.test(document.styleSheets.item(A).ownerNode.text)};function curvyCorners(){var G,D,E,B,J;if(typeof arguments[0]!=="object"){throw curvyCorners.newError("First parameter of curvyCorners() must be an object.")}if(arguments[0] instanceof curvyCnrSpec){B=arguments[0];if(!B.selectorText&&typeof arguments[1]==="string"){B.selectorText=arguments[1]}}else{if(typeof arguments[1]!=="object"&&typeof arguments[1]!=="string"){throw curvyCorners.newError("Second parameter of curvyCorners() must be an object or a class name.")}D=arguments[1];if(typeof D!=="string"){D=""}if(D!==""&&D.charAt(0)!=="."&&"autoPad" in arguments[0]){D="."+D}B=new curvyCnrSpec(D);B.setfrom(arguments[0])}if(B.selectorText){J=0;var I=B.selectorText.replace(/\s+$/,"").split(/,\s*/);E=new Array;function A(M){var L=M.split("#");return(L.length===2?"#":"")+L.pop()}for(G=0;G7?curvyBrowser.get_style(this.box,"filter"):null;var H=this.spec.get("tR");var M=this.spec.get("bR");var W=function(f){if(typeof f==="number"){return f}if(typeof f!=="string"){throw new Error("unexpected styleToNPx type "+typeof f)}var d=/^[-\d.]([a-z]+)$/.exec(f);if(d&&d[1]!="px"){throw new Error("Unexpected unit "+d[1])}if(isNaN(f=parseInt(f))){f=0}return f};var T=function(d){return d<=0?"0":d+"px"};try{this.borderWidth=W(b);this.borderWidthB=W(J);this.borderWidthL=W(D);this.borderWidthR=W(B);this.boxColour=curvyObject.format_colour(E);this.topPadding=W(Z);this.bottomPadding=W(c);this.leftPadding=W(Q);this.rightPadding=W(a);this.boxWidth=K;this.boxHeight=this.box.clientHeight;this.borderColour=curvyObject.format_colour(I);this.borderColourB=curvyObject.format_colour(G);this.borderColourL=curvyObject.format_colour(A);this.borderString=this.borderWidth+"px solid "+this.borderColour;this.borderStringB=this.borderWidthB+"px solid "+this.borderColourB;this.backgroundImage=((C!="none")?C:"");this.backgroundRepeat=Y}catch(X){throw this.newError("getMessage" in X?X.getMessage():X.message)}var F=this.boxHeight;var V=K;if(curvyBrowser.isOp){R=W(R);P=W(P);if(R){var N=V+this.borderWidthL+this.borderWidthR;if(R>N){R=N}R=(N/R*100)+"%"}if(P){var N=F+this.borderWidth+this.borderWidthB;if(P>N){P=N}P=(N/P*100)+"%"}}if(curvyBrowser.quirksMode){}else{this.boxWidth-=this.leftPadding+this.rightPadding;this.boxHeight-=this.topPadding+this.bottomPadding}this.contentContainer=document.createElement("div");if(filter){this.contentContainer.style.filter=filter}while(this.box.firstChild){this.contentContainer.appendChild(this.box.removeChild(this.box.firstChild))}if(O!="absolute"){this.box.style.position="relative"}this.box.style.padding="0";this.box.style.border=this.box.style.backgroundImage="none";this.box.style.backgroundColor="transparent";this.box.style.width=(V+this.borderWidthL+this.borderWidthR)+"px";this.box.style.height=(F+this.borderWidth+this.borderWidthB)+"px";var L=document.createElement("div");L.style.position="absolute";if(filter){L.style.filter=filter}if(curvyBrowser.quirksMode){L.style.width=(V+this.borderWidthL+this.borderWidthR)+"px"}else{L.style.width=V+"px"}L.style.height=T(F+this.borderWidth+this.borderWidthB-H-M);L.style.padding="0";L.style.top=H+"px";L.style.left="0";if(this.borderWidthL){L.style.borderLeft=this.borderWidthL+"px solid "+this.borderColourL}if(this.borderWidth&&!H){L.style.borderTop=this.borderWidth+"px solid "+this.borderColour}if(this.borderWidthR){L.style.borderRight=this.borderWidthR+"px solid "+this.borderColourL}if(this.borderWidthB&&!M){L.style.borderBottom=this.borderWidthB+"px solid "+this.borderColourB}L.style.backgroundColor=E;L.style.backgroundImage=this.backgroundImage;L.style.backgroundRepeat=this.backgroundRepeat;this.shell=this.box.appendChild(L);K=curvyBrowser.get_style(this.shell,"width");if(K===""||K==="auto"||K.indexOf("%")!==-1){throw this.newError("Shell width is "+K)}this.boxWidth=(K!=""&&K!="auto"&&K.indexOf("%")==-1)?parseInt(K):this.shell.clientWidth;this.applyCorners=function(){if(this.backgroundObject){var w=function(AO,i,t){if(AO===0){return 0}var k;if(AO==="right"||AO==="bottom"){return t-i}if(AO==="center"){return(t-i)/2}if(AO.indexOf("%")>0){return(t-i)*100/parseInt(AO)}return W(AO)};this.backgroundPosX=w(R,this.backgroundObject.width,V);this.backgroundPosY=w(P,this.backgroundObject.height,F)}else{if(this.backgroundImage){this.backgroundPosX=W(R);this.backgroundPosY=W(P)}}if(H){v=document.createElement("div");v.style.width=this.boxWidth+"px";v.style.fontSize="1px";v.style.overflow="hidden";v.style.position="absolute";v.style.paddingLeft=this.borderWidth+"px";v.style.paddingRight=this.borderWidth+"px";v.style.height=H+"px";v.style.top=-H+"px";v.style.left=-this.borderWidthL+"px";this.topContainer=this.shell.appendChild(v)}if(M){var v=document.createElement("div");v.style.width=this.boxWidth+"px";v.style.fontSize="1px";v.style.overflow="hidden";v.style.position="absolute";v.style.paddingLeft=this.borderWidthB+"px";v.style.paddingRight=this.borderWidthB+"px";v.style.height=M+"px";v.style.bottom=-M+"px";v.style.left=-this.borderWidthL+"px";this.bottomContainer=this.shell.appendChild(v)}var AG=this.spec.cornerNames();for(var AK in AG){if(!isNaN(AK)){var AC=AG[AK];var AD=this.spec[AC+"R"];var AE,AH,j,AF;if(AC=="tr"||AC=="tl"){AE=this.borderWidth;AH=this.borderColour;AF=this.borderWidth}else{AE=this.borderWidthB;AH=this.borderColourB;AF=this.borderWidthB}j=AD-AF;var u=document.createElement("div");u.style.height=this.spec.get(AC+"Ru");u.style.width=this.spec.get(AC+"Ru");u.style.position="absolute";u.style.fontSize="1px";u.style.overflow="hidden";var r,q,p;var n=filter?parseInt(/alpha\(opacity.(\d+)\)/.exec(filter)[1]):100;for(r=0;r=j)?-1:Math.floor(Math.sqrt(Math.pow(j,2)-Math.pow(r+1,2)))-1;if(j!=AD){var h=(r>=j)?-1:Math.ceil(Math.sqrt(Math.pow(j,2)-Math.pow(r,2)));var f=(r+1>=AD)?-1:Math.floor(Math.sqrt(Math.pow(AD,2)-Math.pow((r+1),2)))-1}var d=(r>=AD)?-1:Math.ceil(Math.sqrt(Math.pow(AD,2)-Math.pow(r,2)));if(m>-1){this.drawPixel(r,0,this.boxColour,n,(m+1),u,true,AD)}if(j!=AD){if(this.spec.antiAlias){for(q=m+1;q=30,AD)}else{if(this.boxColour!=="transparent"){var AB=curvyObject.BlendColour(this.boxColour,AH,curvyObject.pixelFraction(r,q,j));this.drawPixel(r,q,AB,n,1,u,false,AD)}else{this.drawPixel(r,q,AH,n>>1,1,u,false,AD)}}}if(f>=h){if(h==-1){h=0}this.drawPixel(r,h,AH,n,(f-h+1),u,false,0)}p=AH;q=f}else{if(f>m){this.drawPixel(r,(m+1),AH,n,(f-m),u,false,0)}}}else{p=this.boxColour;q=m}if(this.spec.antiAlias){while(++q>>4]+""+A[B&15]};curvyObject.BlendColour=function(L,J,G){if(L==="transparent"||J==="transparent"){throw this.newError("Cannot blend with transparent")}if(L.charAt(0)!=="#"){L=curvyObject.format_colour(L)}if(J.charAt(0)!=="#"){J=curvyObject.format_colour(J)}var D=parseInt(L.substr(1,2),16);var K=parseInt(L.substr(3,2),16);var F=parseInt(L.substr(5,2),16);var C=parseInt(J.substr(1,2),16);var I=parseInt(J.substr(3,2),16);var E=parseInt(J.substr(5,2),16);if(G>1||G<0){G=1}var H=Math.round((D*G)+(C*(1-G)));if(H>255){H=255}if(H<0){H=0}var B=Math.round((K*G)+(I*(1-G)));if(B>255){B=255}if(B<0){B=0}var A=Math.round((F*G)+(E*(1-G)));if(A>255){A=255}if(A<0){A=0}return"#"+curvyObject.IntToHex(H)+curvyObject.IntToHex(B)+curvyObject.IntToHex(A)};curvyObject.pixelFraction=function(H,G,A){var J;var E=A*A;var B=new Array(2);var F=new Array(2);var I=0;var C="";var D=Math.sqrt(E-Math.pow(H,2));if(D>=G&&D<(G+1)){C="Left";B[I]=0;F[I]=D-G;++I}D=Math.sqrt(E-Math.pow(G+1,2));if(D>=H&&D<(H+1)){C+="Top";B[I]=D-H;F[I]=1;++I}D=Math.sqrt(E-Math.pow(H+1,2));if(D>=G&&D<(G+1)){C+="Right";B[I]=1;F[I]=D-G;++I}D=Math.sqrt(E-Math.pow(G,2));if(D>=H&&D<(H+1)){C+="Bottom";B[I]=D-H;F[I]=0}switch(C){case"LeftRight":J=Math.min(F[0],F[1])+((Math.max(F[0],F[1])-Math.min(F[0],F[1]))/2);break;case"TopRight":J=1-(((1-B[0])*(1-F[1]))/2);break;case"TopBottom":J=Math.min(B[0],B[1])+((Math.max(B[0],B[1])-Math.min(B[0],B[1]))/2);break;case"LeftBottom":J=F[0]*B[1]/2;break;default:J=1}return J};curvyObject.rgb2Array=function(A){var B=A.substring(4,A.indexOf(")"));return B.split(", ")};curvyObject.rgb2Hex=function(B){try{var C=curvyObject.rgb2Array(B);var G=parseInt(C[0]);var E=parseInt(C[1]);var A=parseInt(C[2]);var D="#"+curvyObject.IntToHex(G)+curvyObject.IntToHex(E)+curvyObject.IntToHex(A)}catch(F){var H="getMessage" in F?F.getMessage():F.message;throw new Error("Error ("+H+") converting RGB value to Hex in rgb2Hex")}return D};curvyObject.setOpacity=function(F,C){C=(C==100)?99.999:C;if(curvyBrowser.isSafari&&F.tagName!="IFRAME"){var B=curvyObject.rgb2Array(F.style.backgroundColor);var E=parseInt(B[0]);var D=parseInt(B[1]);var A=parseInt(B[2]);F.style.backgroundColor="rgba("+E+", "+D+", "+A+", "+C/100+")"}else{if(typeof F.style.opacity!=="undefined"){F.style.opacity=C/100}else{if(typeof F.style.MozOpacity!=="undefined"){F.style.MozOpacity=C/100}else{if(typeof F.style.filter!="undefined"){F.style.filter="alpha(opacity="+C+")"}else{if(typeof F.style.KHTMLOpacity!="undefined"){F.style.KHTMLOpacity=C/100}}}}}};function addEvent(D,C,B,A){if(D.addEventListener){D.addEventListener(C,B,A);return true}if(D.attachEvent){return D.attachEvent("on"+C,B)}D["on"+C]=B;return false}curvyObject.getComputedColour=function(E){var F=document.createElement("DIV");F.style.backgroundColor=E;document.body.appendChild(F);if(window.getComputedStyle){var D=document.defaultView.getComputedStyle(F,null).getPropertyValue("background-color");F.parentNode.removeChild(F);if(D.substr(0,3)==="rgb"){D=curvyObject.rgb2Hex(D)}return D}else{var A=document.body.createTextRange();A.moveToElementText(F);A.execCommand("ForeColor",false,E);var B=A.queryCommandValue("ForeColor");var C="rgb("+(B&255)+", "+((B&65280)>>8)+", "+((B&16711680)>>16)+")";F.parentNode.removeChild(F);A=null;return curvyObject.rgb2Hex(C)}};curvyObject.format_colour=function(A){if(A!=""&&A!="transparent"){if(A.substr(0,3)==="rgb"){A=curvyObject.rgb2Hex(A)}else{if(A.charAt(0)!=="#"){A=curvyObject.getComputedColour(A)}else{if(A.length===4){A="#"+A.charAt(1)+A.charAt(1)+A.charAt(2)+A.charAt(2)+A.charAt(3)+A.charAt(3)}}}}return A};curvyCorners.getElementsByClass=function(H,F){var E=new Array;if(F===undefined){F=document}H=H.split(".");var A="*";if(H.length===1){A=H[0];H=false}else{if(H[0]){A=H[0]}H=H[1]}var D,C,B;if(A.charAt(0)==="#"){C=document.getElementById(A.substr(1));if(C){E.push(C)}}else{C=F.getElementsByTagName(A);B=C.length;if(H){var G=new RegExp("(^|\\s)"+H+"(\\s|$)");for(D=0;D6){var H=J["-webkit-border-radius"]||0;var K=J["-webkit-border-top-right-radius"]||0;var F=J["-webkit-border-top-left-radius"]||0;var G=J["-webkit-border-bottom-right-radius"]||0;var M=J["-webkit-border-bottom-left-radius"]||0}else{var H=J["webkit-border-radius"]||0;var K=J["webkit-border-top-right-radius"]||0;var F=J["webkit-border-top-left-radius"]||0;var G=J["webkit-border-bottom-right-radius"]||0;var M=J["webkit-border-bottom-left-radius"]||0}if(H||F||K||G||M){var I=new curvyCnrSpec(L.selectorText);if(H){I.setcorner(null,null,parseInt(H),B(H))}else{if(K){I.setcorner("t","r",parseInt(K),B(K))}if(F){I.setcorner("t","l",parseInt(F),B(F))}if(M){I.setcorner("b","l",parseInt(M),B(M))}if(G){I.setcorner("b","r",parseInt(G),B(G))}}curvyCorners(I)}}for(E=0;E'; + } + if (node.url) { + str += ''; + str += node.name; + if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += ''; + str += ''; + if (node._hc) { + str += '
'; + str += this.addNode(node); + str += '
'; + } + this.aIndent.pop(); + return str; +}; + +// Adds the empty and line icons +dTree.prototype.indent = function(node, nodeId) { + var str = ''; + if (this.root.id != node.pid) { + for (var n=0; n'; + (node._ls) ? this.aIndent.push(0) : this.aIndent.push(1); + if (node._hc) { + str += ''; + } else str += ''; + } + return str; +}; + +// Checks if a node has any children and if it is the last sibling +dTree.prototype.setCS = function(node) { + var lastId; + for (var n=0; n)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/jquery-ui-1.8.2.custom.min.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/jquery-ui-1.8.2.custom.min.js new file mode 100755 index 0000000000..c11e844f9b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/jquery-ui-1.8.2.custom.min.js @@ -0,0 +1,1012 @@ +/*! + * jQuery UI 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + */ +(function(c){c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.2",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=0)&&c(a).is(":focusable")}})}})(jQuery); +;/*! + * jQuery UI Widget 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Widget + */ +(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype= +b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g= +b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create(); +this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f, +h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a= +b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery); +;/*! + * jQuery UI Mouse 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&& +this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault(); +return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&& +this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX- +a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Position + */ +(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h= +0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+= +g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k, +elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"? +-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position= +"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top- +this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions(); +d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis|| +this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element, +b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this== +a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]|| +0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top- +(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment== +"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&& +a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"), +10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft(): +f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.leftthis.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?e:!(e-this.offset.click.left').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options; +if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!= +"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>=i&& +e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()}; +if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(), +e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset= +this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio: +this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize", +b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height; +g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop", +b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top= +a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidthb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height, +l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+ +a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this, +arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable, +{version:"1.8.2"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)}); +else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&& +d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a= +d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset; +var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left: +a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top- +e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition, +g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b= +d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height= +e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +; +/* + * jQuery UI Selectable 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function($) { + +$.widget("ui.selectable", $.ui.mouse, { + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' + }, + _create: function() { + var self = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(self.options.filter, self.element[0]); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("
"); + }, + + destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled") + .removeData("selectable") + .unbind(".selectable"); + this._mouseDestroy(); + + return this; + }, + + _mouseStart: function(event) { + var self = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "z-index": 100, + "position": "absolute", + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + self._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var self = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == self.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if (event.metaKey && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var self = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + self._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + self._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +$.extend($.ui.selectable, { + version: "1.8.2" +}); + +})(jQuery); +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting"); +b.unselecting=true;f._trigger("unselecting",c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f= +this;this.dragged=true;if(!this.options.disabled){var d=this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this, +arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem= +c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset, +{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment(); +if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start", +a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute"); +if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a, +c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]== +document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate", +null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem): +d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c}, +_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a= +this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)? +h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"), +b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)? +i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement, +c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height= +this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()- +parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0], +this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b= +1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update", +g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity", +this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset"); +this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role", +"tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a= +this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion"); +this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height", +"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target}, +a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0, +b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d= +this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected); +a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]), +toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j, +duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion, +{version:"1.8.2",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0], +h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"}, +a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,c=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(d){var b=e.ui.keyCode;switch(d.keyCode){case b.PAGE_UP:a._move("previousPage",d);break;case b.PAGE_DOWN:a._move("nextPage",d);break;case b.UP:a._move("previous",d);d.preventDefault(); +break;case b.DOWN:a._move("next",d);d.preventDefault();break;case b.ENTER:case b.NUMPAD_ENTER:a.menu.active&&d.preventDefault();case b.TAB:if(!a.menu.active)return;a.menu.select(d);break;case b.ESCAPE:a.element.val(a.term);a.close(d);break;case b.LEFT:case b.RIGHT:case b.SHIFT:case b.CONTROL:case b.ALT:case b.COMMAND:case b.COMMAND_RIGHT:case b.INSERT:case b.CAPS_LOCK:case b.END:case b.HOME:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,d)},a.options.delay); +break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete",function(d){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(d);a._change(d)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("
    ").addClass("ui-autocomplete").appendTo("body",c).mousedown(function(){setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(d,b){b=b.item.data("item.autocomplete"); +false!==a._trigger("focus",null,{item:b})&&/^key/.test(d.originalEvent.type)&&a.element.val(b.value)},selected:function(d,b){b=b.item.data("item.autocomplete");false!==a._trigger("select",d,{item:b})&&a.element.val(b.value);a.close(d);d=a.previous;if(a.element[0]!==c.activeElement){a.element.focus();a.previous=d}a.selectedItem=b},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()}, +destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,c;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(d,b){b(e.ui.autocomplete.filter(a,d.term))}}else if(typeof this.options.source=== +"string"){c=this.options.source;this.source=function(d,b){e.getJSON(c,d,b)}}else this.source=this.options.source},search:function(a,c){a=a!=null?a:this.element.val();if(a.length").data("item.autocomplete", +c).append(""+c.label+"").appendTo(a)},_move:function(a,c){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](c);else this.search(null,c)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,c){var d=new RegExp(e.ui.autocomplete.escapeRegex(c), +"i");return e.grep(a,function(b){return d.test(b.label||b.value||b)})}})})(jQuery); +(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(e(c.target).closest(".ui-menu-item a").length){c.preventDefault();a.select(c)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(c){a.activate(c,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,c){this.deactivate();if(this.hasScroll()){var d=c.offset().top-this.element.offset().top,b=this.element.attr("scrollTop"),f=this.element.height();if(d<0)this.element.attr("scrollTop",b+d);else d>f&&this.element.attr("scrollTop",b+d-f+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,c,d){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(d,a):this.activate(d,this.element.children(c))}else this.activate(d,this.element.children(c))},nextPage:function(a){if(this.hasScroll())if(!this.active|| +this.last())this.activate(a,this.element.children(":first"));else{var c=this.active.offset().top,d=this.element.height(),b=this.element.children("li").filter(function(){var f=e(this).offset().top-c-d+e(this).height();return f<10&&f>-10});b.length||(b=this.element.children(":last"));this.activate(a,b)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last")); +else{var c=this.active.offset().top,d=this.element.height();result=this.element.children("li").filter(function(){var b=e(this).offset().top-c+d-e(this).height();return b<10&&b>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()
    ").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("");d.secondary&&b.append("");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon"); +this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()}, +destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
    ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
    ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index", +c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("
    ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a, +function(g,f){g=c('').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging"); +b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position"); +a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop", +f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]= +g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a, +b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break; +case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title", +d.uiDialogTitlebar).html(""+(b||" "));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight", +this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.2",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&& +c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("
    ").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&& +b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight, +document.body.offsetHeight);return a");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("
    ");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("").appendTo(this.element).addClass("ui-slider-handle"); +if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur(); +else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e= +false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");g=a._start(c,f);if(g===false)return}break}i=a.options.step;g=a.options.values&&a.options.values.length?(h=a.values(f)):(h=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(g+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(g-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g=== +a._valueMax())return;h=a._trimAlignValue(g+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===a._valueMin())return;h=a._trimAlignValue(g-i);break}a._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"); +this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,g,h,i;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:a.pageX,y:a.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(b.range===true&&this.values(1)===b.min){i+=1;g=d(this.handles[i])}if(this._start(a, +i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();b=g.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-g.width()/2,top:a.pageY-b.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(a,i,e);return this._animateOff=true},_mouseStart:function(){return true}, +_mouseDrag:function(a){var b=this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b; +if(this.orientation==="horizontal"){b=this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value= +this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;fthis._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({width:f- +h+"%"},{queue:false,duration:b.animate})}else{if(l===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:b.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.2"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d){function s(){return++u}function v(){return++w}var u=0,w=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
    ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:'
  • #{label}
  • '},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+s()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+v());return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c= +d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]|| +(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass": +"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs", +function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show", +null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs", +function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g, +j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs", +function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this, +"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs", +true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide"); +this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1=c?--h:h});this._tabify();this._trigger("remove", +null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this}, +select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing"); +if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}}, +abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.2"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate= +function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k')}function E(a,b){d.extend(a, +b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.2"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]= +f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('
    ')}}, +_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&& +b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f== +""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a, +c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b), +true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor== +Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]); +d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}}, +_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false; +for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target|| +a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a); +d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&& +d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f, +h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover"); +this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover"); +this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"); +a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(), +k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"]; +a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val(): +"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&& +!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth; +b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]); +a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a, +"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")|| +this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null; +for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c, +k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c? +c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+112?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear|| +a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m, +g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+r+"":f?"":''+r+"";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
    '+(c?h:"")+(this._isInRange(a,r)?'":"")+(c?"":h)+"
    ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='
    '+(/all|left/.test(t)&&C==0?c? +f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'
    ';var A=k?'":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="=5?' class="ui-datepicker-week-end"':"")+'>'+s[q]+""}x+=A+"";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N";var O=!k?"":'";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&qo;O+='";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+""}g++;if(g>11){g=0;m++}x+="
    '+this._get(a,"weekHeader")+"
    '+this._get(a,"calculateWeek")(q)+""+(B&&!w?" ":I?''+q.getDate()+ +"":''+q.getDate()+"")+"
    "+(l?""+(i[0]>0&&D==i[1]-1?'
    ':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='
    ',o="";if(h||!k)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(j+=o+(h||!(k&&l)?" ":""));if(h||!l)j+=''+c+"";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b, +i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?" ":"")+o;j+="
    ";return j},_adjustInstDate:function(a,b,c){var e= +a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a, +"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a); +c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a, +"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker= +function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); +return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.2";window["DP_jQuery_"+y]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("
    ").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(athis._valueMax())a=this._valueMax();return a}, +_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.2"})})(jQuery); +;/* + * jQuery UI Effects 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit= +true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189, +183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255, +165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u, +i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a? +f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.2",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); +c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| +typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this, +arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c, +a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+ +b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2, +10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)* +a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* +f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/menu1.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/menu1.js new file mode 100755 index 0000000000..5f87f66421 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/menu1.js @@ -0,0 +1,155 @@ +/* +Author : bieler batiste +Company : doSimple : http://www.dosimple.ch +send me a mail for more informations : faden@PASDEPOURRIELaltern.org - remove ( PASDEPOURRIEL ) + +Short javascript function to create and handle a CSS navigation menu + +Copyright (C) 2004 Bieler Batiste + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// the timeout for the menu +var timeout = 100; + +// not very clean but simple +// the function can be run in the HTML for faster display +// window.onload=initMenu; + +// creat timeout variables for list item +// it's for avoid some warning with IE +for( var i = 0; i < 100; i++ ) +{ + eval("var timeoutli" + i + " = false;"); +} + +// this fonction apply the CSS style and the event +function initMenu() +{ + // a test to avoid some browser like IE4, Opera 6, and IE Mac + if ( browser.isDOM1 + && !( browser.isMac && browser.isIE ) + && !( browser.isOpera && browser.versionMajor < 7 ) + && !( browser.isIE && browser.versionMajor < 5 ) ) + { + // get some element + var menu = document.getElementById('menu'); // the root element + var lis = menu.getElementsByTagName('li'); // all the li + + // change the class name of the menu, + // it's usefull for compatibility with old browser + menu.className='menu'; + // i am searching for ul element in li element + for ( var i=0; i 0 ) + { + // improve IE key navigation + if ( browser.isIE ) + { + addAnEvent(lis.item(i),'keyup',show); + } + // link events to list item + addAnEvent(lis.item(i),'mouseover',show); + addAnEvent(lis.item(i),'mouseout',timeoutHide); + addAnEvent(lis.item(i),'blur',timeoutHide); + addAnEvent(lis.item(i),'focus',show); + + // add an id to list item + lis.item(i).setAttribute( 'id', "li"+i ); + } + } + } +} + + + + +function addAnEvent( target, eventName, functionName ) +{ + // apply the method to IE + if ( browser.isIE ) + { + //attachEvent dont work properly with this + eval('target.on'+eventName+'=functionName'); + } + // apply the method to DOM compliant browsers + else + { + target.addEventListener( eventName , functionName , true ); // true is important for Opera7 + } +} + +// hide the first ul element of the current element +function timeoutHide() +{ + // start the timeout + eval( "timeout" + this.id + " = window.setTimeout('hideUlUnder( \"" + this.id + "\" )', " + timeout + " );"); +} + +// hide the ul elements under the element identified by id +function hideUlUnder( id ) +{ + document.getElementById(id).getElementsByTagName('ul')[0].style['visibility'] = 'hidden'; +} + +// show the first ul element found under this element +function show() +{ + // show the sub menu + this.getElementsByTagName('ul')[0].style['visibility'] = 'visible'; + var currentNode=this; + while(currentNode) + { + if( currentNode.nodeName=='LI') + { + // currentNode.getElementsByTagName('a')[0].className = 'linkOver'; + } + currentNode=currentNode.parentNode; + } + // clear the timeout + eval ( "clearTimeout( timeout"+ this.id +");" ); + hideAllOthersUls( this ); +} + +// hide all ul on the same level of this list item +function hideAllOthersUls( currentLi ) +{ + var lis = currentLi.parentNode; + for ( var i=0; i 0 ) + { + if ( browser.isIE ) + { + addAnEvent(lis2.item(i),'keyup',show); + } + + addAnEvent(lis2.item(i),'mouseover',show); + addAnEvent(lis2.item(i),'mouseout',timeoutHide); + addAnEvent(lis2.item(i),'blur',timeoutHide); + addAnEvent(lis2.item(i),'focus',show); + + lis2.item(i).setAttribute( 'id', "li2"+i ); + } + } + } +} + + + +function addAnEvent( target, eventName, functionName ) +{ + if ( browser.isIE ) + { + eval('target.on'+eventName+'=functionName'); + } + else + { + target.addEventListener( eventName , functionName , true ); + } +} + +function timeoutHide() +{ + eval( "timeout" + this.id + " = window.setTimeout('hideUlUnder( \"" + this.id + "\" )', " + timeout + " );"); +} + +// hide the ul elements under the element identified by id +function hideUlUnder( id ) +{ + document.getElementById(id).getElementsByTagName('ul')[0].style['visibility'] = 'hidden'; +} + +// show the first ul element found under this element +function show() +{ + // show the sub menu + this.getElementsByTagName('ul')[0].style['visibility'] = 'visible'; + var currentNode=this; + while(currentNode) + { + if( currentNode.nodeName=='LI') + { + // currentNode.getElementsByTagName('a')[0].className = 'linkOver'; + } + currentNode=currentNode.parentNode; + } + // clear the timeout + eval ( "clearTimeout( timeout"+ this.id +");" ); + hideAllOthersUls( this ); +} + +// hide all ul on the same level of this list item +function hideAllOthersUls( currentLi ) +{ + var lis = currentLi.parentNode; + for ( var i=0; i -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + + hide: function(element) { + element = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = Element.ancestors(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value || value == 'auto') { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
    ', 1], + TBODY: ['', '
    ', 2], + TR: ['', '
    ', 3], + TD: ['
    ', '
    ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
    '; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/tabber.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/tabber.js new file mode 100755 index 0000000000..a53b1b3060 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/js/tabber.js @@ -0,0 +1,536 @@ +/*================================================== + $Id: tabber.js,v 1.9 2006/04/27 20:51:51 pat Exp $ + tabber.js by Patrick Fitzgerald pat@barelyfitz.com + + Documentation can be found at the following URL: + http://www.barelyfitz.com/projects/tabber/ + + License (http://www.opensource.org/licenses/mit-license.php) + + Copyright (c) 2006 Patrick Fitzgerald + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ==================================================*/ + +function tabberObj(argsObj) +{ + var arg; /* name of an argument to override */ + + /* Element for the main tabber div. If you supply this in argsObj, + then the init() method will be called. + */ + this.div = null; + + /* Class of the main tabber div */ + this.classMain = "tabber"; + + /* Rename classMain to classMainLive after tabifying + (so a different style can be applied) + */ + this.classMainLive = "tabberlive"; + + /* Class of each DIV that contains a tab */ + this.classTab = "tabbertab"; + + /* Class to indicate which tab should be active on startup */ + this.classTabDefault = "tabbertabdefault"; + + /* Class for the navigation UL */ + this.classNav = "tabbernav"; + + /* When a tab is to be hidden, instead of setting display='none', we + set the class of the div to classTabHide. In your screen + stylesheet you should set classTabHide to display:none. In your + print stylesheet you should set display:block to ensure that all + the information is printed. + */ + this.classTabHide = "tabbertabhide"; + + /* Class to set the navigation LI when the tab is active, so you can + use a different style on the active tab. + */ + this.classNavActive = "tabberactive"; + + /* Elements that might contain the title for the tab, only used if a + title is not specified in the TITLE attribute of DIV classTab. + */ + this.titleElements = ['h2','h3','h4','h5','h6']; + + /* Should we strip out the HTML from the innerHTML of the title elements? + This should usually be true. + */ + this.titleElementsStripHTML = true; + + /* If the user specified the tab names using a TITLE attribute on + the DIV, then the browser will display a tooltip whenever the + mouse is over the DIV. To prevent this tooltip, we can remove the + TITLE attribute after getting the tab name. + */ + this.removeTitle = true; + + /* If you want to add an id to each link set this to true */ + this.addLinkId = false; + + /* If addIds==true, then you can set a format for the ids. + will be replaced with the id of the main tabber div. + will be replaced with the tab number + (tab numbers starting at zero) + will be replaced with the tab number + (tab numbers starting at one) + will be replaced by the tab title + (with all non-alphanumeric characters removed) + */ + this.linkIdFormat = 'nav'; + + /* You can override the defaults listed above by passing in an object: + var mytab = new tabber({property:value,property:value}); + */ + for (arg in argsObj) { this[arg] = argsObj[arg]; } + + /* Create regular expressions for the class names; Note: if you + change the class names after a new object is created you must + also change these regular expressions. + */ + this.REclassMain = new RegExp('\\b' + this.classMain + '\\b', 'gi'); + this.REclassMainLive = new RegExp('\\b' + this.classMainLive + '\\b', 'gi'); + this.REclassTab = new RegExp('\\b' + this.classTab + '\\b', 'gi'); + this.REclassTabDefault = new RegExp('\\b' + this.classTabDefault + '\\b', 'gi'); + this.REclassTabHide = new RegExp('\\b' + this.classTabHide + '\\b', 'gi'); + + /* Array of objects holding info about each tab */ + this.tabs = new Array(); + + /* If the main tabber div was specified, call init() now */ + if (this.div) { + + this.init(this.div); + + /* We don't need the main div anymore, and to prevent a memory leak + in IE, we must remove the circular reference between the div + and the tabber object. */ + this.div = null; + } +} + + +/*-------------------------------------------------- + Methods for tabberObj + --------------------------------------------------*/ + + +tabberObj.prototype.init = function(e) +{ + /* Set up the tabber interface. + + e = element (the main containing div) + + Example: + init(document.getElementById('mytabberdiv')) + */ + + var + childNodes, /* child nodes of the tabber div */ + i, i2, /* loop indices */ + t, /* object to store info about a single tab */ + defaultTab=0, /* which tab to select by default */ + DOM_ul, /* tabbernav list */ + DOM_li, /* tabbernav list item */ + DOM_a, /* tabbernav link */ + aId, /* A unique id for DOM_a */ + headingElement; /* searching for text to use in the tab */ + + /* Verify that the browser supports DOM scripting */ + if (!document.getElementsByTagName) { return false; } + + /* If the main DIV has an ID then save it. */ + if (e.id) { + this.id = e.id; + } + + /* Clear the tabs array (but it should normally be empty) */ + this.tabs.length = 0; + + /* Loop through an array of all the child nodes within our tabber element. */ + childNodes = e.childNodes; + for(i=0; i < childNodes.length; i++) { + + /* Find the nodes where class="tabbertab" */ + if(childNodes[i].className && + childNodes[i].className.match(this.REclassTab)) { + + /* Create a new object to save info about this tab */ + t = new Object(); + + /* Save a pointer to the div for this tab */ + t.div = childNodes[i]; + + /* Add the new object to the array of tabs */ + this.tabs[this.tabs.length] = t; + + /* If the class name contains classTabDefault, + then select this tab by default. + */ + if (childNodes[i].className.match(this.REclassTabDefault)) { + defaultTab = this.tabs.length-1; + } + } + } + + /* Create a new UL list to hold the tab headings */ + DOM_ul = document.createElement("ul"); + DOM_ul.className = this.classNav; + + /* Loop through each tab we found */ + for (i=0; i < this.tabs.length; i++) { + + t = this.tabs[i]; + + /* Get the label to use for this tab: + From the title attribute on the DIV, + Or from one of the this.titleElements[] elements, + Or use an automatically generated number. + */ + t.headingText = t.div.title; + + /* Remove the title attribute to prevent a tooltip from appearing */ + if (this.removeTitle) { t.div.title = ''; } + + if (!t.headingText) { + + /* Title was not defined in the title of the DIV, + So try to get the title from an element within the DIV. + Go through the list of elements in this.titleElements + (typically heading elements ['h2','h3','h4']) + */ + for (i2=0; i2/gi," "); + t.headingText = t.headingText.replace(/<[^>]+>/g,""); + } + break; + } + } + } + + if (!t.headingText) { + /* Title was not found (or is blank) so automatically generate a + number for the tab. + */ + t.headingText = i + 1; + } + + /* Create a list element for the tab */ + DOM_li = document.createElement("li"); + + /* Save a reference to this list item so we can later change it to + the "active" class */ + t.li = DOM_li; + + /* Create a link to activate the tab */ + DOM_a = document.createElement("a"); + DOM_a.appendChild(document.createTextNode(t.headingText)); + DOM_a.href = "javascript:void(null);"; + DOM_a.title = t.headingText; + DOM_a.onclick = this.navClick; + + /* Add some properties to the link so we can identify which tab + was clicked. Later the navClick method will need this. + */ + DOM_a.tabber = this; + DOM_a.tabberIndex = i; + + /* Do we need to add an id to DOM_a? */ + if (this.addLinkId && this.linkIdFormat) { + + /* Determine the id name */ + aId = this.linkIdFormat; + aId = aId.replace(//gi, this.id); + aId = aId.replace(//gi, i); + aId = aId.replace(//gi, i+1); + aId = aId.replace(//gi, t.headingText.replace(/[^a-zA-Z0-9\-]/gi, '')); + + DOM_a.id = aId; + } + + /* Add the link to the list element */ + DOM_li.appendChild(DOM_a); + + /* Add the list element to the list */ + DOM_ul.appendChild(DOM_li); + } + + /* Add the UL list to the beginning of the tabber div */ + e.insertBefore(DOM_ul, e.firstChild); + + /* Make the tabber div "live" so different CSS can be applied */ + e.className = e.className.replace(this.REclassMain, this.classMainLive); + + /* Activate the default tab, and do not call the onclick handler */ + this.tabShow(defaultTab); + + /* If the user specified an onLoad function, call it now. */ + if (typeof this.onLoad == 'function') { + this.onLoad({tabber:this}); + } + + return this; +}; + + +tabberObj.prototype.navClick = function(event) +{ + /* This method should only be called by the onClick event of an + element, in which case we will determine which tab was clicked by + examining a property that we previously attached to the + element. + + Since this was triggered from an onClick event, the variable + "this" refers to the element that triggered the onClick + event (and not to the tabberObj). + + When tabberObj was initialized, we added some extra properties + to the element, for the purpose of retrieving them now. Get + the tabberObj object, plus the tab number that was clicked. + */ + + var + rVal, /* Return value from the user onclick function */ + a, /* element that triggered the onclick event */ + self, /* the tabber object */ + tabberIndex, /* index of the tab that triggered the event */ + onClickArgs; /* args to send the onclick function */ + + a = this; + if (!a.tabber) { return false; } + + self = a.tabber; + tabberIndex = a.tabberIndex; + + /* Remove focus from the link because it looks ugly. + I don't know if this is a good idea... + */ + a.blur(); + + /* If the user specified an onClick function, call it now. + If the function returns false then do not continue. + */ + if (typeof self.onClick == 'function') { + + onClickArgs = {'tabber':self, 'index':tabberIndex, 'event':event}; + + /* IE uses a different way to access the event object */ + if (!event) { onClickArgs.event = window.event; } + + rVal = self.onClick(onClickArgs); + if (rVal === false) { return false; } + } + + self.tabShow(tabberIndex); + + return false; +}; + + +tabberObj.prototype.tabHideAll = function() +{ + var i; /* counter */ + + /* Hide all tabs and make all navigation links inactive */ + for (i = 0; i < this.tabs.length; i++) { + this.tabHide(i); + } +}; + + +tabberObj.prototype.tabHide = function(tabberIndex) +{ + var div; + + if (!this.tabs[tabberIndex]) { return false; } + + /* Hide a single tab and make its navigation link inactive */ + div = this.tabs[tabberIndex].div; + + /* Hide the tab contents by adding classTabHide to the div */ + if (!div.className.match(this.REclassTabHide)) { + div.className += ' ' + this.classTabHide; + } + this.navClearActive(tabberIndex); + + return this; +}; + + +tabberObj.prototype.tabShow = function(tabberIndex) +{ + /* Show the tabberIndex tab and hide all the other tabs */ + + var div; + + if (!this.tabs[tabberIndex]) { return false; } + + /* Hide all the tabs first */ + this.tabHideAll(); + + /* Get the div that holds this tab */ + div = this.tabs[tabberIndex].div; + + /* Remove classTabHide from the div */ + div.className = div.className.replace(this.REclassTabHide, ''); + + /* Mark this tab navigation link as "active" */ + this.navSetActive(tabberIndex); + + /* If the user specified an onTabDisplay function, call it now. */ + if (typeof this.onTabDisplay == 'function') { + this.onTabDisplay({'tabber':this, 'index':tabberIndex}); + } + + return this; +}; + +tabberObj.prototype.navSetActive = function(tabberIndex) +{ + /* Note: this method does *not* enforce the rule + that only one nav item can be active at a time. + */ + + /* Set classNavActive for the navigation list item */ + this.tabs[tabberIndex].li.className = this.classNavActive; + + return this; +}; + + +tabberObj.prototype.navClearActive = function(tabberIndex) +{ + /* Note: this method does *not* enforce the rule + that one nav should always be active. + */ + + /* Remove classNavActive from the navigation list item */ + this.tabs[tabberIndex].li.className = ''; + + return this; +}; + + +/*==================================================*/ + + +function tabberAutomatic(tabberArgs) +{ + /* This function finds all DIV elements in the document where + class=tabber.classMain, then converts them to use the tabber + interface. + + tabberArgs = an object to send to "new tabber()" + */ + var + tempObj, /* Temporary tabber object */ + divs, /* Array of all divs on the page */ + i; /* Loop index */ + + if (!tabberArgs) { tabberArgs = {}; } + + /* Create a tabber object so we can get the value of classMain */ + tempObj = new tabberObj(tabberArgs); + + /* Find all DIV elements in the document that have class=tabber */ + + /* First get an array of all DIV elements and loop through them */ + divs = document.getElementsByTagName("div"); + for (i=0; i < divs.length; i++) { + + /* Is this DIV the correct class? */ + if (divs[i].className && + divs[i].className.match(tempObj.REclassMain)) { + + /* Now tabify the DIV */ + tabberArgs.div = divs[i]; + divs[i].tabber = new tabberObj(tabberArgs); + } + } + + return this; +} + + +/*==================================================*/ + + +function tabberAutomaticOnLoad(tabberArgs) +{ + /* This function adds tabberAutomatic to the window.onload event, + so it will run after the document has finished loading. + */ + var oldOnLoad; + + if (!tabberArgs) { tabberArgs = {}; } + + /* Taken from: http://simon.incutio.com/archive/2004/05/26/addLoadEvent */ + + oldOnLoad = window.onload; + if (typeof window.onload != 'function') { + window.onload = function() { + tabberAutomatic(tabberArgs); + + }; + } else { + window.onload = function() { + oldOnLoad(); + tabberAutomatic(tabberArgs); + + }; + } +} + + +/*==================================================*/ +function init_tabs(){ + if (typeof tabberOptions == 'undefined') { + tabberAutomatic({}); + } + else + {if (!tabberOptions['manualStartup']) { + tabberAutomatic(tabberOptions); + } + } +} + +function init_autotabber(){ +/* Run tabberAutomaticOnload() unless the "manualStartup" option was specified */ + + if (typeof tabberOptions == 'undefined') { + + tabberAutomaticOnLoad(); + + } else { + + if (!tabberOptions['manualStartup']) { + tabberAutomaticOnLoad(tabberOptions); + } + + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-client.js b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-client.js new file mode 100755 index 0000000000..8a0739d9ca --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-client.js @@ -0,0 +1,612 @@ +/* + * Pushlet JS client library. + * NOTE: this should replace the js-pushlet-client.jsp file + * (since we can figure out pushletWebRoot from within JS) + * + * $Id: js-pushlet-client.js,v 1.2 2007/11/10 14:17:18 justb Exp $ + */ +var flag = false; +var pushletWebRoot = null; +var pushletURI; +var pushletNetURI; +var sessionId = null; +var controlQueue = new Queue(20); +var statusMsg = 'null'; +var statusChanged = false; +var statusChar = '|'; +var pushletNet; +var listenMode = null; +var listenSubject = null; + +// Initialize various URLs +_initURIs(); + +/************ Public application functions ******************/ + +// Embed pushlet frame in page +function p_embed(thePushletWebRoot) { + if (thePushletWebRoot) { + // Use this when webapp is not in same server e.g. with virtual hosts + pushletWebRoot = thePushletWebRoot; + _initURIs(); + } +//alert(pushletNetURI+""); + p_debug(flag, "p_embed", 'write ' + pushletLayer); + var pushletLayer = ''; + + self.document.write(pushletLayer); + _setStatus('initializing...'); + _showStatus(); + _waitForPushletFrame(); +} + +// Join the pushlet server +function p_join() { + // Ignore (for now) if already joined + if (sessionId != null) { + return; + } + + _setStatus('connecting...'); + p_debug(flag, "p_join", 'joining..'); + + + // Check if pushlet frame is loaded + if (pushletNet) { + // Pushlet iframe is ready for calls + pushletNet.setControlURI(pushletURI + '?p_event=join'); + } else { + + // Pushlet net iframe not loaded: continue waiting + setTimeout("p_join()", 100); + } +} + +// Create data event channel with the server +function p_listen(subject, mode) { + // Optional initial subject to subscribe to + if (subject) { + // Remember + listenSubject = subject; + } + + // Optional mode (stream, pull, poll) i.s.o. default + if (mode) { + // Remember + listenMode = mode; + } + + // Loop forever as long not joined + if (sessionId) { + // ok we have joined + + // Create event URI for listen + var uri = pushletURI + '?p_id=' + sessionId + '&p_event=listen'; + + // Optional subject to subscribe to + if (listenSubject) { + uri = uri + '&p_subject=' + listenSubject; + } + + // Optional mode (stream, pull, poll) i.s.o. default + if (listenMode) { + uri = uri + '&p_mode=' + listenMode; + } + + pushletNet.listen(uri); + return; + } + + // No join ack (sessionId) yet: wait until received + setTimeout("p_listen()", 100); + +} + +// Shorthand: Join the pushlet server and start listening immediately +function p_join_listen(subject, mode) { + p_join(); + p_listen(subject, mode); +} + +// Leave the pushlet server +function p_leave() { + // Ignore (for now) if already left + if (sessionId == null) { + return; + } + + var uri = pushletURI + '?p_event=leave'; + p_debug(flag, 'p_leave', 'leave uri=' + uri); + _sendControlURI(uri); +} + + +// Send heartbeat event; callback is onHeartbeatAck() +function p_heartbeat() { + var uri = pushletURI + '?p_event=hb'; + p_debug(flag, 'p_heartbeat'); + _sendControlURI(uri); +} + +// Publish to a subject +function p_publish(subject, nvPairs) { + if (!subject) { + return false; + } + + var uri = pushletURI + '?p_event=publish&p_subject=' + subject; + + var args = p_publish.arguments; + + // Put the arguments' name/value pairs in the URI + for (var i = 1; i < args.length; i++) { + uri = uri + '&' + args[i] + '=' + args[++i]; + } + + p_debug(false, 'p_publish', 'publish uri=' + uri); + _sendControlURI(uri); +} + +// Subscribe to a subject with optional label +function p_subscribe(subject, label) { + var uri = pushletURI + '?p_event=subscribe&p_subject=' + subject; + if (label) { + uri = uri + '&p_label=' + label; + } + + p_debug(flag, 'p_subscribe', 'subscribe uri=' + uri); + _sendControlURI(uri); +} + + // Unsubscribe from a subject +function p_unsubscribe(subscriptionId) { + var uri = pushletURI + '?p_event=unsubscribe'; + + if (subscriptionId) { + uri = uri + '&p_sid=' + subscriptionId; + } + + p_debug(flag, 'p_unsubscribe', 'unsubscribe uri=' + uri); + _sendControlURI(uri); +} + + +// Get webroot for this webapp +function p_getWebRoot() { + return pushletWebRoot; +} + +// Get pushlet session id +function p_getSessionId() { + return sessionId; +} + +// Show debug window +function p_setDebug(aFlag) { + flag = aFlag; + p_setNetDebug(aFlag); +} + +// Show network debug window +function p_setNetDebug(aFlag) { + pushletNet.p_setDebug(aFlag); +} + +/************ Private functions ******************/ + +/** CALLBACKS FROM pushletFrame ***/ + +// Generic callback from server; this function is called from within the +// Pushlet subscriber frame (see frames below). +function _push(args) { + // Create a PushletEvent object from the arguments passed in + // push.arguments is event data coming from the Server + var event = new PushletEvent(args); + + p_debug(flag, '_push() from server: ', event.toString()); + + // Do action based on event type + var eventType = event.getEvent(); + + if (eventType == 'data') { + _setStatus('data'); + _doCallback(event, window.onData); + } else if (eventType == 'join-ack') { + sessionId = event.get('p_id'); + _setStatus('connected'); + _doCallback(event, window.onJoinAck); + } else if (eventType == 'listen-ack') { + _setStatus('listening'); + _doCallback(event, window.onListenAck); + + // Send empty heartbeat event. This + // silences many busy browser windows. + // At least in Moz and IE. + p_heartbeat(); + } else if (eventType == 'hb') { + _setStatus('heartbeat'); + _doCallback(event, window.onHeartbeat); + } else if (eventType == 'hb-ack') { + _doCallback(event, window.onHeartbeatAck); + } else if (eventType == 'leave-ack') { + sessionId = null; + _setStatus('disconnected'); + _doCallback(event, window.onLeaveAck); + } else if (eventType == 'refresh-ack') { + _doCallback(event, window.onRefreshAck); + } else if (eventType == 'subscribe-ack') { + _setStatus('subscribed to ' + event.get('p_subject')); + _doCallback(event, window.onSubscribeAck); + } else if (eventType == 'unsubscribe-ack') { + _setStatus('unsubscribed'); + _doCallback(event, window.onUnsubscribeAck); + } else if (eventType == 'abort') { + _setStatus('abort'); + _doCallback(event, window.onAbort); + } else if (eventType.match(/nack$/)) { + _setStatus('error response: ' + event.get('p_reason')); + _doCallback(event, window.onNack); + } +} + +function getWebRoot() { + /** Return directory of this relative to document URL. */ + if (pushletWebRoot != null) { + return pushletWebRoot; + } + //derive the baseDir value by looking for the script tag that loaded this file + var head = document.getElementsByTagName('head')[0]; + var nodes = head.childNodes; + for (var i = 0; i < nodes.length; ++i) { + var src = nodes.item(i).src; + if (src) { + var index = src.indexOf("lib/js-pushlet-client.js"); + if (index >= 0) { + pushletWebRoot = src.substring(0, index); + break; + } + } + } + return pushletWebRoot; +} + +function _initURIs() { + pushletURI = getWebRoot() + 'pushlet.srv'; + pushletNetURI = getWebRoot() + 'lib/js-pushlet-net.html'; + //alert(pushletURI); +// alert(pushletNetURI); +} + +function _showStatus() { + // To show progress + if (statusChanged == true) { + if (statusChar == '|') statusChar = '/'; + else if (statusChar == '/') statusChar = '--'; + else if (statusChar == '--') statusChar = '\\'; + else statusChar = '|'; + statusChanged = false; + } + + window.defaultStatus = statusMsg; + window.status = statusMsg + ' ' + statusChar; + timeout = window.setTimeout('_showStatus()', 400); +} + +function _setStatus(status) { + statusMsg = "pushlet - " + status; + statusChanged = true; +} + +function _onUnload() { + p_debug(true, "pushlet-lib", "_onUnload() called"); +} + +function _onBeforeUnload() { + p_debug(true, "pushlet-lib", "_onBeforeUnload() called"); +} + +function _onStop() { + p_debug(true, "pushlet-lib", "_onStop() called"); +} + +function _doCallback(event, cbFunction) { + // Do specific callback function if provided by client + if (cbFunction) { + // Do specific callback like onData(), onJoinAck() etc. + cbFunction(event); + } else if (window.onEvent) { + // general callback onEvent() provided to catch all events + onEvent(event); + } +} + +/** CALLS TO pushletFrame ***/ + + +function _sendControlURI(uri) { + if (controlQueue.isFull()) { + // TODO divert to errpage + alert('serious problem: control queue is full'); + // no sense going on + return; + } + + if (sessionId == null) { + controlQueue.enqueue(uri); + _processControlQueue(); + return; + } + + // All clear to send immediately ? + if (controlQueue.isEmpty()) { + if (pushletNet.isControlReady()) { + // Ok send direct + uri = uri + '&p_id=' + sessionId; + pushletNet.setControlURI(uri); + } else { + controlQueue.enqueue(uri); + } + } else { + // Queue not empty + controlQueue.enqueue(uri); + } + + if (!controlQueue.isEmpty()) { + _processControlQueue(); + } +} + +function _processControlQueue() { + if (controlQueue.isEmpty()) { + // all done + return; + } + + if (sessionId != null) { + // Dequeue next control URI if pushletFrame ready + if (pushletNet.isControlReady()) { + var uri = controlQueue.dequeue() + '&p_id=' + sessionId; + pushletNet.setControlURI(uri); + } + } + + // Loop forever as long queue is not empty + if (!controlQueue.isEmpty()) { + setTimeout("_processControlQueue()", 50); + } +} + + +function _waitForPushletFrame() { + // Loop forever as long net uri not ready + if (self.pushletFrame && self.pushletFrame.isLoaded && self.pushletFrame.isLoaded()) { + _setStatus('loaded pushlet frame...'); + + pushletNet = self.pushletFrame; + return; + } + + _setStatus('pushlet frame not ready'); + setTimeout("_waitForPushletFrame()", 20); +} + +/************** Util classes *******************************/ + +/** NV pair object */ +function NameValuePair(name, value) { + this.name = name; + this.value = value; +} + +/** Simple Map object to store array of name/value pairs */ +function Map() { + // Data members + this.index = 0; + this.map = new Array(); + + // Function members + this.get = MapGet; + this.put = MapPut; + this.toString = MapToString; + this.toTable = MapToTable; +} + +/** get() */ +function MapGet(name) { + for (var i = 0; i < this.index; i++) { + if (this.map[i].name == name) { + return this.map[i].value; + } + } + return ''; +} + +/** put() */ +function MapPut(name, value) { + this.map[this.index++] = new NameValuePair(name, value); +} + +/** To HTML string */ +function MapToString() { + var res = ''; + + for (var i = 0; i < this.index; i++) { + res = res + this.map[i].name + '=' + this.map[i].value + '\n'; + } + return res; +} + +/** To HTML table */ +function MapToTable() { + var res = ''; + var styleDiv = '
    ' + + for (var i = 0; i < this.index; i++) { + res = res + '
    '; + } + res += '
    ' + styleDiv + this.map[i].name + '' + styleDiv + this.map[i].value + '
    ' + return res; +} + +/** Simple FIFO Queue class */ +function Queue(aCapacity) { + // Data members + this.capacity = aCapacity; + this.size = 0; + this.arr = new Array(); + this.front = 0; + this.rear = 0; + + // Function members + this.dequeue = QueueDequeue; + this.enqueue = QueueEnqueue; + this.next = QueueNext; + this.isFull = QueueIsFull; + this.isEmpty = QueueIsEmpty; +} + +/** enqueue() */ +function QueueEnqueue(item) { + if (this.isFull()) { + alert('queue full !!'); + return; + } + + this.arr[this.rear] = item; + this.rear = this.next(this.rear); + this.size++; +} + +/** dequeue() */ +function QueueDequeue(name) { + if (this.isEmpty()) { + alert('queue empty !!'); + return; + } + var temp = this.arr[this.front]; + this.arr[this.front] = null; + this.front = this.next(this.front); + this.size--; + return temp; +} + +/** Circular counter. */ +function QueueNext(index) { + return (index + 1 < this.capacity ? index + 1 : 0); +} + +function QueueIsFull() { + return this.size == this.capacity; +} + +function QueueIsEmpty() { + return this.size == 0; +} + +/* Class to represent nl.justobjects.pushlet.Event in JavaScript. + Arguments are an array where args[i] is name and args[i+1] is value +*/ +function PushletEvent(args) { + // Member variable setup; the Map stores the N/V pairs + this.map = new Map(); + + // Member function setup + this.getSubject = PushletEventGetSubject + this.getEvent = PushletEventGetEvent + this.put = PushletEventPut + this.get = PushletEventGet + this.toString = PushletEventToString + this.toTable = PushletEventToTable + + // Put the arguments' name/value pairs in the Map + for (var i = 0; i < args.length; i++) { + this.put(args[i], args[++i]); + } +} + +// Get the subject attribute +function PushletEventGetSubject() { + return this.map.get('p_subject') +} + +// Get the subject attribute +function PushletEventGetEvent() { + return this.map.get('p_event') +} + +// Get event attribute +function PushletEventGet(name) { + return this.map.get(name) +} + +// Put event attribute +function PushletEventPut(name, value) { + return this.map.put(name, value) +} + +function PushletEventToString() { + return this.map.toString(); +} + +// Convert content to HTML TABLE +function PushletEventToTable() { + return this.map.toTable(); +} + +/*************** Debug utility *******************************/ +var timestamp = 0 +var debugWindow = null +var messages = new Array() +var messagesIndex = 0 + +/** Send debug messages to a (D)HTML window. */ +function p_debug(flag, label, value) { + + // Only print if the flag is set + if (!flag) { + return; + } + + var funcName = "none"; + + // Fetch JS function name if any + if (p_debug.caller) { + funcName = p_debug.caller.toString() + funcName = funcName.substring(9, funcName.indexOf(")") + 1) + } + + // Create message + var msg = "-" + funcName + ": " + label + "=" + value + + // Add optional timestamp + var now = new Date() + var elapsed = now - timestamp + if (elapsed < 10000) { + msg += " (" + elapsed + " msec)" + } + + timestamp = now + + // Show. + + if ((debugWindow == null) || debugWindow.closed) { + debugWindow = window.open("", "p_debugWin", "toolbar=no,scrollbars=yes,resizable=yes,width=600,height=400"); + } + + // Add message to current list + messages[messagesIndex++] = msg + + // Write doc header + debugWindow.document.writeln('Pushlet Debug Window'); + + // Write the messages + for (var i = 0; i < messagesIndex; i++) { + debugWindow.document.writeln('
    ' + i + ': ' + messages[i] + '
    '); + } + + // Write doc footer and close + debugWindow.document.writeln(''); + debugWindow.document.close(); + debugWindow.focus(); + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-net.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-net.html new file mode 100755 index 0000000000..fceafc90b2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/lib/js-pushlet-net.html @@ -0,0 +1,109 @@ + + + + + Pushlet Networking Component + + + + + + + + + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/logOut.jsp b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/logOut.jsp new file mode 100755 index 0000000000..49ec9f46f0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/WebContent/logOut.jsp @@ -0,0 +1,39 @@ + + + + + + + + + + Log Out + + + + + + + + + + <%-- desabonnement du pushlet--%> +
    +Bye bye <% out.println(session.getAttribute("login")); %> !
    +Thank you for using Paparazzi On the Web !
    + +<% +session.removeAttribute("login"); +session.removeAttribute("rights"); +session.invalidate(); +%> + +

    +Click here to go to the Paparazzi project homepage.
    +Click here to return to the Paparazzi On the Web homepage. +

    +
    + + \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/Version.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/Version.class new file mode 100755 index 0000000000..a0d3e54309 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/Version.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$DataEventListener.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$DataEventListener.class new file mode 100755 index 0000000000..f3ff29c730 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$DataEventListener.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$HTTPAuthenticateProxy.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$HTTPAuthenticateProxy.class new file mode 100755 index 0000000000..b4e6d3877d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient$HTTPAuthenticateProxy.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.class new file mode 100755 index 0000000000..8995f5fe64 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.java.patch b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.java.patch new file mode 100755 index 0000000000..63d660354d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClient.java.patch @@ -0,0 +1,29 @@ +--- PushletClient.java 6 May 2005 20:08:20 -0000 1.16 ++++ PushletClient.java 28 Oct 2006 23:19:12 -0000 +@@ -142,7 +142,13 @@ + } + + dataEventListener = new DataEventListener(aListener, listenURL); +- dataEventListener.start(); ++ synchronized (dataEventListener) { ++ dataEventListener.start(); ++ try { ++ dataEventListener.wait(); ++ } catch (InterruptedException e) { ++ } ++ } + } + + /** Immediate listener. */ +@@ -354,6 +360,11 @@ + // Connect to server + reader = openURL(listenURL); + ++ synchronized (this) { ++ // Inform the calling thread we're ready to receive events. ++ this.notify(); ++ } ++ + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClientListener.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClientListener.class new file mode 100755 index 0000000000..f51394c738 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/client/PushletClientListener.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/BrowserAdapter.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/BrowserAdapter.class new file mode 100755 index 0000000000..621934ecf5 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/BrowserAdapter.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ClientAdapter.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ClientAdapter.class new file mode 100755 index 0000000000..2af4b37f0f Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ClientAdapter.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Command.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Command.class new file mode 100755 index 0000000000..ff1e50ec20 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Command.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Config.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Config.class new file mode 100755 index 0000000000..e35454ab7a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Config.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ConfigDefs.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ConfigDefs.class new file mode 100755 index 0000000000..97abf75f59 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/ConfigDefs.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Controller.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Controller.class new file mode 100755 index 0000000000..52d6182c72 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Controller.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher$SessionManagerVisitor.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher$SessionManagerVisitor.class new file mode 100755 index 0000000000..67e2ff50a4 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher$SessionManagerVisitor.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher.class new file mode 100755 index 0000000000..96a1e30460 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Dispatcher.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Event.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Event.class new file mode 100755 index 0000000000..5f0a44f42b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Event.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventParser.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventParser.class new file mode 100755 index 0000000000..ba24b91dc8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventParser.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventPullSource.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventPullSource.class new file mode 100755 index 0000000000..5035b8c3ac Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventPullSource.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventQueue.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventQueue.class new file mode 100755 index 0000000000..5a683b561c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventQueue.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSource.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSource.class new file mode 100755 index 0000000000..82cb2a1788 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSource.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSourceManager.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSourceManager.class new file mode 100755 index 0000000000..5f3f210f67 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/EventSourceManager.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Protocol.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Protocol.class new file mode 100755 index 0000000000..621230a85c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Protocol.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SerializedAdapter.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SerializedAdapter.class new file mode 100755 index 0000000000..a9e20bd445 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SerializedAdapter.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Session.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Session.class new file mode 100755 index 0000000000..aeaf500cd3 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Session.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager$AgingTimerTask.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager$AgingTimerTask.class new file mode 100755 index 0000000000..32c0c5107d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager$AgingTimerTask.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager.class new file mode 100755 index 0000000000..20b1c938be Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/SessionManager.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscriber.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscriber.class new file mode 100755 index 0000000000..86988f5c55 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscriber.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscription.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscription.class new file mode 100755 index 0000000000..3757a3654e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/Subscription.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/XMLAdapter.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/XMLAdapter.class new file mode 100755 index 0000000000..5c9e098014 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/core/XMLAdapter.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/servlet/Pushlet.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/servlet/Pushlet.class new file mode 100755 index 0000000000..8487dc070e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/servlet/Pushlet.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/DefaultLogger.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/DefaultLogger.class new file mode 100755 index 0000000000..88c9a8886e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/DefaultLogger.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log.class new file mode 100755 index 0000000000..ad1b9d2a01 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log4jLogger.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log4jLogger.class new file mode 100755 index 0000000000..fc7f3aad68 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Log4jLogger.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletException.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletException.class new file mode 100755 index 0000000000..2de5da72f8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletException.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletLogger.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletLogger.class new file mode 100755 index 0000000000..d5223e244a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/PushletLogger.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Rand.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Rand.class new file mode 100755 index 0000000000..e5ce60654c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Rand.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Servlets.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Servlets.class new file mode 100755 index 0000000000..e7f6917dbd Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Servlets.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Sys.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Sys.class new file mode 100755 index 0000000000..2ce439ec6c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/nl/justobjects/pushlet/util/Sys.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/AES.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/AES.class new file mode 100755 index 0000000000..3641ca5740 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/AES.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert$SavingTrustManager.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert$SavingTrustManager.class new file mode 100755 index 0000000000..35373b7698 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert$SavingTrustManager.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert.class new file mode 100755 index 0000000000..83b0761007 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/InstallCert.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetId.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetId.class new file mode 100755 index 0000000000..4f1d6996c4 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetId.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage$myListener.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage$myListener.class new file mode 100755 index 0000000000..f7eca18ad0 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage$myListener.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage.class new file mode 100755 index 0000000000..e98ec79c90 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcNetIdStorage.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcStatus.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcStatus.class new file mode 100755 index 0000000000..8d60963c98 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/AcStatus.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/BusIvy_.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/BusIvy_.class new file mode 100755 index 0000000000..9956d0f89c Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/BusIvy_.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/HeartBeat.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/HeartBeat.class new file mode 100755 index 0000000000..1ab04f5baf Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/HeartBeat.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$1.class new file mode 100755 index 0000000000..bd75882833 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$2.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$2.class new file mode 100755 index 0000000000..bf756b6a8b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$2.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$3.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$3.class new file mode 100755 index 0000000000..21de596c65 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$3.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$4.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$4.class new file mode 100755 index 0000000000..6d13278297 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$4.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$5.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$5.class new file mode 100755 index 0000000000..5fed7c428b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$5.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$6.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$6.class new file mode 100755 index 0000000000..6a7caf2a4a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$6.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$7.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$7.class new file mode 100755 index 0000000000..293ad9e246 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$7.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$8.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$8.class new file mode 100755 index 0000000000..d19d51ecc0 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$8.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$9.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$9.class new file mode 100755 index 0000000000..f4298fe102 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$9.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$aircraftIdSeeker.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$aircraftIdSeeker.class new file mode 100755 index 0000000000..53b2abc7b9 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp$aircraftIdSeeker.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp.class new file mode 100755 index 0000000000..5fe7d5716d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2Udp.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2UdpWriting.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2UdpWriting.class new file mode 100755 index 0000000000..faee86c6eb Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/Ivy2UdpWriting.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyConnectionExeption.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyConnectionExeption.class new file mode 100755 index 0000000000..628a3506e8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyConnectionExeption.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$1.class new file mode 100755 index 0000000000..5d4418e8c2 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction$1.class new file mode 100755 index 0000000000..7639106504 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction.class new file mode 100755 index 0000000000..e32fd81757 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$LogAction.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction$1.class new file mode 100755 index 0000000000..a7c7be2d80 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction.class new file mode 100755 index 0000000000..9182435d53 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$MoreAction.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction$1.class new file mode 100755 index 0000000000..295c9ea683 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction.class new file mode 100755 index 0000000000..e7fdb66980 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$QuitAction.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction$1.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction$1.class new file mode 100755 index 0000000000..3b3005bc0e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction$1.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction.class new file mode 100755 index 0000000000..7be9b47844 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM$StopAction.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM.class new file mode 100755 index 0000000000..eb49810a41 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/IvyIHM.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/MsgFilter.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/MsgFilter.class new file mode 100755 index 0000000000..2c01f717d5 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/MsgFilter.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/PowUrl.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/PowUrl.class new file mode 100755 index 0000000000..5da2b22782 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/ivyclient/PowUrl.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AjaxRqst.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AjaxRqst.class new file mode 100755 index 0000000000..2f89e040a8 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AjaxRqst.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AlreadyRegisteredUserException.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AlreadyRegisteredUserException.class new file mode 100755 index 0000000000..47a169bd8d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/AlreadyRegisteredUserException.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Conf.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Conf.class new file mode 100755 index 0000000000..751a7ee327 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Conf.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbMode.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbMode.class new file mode 100755 index 0000000000..f5fec1e67d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbMode.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbOrder.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbOrder.class new file mode 100755 index 0000000000..eb8306de43 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/DbOrder.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Greeting.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Greeting.class new file mode 100755 index 0000000000..500bb3832b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Greeting.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/HeartBeat.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/HeartBeat.class new file mode 100755 index 0000000000..d6ad0e3c0a Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/HeartBeat.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Ivy2TomcatHttpServer.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Ivy2TomcatHttpServer.class new file mode 100755 index 0000000000..2521a87855 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Ivy2TomcatHttpServer.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/IvyMsg.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/IvyMsg.class new file mode 100755 index 0000000000..d69238c5c2 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/IvyMsg.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Log.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Log.class new file mode 100755 index 0000000000..5f5244715d Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Log.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Md5.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Md5.class new file mode 100755 index 0000000000..8b3aab8117 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Md5.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Rights.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Rights.class new file mode 100755 index 0000000000..e85a2100d5 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Rights.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SGBDfeeder.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SGBDfeeder.class new file mode 100755 index 0000000000..77905a764f Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SGBDfeeder.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeHostnameVerifier.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeHostnameVerifier.class new file mode 100755 index 0000000000..7cde65baec Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeHostnameVerifier.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeX509TrustManager.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeX509TrustManager.class new file mode 100755 index 0000000000..88bbfbfb07 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$FakeX509TrustManager.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeHostnameVerifier.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeHostnameVerifier.class new file mode 100755 index 0000000000..3ec530f905 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeHostnameVerifier.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeX509TrustManager.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeX509TrustManager.class new file mode 100755 index 0000000000..e615069b24 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities$_FakeX509TrustManager.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities.class new file mode 100755 index 0000000000..e2a55f971b Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SSLUtilities.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur$IvyEventSource.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur$IvyEventSource.class new file mode 100755 index 0000000000..98d7c88271 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur$IvyEventSource.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur.class new file mode 100755 index 0000000000..469635515e Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/Serveur.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SessionIvy.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SessionIvy.class new file mode 100755 index 0000000000..aa940715c9 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/SessionIvy.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/StrictSSLProtocolSocketFactory.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/StrictSSLProtocolSocketFactory.class new file mode 100755 index 0000000000..52de4ed471 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/StrictSSLProtocolSocketFactory.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/User.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/User.class new file mode 100755 index 0000000000..6b13c3b025 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/User.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/UserTab.class b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/UserTab.class new file mode 100755 index 0000000000..34f1f5acd6 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/build/classes/pow/webserver/UserTab.class differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-frame.html new file mode 100755 index 0000000000..abdf0c7e73 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-frame.html @@ -0,0 +1,103 @@ + + + + + + +All Classes + + + + + + + + + + + +All Classes +
    + + + + + +
    AcNetId +
    +AcNetIdStorage +
    +AcStatus +
    +AES +
    +AjaxRqst +
    +AlreadyRegisteredUserException +
    +BusIvy_ +
    +Conf +
    +DbMode +
    +DbOrder +
    +Greeting +
    +HeartBeat +
    +HeartBeat +
    +InstallCert +
    +Ivy2TomcatHttpServer +
    +Ivy2Udp +
    +Ivy2UdpWriting +
    +IvyConnectionExeption +
    +IvyIHM +
    +IvyMsg +
    +Log +
    +Md5 +
    +MsgFilter +
    +PowUrl +
    +Rights +
    +Serveur +
    +Serveur.IvyEventSource +
    +SessionIvy +
    +SGBDfeeder +
    +SSLUtilities +
    +SSLUtilities._FakeHostnameVerifier +
    +SSLUtilities._FakeX509TrustManager +
    +SSLUtilities.FakeHostnameVerifier +
    +SSLUtilities.FakeX509TrustManager +
    +StrictSSLProtocolSocketFactory +
    +User +
    +UserTab +
    +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-noframe.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-noframe.html new file mode 100755 index 0000000000..476dda131a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/allclasses-noframe.html @@ -0,0 +1,103 @@ + + + + + + +All Classes + + + + + + + + + + + +All Classes +
    + + + + + +
    AcNetId +
    +AcNetIdStorage +
    +AcStatus +
    +AES +
    +AjaxRqst +
    +AlreadyRegisteredUserException +
    +BusIvy_ +
    +Conf +
    +DbMode +
    +DbOrder +
    +Greeting +
    +HeartBeat +
    +HeartBeat +
    +InstallCert +
    +Ivy2TomcatHttpServer +
    +Ivy2Udp +
    +Ivy2UdpWriting +
    +IvyConnectionExeption +
    +IvyIHM +
    +IvyMsg +
    +Log +
    +Md5 +
    +MsgFilter +
    +PowUrl +
    +Rights +
    +Serveur +
    +Serveur.IvyEventSource +
    +SessionIvy +
    +SGBDfeeder +
    +SSLUtilities +
    +SSLUtilities._FakeHostnameVerifier +
    +SSLUtilities._FakeX509TrustManager +
    +SSLUtilities.FakeHostnameVerifier +
    +SSLUtilities.FakeX509TrustManager +
    +StrictSSLProtocolSocketFactory +
    +User +
    +UserTab +
    +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/constant-values.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/constant-values.html new file mode 100755 index 0000000000..f51df7f84d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/constant-values.html @@ -0,0 +1,146 @@ + + + + + + +Constant Field Values + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Constant Field Values

    +
    +
    +Contents
      +
    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/deprecated-list.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/deprecated-list.html new file mode 100755 index 0000000000..d18bd5efe2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/deprecated-list.html @@ -0,0 +1,166 @@ + + + + + + +Deprecated List + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Deprecated API

    +
    +
    +Contents + + + + + + + + + + + + +
    +Deprecated Classes
    pow.webserver.SSLUtilities._FakeHostnameVerifier +
    +          see SSLUtilities.FakeHostnameVerifier. 
    pow.webserver.SSLUtilities._FakeX509TrustManager +
    +          see SSLUtilities.FakeX509TrustManager. 
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/help-doc.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/help-doc.html new file mode 100755 index 0000000000..7880f61ecf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/help-doc.html @@ -0,0 +1,223 @@ + + + + + + +API Help + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +How This API Document Is Organized

    +
    +This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.

    +Overview

    +
    + +

    +The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

    +

    +Package

    +
    + +

    +Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:

      +
    • Interfaces (italic)
    • Classes
    • Enums
    • Exceptions
    • Errors
    • Annotation Types
    +
    +

    +Class/Interface

    +
    + +

    +Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

      +
    • Class inheritance diagram
    • Direct Subclasses
    • All Known Subinterfaces
    • All Known Implementing Classes
    • Class/interface declaration
    • Class/interface description +

      +

    • Nested Class Summary
    • Field Summary
    • Constructor Summary
    • Method Summary +

      +

    • Field Detail
    • Constructor Detail
    • Method Detail
    +Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
    + +

    +Annotation Type

    +
    + +

    +Each annotation type has its own separate page with the following sections:

      +
    • Annotation Type declaration
    • Annotation Type description
    • Required Element Summary
    • Optional Element Summary
    • Element Detail
    +
    + +

    +Enum

    +
    + +

    +Each enum has its own separate page with the following sections:

      +
    • Enum declaration
    • Enum description
    • Enum Constant Summary
    • Enum Constant Detail
    +
    +

    +Use

    +
    +Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
    +

    +Tree (Class Hierarchy)

    +
    +There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
      +
    • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
    • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
    +
    +

    +Deprecated API

    +
    +The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.
    +

    +Index

    +
    +The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
    +

    +Prev/Next

    +These links take you to the next or previous class, interface, package, or related page.

    +Frames/No Frames

    +These links show and hide the HTML frames. All pages are available with or without frames. +

    +

    +Serialized Form

    +Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description. +

    +

    +Constant Field Values

    +The Constant Field Values page lists the static final fields and their values. +

    + + +This help file applies to API documentation generated using the standard doclet. + +
    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-1.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-1.html new file mode 100755 index 0000000000..4680a6329b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-1.html @@ -0,0 +1,185 @@ + + + + + + +A-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +A

    +
    +
    AcNetId - Class in pow.ivyclient
    this object represents the data concerning a drone extracted from Ivy + A drone has two identities.
    AcNetId(int, String, String, String, String, String, int) - +Constructor for class pow.ivyclient.AcNetId +
      +
    AcNetId(int, String, String, String, String, String, String, int) - +Constructor for class pow.ivyclient.AcNetId +
      +
    AcNetIdStorage - Class in pow.ivyclient
    this structure memorize all the drone which exist on the ivy bus.
    AcNetIdStorage(int, Ivy, String, int, ConcurrentHashMap<String, AcStatus>) - +Constructor for class pow.ivyclient.AcNetIdStorage +
      +
    AcStatus - Enum in pow.ivyclient
    implements the life cycle of a drone when it is detected on the ivy bus.
    activate() - +Method in class pow.webserver.Serveur.IvyEventSource +
    Activate the event source. +
    addDrone(String) - +Method in class pow.webserver.User +
    add a drone name to the list of drones that the user can control +
    addDrones(int) - +Method in class pow.ivyclient.BusIvy_ +
    inform the bus that a new drone send information on this bus +
    adminLogin() - +Method in class pow.webserver.Conf +
      +
    AES - Class in pow
    implements AES encryption and decryption algorithms + see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html + see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption
    AES() - +Constructor for class pow.AES +
    construct a cipher with a generated 128 bits key +
    AES(String) - +Constructor for class pow.AES +
    construct a cipher from an user specified key +
    AES(byte[], byte[]) - +Constructor for class pow.AES +
    construct a cipher from a key and a parameter array + usefull to create a remote decryption cypher +
    AjaxRqst - Class in pow.webserver
    Servlet implementation class ajaxRqst + handles the different request from a web client which wants to give orders to a drone + and it handles administrator queries to manage users' profiles
    AjaxRqst() - +Constructor for class pow.webserver.AjaxRqst +
      +
    AlreadyRegisteredUserException - Exception in pow.webserver
    exception to inform that a user cannot be created in the users' file + because it exists yet
    AlreadyRegisteredUserException(User) - +Constructor for exception pow.webserver.AlreadyRegisteredUserException +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-10.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-10.html new file mode 100755 index 0000000000..a595140053 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-10.html @@ -0,0 +1,145 @@ + + + + + + +L-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +L

    +
    +
    Log - Class in pow.webserver
    Handles the writing of a log in a file
    Log(String) - +Constructor for class pow.webserver.Log +
    create a log file into the log floder of the web application +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-11.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-11.html new file mode 100755 index 0000000000..49bd54e8a3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-11.html @@ -0,0 +1,163 @@ + + + + + + +M-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +M

    +
    +
    mailAdmin() - +Method in class pow.webserver.Conf +
      +
    main(String[]) - +Static method in class pow.InstallCert +
      +
    main(String[]) - +Static method in class pow.ivyclient.IvyIHM +
    launch the interface to connect the ivy bus to POW server +
    main(String[]) - +Static method in class pow.webserver.Md5 +
    example +
    Md5 - Class in pow.webserver
    tool class to implemente MD5 encoding + ( found on the web )
    Md5() - +Constructor for class pow.webserver.Md5 +
      +
    MsgFilter - Class in pow.ivyclient
    this class filters the message, thanks to their hash code + it is used because Paparazzi send periodic messages that are often the same + so we filter them to lighten the server load and the bandwidth of the udp channel
    MsgFilter() - +Constructor for class pow.ivyclient.MsgFilter +
    create a message filter +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-12.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-12.html new file mode 100755 index 0000000000..d7e2f62774 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-12.html @@ -0,0 +1,156 @@ + + + + + + +P-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +P

    +
    +
    passivate() - +Method in class pow.webserver.Serveur.IvyEventSource +
    Desactivate the event source. +
    portIvyToWeb() - +Method in class pow.webserver.Conf +
      +
    portWebToIvy() - +Method in class pow.webserver.Conf +
      +
    pow - package pow
     
    pow.ivyclient - package pow.ivyclient
     
    pow.webserver - package pow.webserver
     
    PowUrl - Class in pow.ivyclient
    object which store all information about the url to log on the server
    PowUrl(String, String, int, String, String) - +Constructor for class pow.ivyclient.PowUrl +
    create all the information requested to connect the ivy module to the server + when all parameters are correct can give an url like + https://paparazzi.fr/ServletPow/Login.srv +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-13.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-13.html new file mode 100755 index 0000000000..55775ff8ae --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-13.html @@ -0,0 +1,179 @@ + + + + + + +R-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +R

    +
    +
    receive(IvyClient, String[]) - +Method in class pow.ivyclient.Ivy2UdpWriting +
    This method implements the method receive of the bus Ivy class. +
    remove(String) - +Method in class pow.webserver.UserTab +
    remove the user with the spefied login +
    resetfilter() - +Method in class pow.ivyclient.MsgFilter +
    empty the filter +
    Rights - Enum in pow.webserver
    describe the different rights a web user can have
    run() - +Method in class pow.ivyclient.HeartBeat +
    send a periodic heartbeat message +
    run() - +Method in class pow.ivyclient.Ivy2Udp +
    listen the udp socket to get orders from web clients and send them to ivy +
    run() - +Method in class pow.ivyclient.IvyIHM +
    loop to perform a periodic check for automatic reconnection +
    run() - +Method in class pow.webserver.HeartBeat +
    send a periodic heartbeat message to every connected ivy bus +
    run() - +Method in class pow.webserver.Serveur.IvyEventSource +
    main loop : + listens to the udp channel + deciphers the udp message + checks if the sender is a new bus or not + send the message to database through a fifo + turns the ivy message into a pushlet event + send the event to web users + checks if there are some buses that doesn't send messages anymore + removes drone which belonged to dead buses +
    run() - +Method in class pow.webserver.SGBDfeeder +
    listens fifo queue and stores ivy messages in database + if the message has the DECONNECT type it also fills the end field corresponding + to this ivy session into the 'connexion' table +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-14.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-14.html new file mode 100755 index 0000000000..150030e8dd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-14.html @@ -0,0 +1,259 @@ + + + + + + +S-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +S

    +
    +
    seek(String) - +Method in class pow.webserver.UserTab +
    return the user corresponding to the given login +
    seekAcNetId(String) - +Method in class pow.ivyclient.AcNetIdStorage +
    search the drone net id of a drone from its ivy id + if the drone is a new one, a new net id is requested to the server +
    send(int) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send to the web server the datagram containing the informations + about the aircraft +
    send(int, String, String[]) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send to the web server a specific order with parameters +
    send(int, String) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send a particular message about an aircraft +
    serialize(String) - +Method in class pow.webserver.UserTab +
    Save the object in a file +
    Serveur - Class in pow.webserver
    Class which receive a datagramm from ivy bus via UDP + transforms it into a Pushlet event and send it to the Pushlet server + in order that it will be sent to web clients
    Serveur() - +Constructor for class pow.webserver.Serveur +
      +
    Serveur.IvyEventSource - Class in pow.webserver
     
    Serveur.IvyEventSource() - +Constructor for class pow.webserver.Serveur.IvyEventSource +
      +
    SessionIvy - Class in pow.webserver
    store information about a specific ivy bus which is connected + to the server
    SessionIvy(String, int, AES, InetAddress) - +Constructor for class pow.webserver.SessionIvy +
    create a session which store information about an ivy bus client connected to the server + main information are its net address to send him orders from web users + and drones which are connected to this ivy bus +
    setAddress(InetAddress) - +Method in class pow.ivyclient.BusIvy_ +
      +
    setBusIvy(BusIvy_) - +Method in class pow.webserver.SessionIvy +
    store the information of the ivy bus into the ivy session +
    setHostnameVerification(boolean) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
    Set the host name verification flag. +
    setIvyInetAddress(InetAddress) - +Method in class pow.webserver.SessionIvy +
    set the ip adress of the ivy bus host +
    setNom(String) - +Method in class pow.webserver.User +
    specify the login of the user +
    setOrder(DbOrder) - +Method in class pow.webserver.IvyMsg +
    specify how to store the message in database +
    setPwd(String) - +Method in class pow.webserver.User +
    specify the user password, it's not stored in clear (md5 hash) +
    setReLogged(boolean) - +Method in class pow.ivyclient.IvyIHM +
    specify whether the module should reconnected or not +
    setRights(Rights) - +Method in class pow.webserver.User +
    specify the type of right granted to the user +
    setServletContext(ServletContext) - +Method in class pow.webserver.Serveur.IvyEventSource +
    method qui renseigne la source sur la servlet qui l'a appelé + modification de la librairie pushlet + Pushlet.java + EventSource.java + EventSourceManager.java +
    setStorage() - +Method in class pow.ivyclient.Ivy2Udp +
    initiate the object which allow to store information about drones +
    SGBDfeeder - Class in pow.webserver
    thread which waits for ivy messages sent by event source (serveur.java) + and stores them into a mysql database + the ivy messages are extracted from a blocking queue (fifo) + parameter of the database are extracted from conf file
    SGBDfeeder(String, String, String, DbMode) - +Constructor for class pow.webserver.SGBDfeeder +
    create a thread which fill the database with the message it extracts from the fifo +
    SSLUtilities - Class in pow.webserver
    This class provide various static methods that relax X509 certificate and + hostname verification while using the SSL over the HTTP protocol.
    SSLUtilities() - +Constructor for class pow.webserver.SSLUtilities +
      +
    SSLUtilities._FakeHostnameVerifier - Class in pow.webserver
    Deprecated. see SSLUtilities.FakeHostnameVerifier.
    SSLUtilities._FakeHostnameVerifier() - +Constructor for class pow.webserver.SSLUtilities._FakeHostnameVerifier +
    Deprecated.   +
    SSLUtilities._FakeX509TrustManager - Class in pow.webserver
    Deprecated. see SSLUtilities.FakeX509TrustManager.
    SSLUtilities._FakeX509TrustManager() - +Constructor for class pow.webserver.SSLUtilities._FakeX509TrustManager +
    Deprecated.   +
    SSLUtilities.FakeHostnameVerifier - Class in pow.webserver
    This class implements a fake hostname verificator, trusting any host + name.
    SSLUtilities.FakeHostnameVerifier() - +Constructor for class pow.webserver.SSLUtilities.FakeHostnameVerifier +
      +
    SSLUtilities.FakeX509TrustManager - Class in pow.webserver
    This class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates.
    SSLUtilities.FakeX509TrustManager() - +Constructor for class pow.webserver.SSLUtilities.FakeX509TrustManager +
      +
    startHeartBeat() - +Method in class pow.ivyclient.Ivy2Udp +
    create a thread which send heart beat message to the server +
    stop() - +Method in class pow.webserver.Serveur.IvyEventSource +
    Desactivate the event source. +
    stop_thread() - +Method in class pow.ivyclient.HeartBeat +
    stop the heartbeat thread by ending the infinite loop +
    stop_thread() - +Method in class pow.ivyclient.Ivy2Udp +
    stop all the thread Ivy2Udp , HeartBeat and ivy2UdpWriting +
    stop_thread() - +Method in class pow.webserver.HeartBeat +
    stop the heartbeat process of the server +
    StrictSSLProtocolSocketFactory - Class in pow.webserver
    A SecureProtocolSocketFactory that uses JSSE to create + SSL sockets.
    StrictSSLProtocolSocketFactory(boolean) - +Constructor for class pow.webserver.StrictSSLProtocolSocketFactory +
    Constructor for StrictSSLProtocolSocketFactory. +
    StrictSSLProtocolSocketFactory() - +Constructor for class pow.webserver.StrictSSLProtocolSocketFactory +
    Constructor for StrictSSLProtocolSocketFactory. +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-15.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-15.html new file mode 100755 index 0000000000..4136614ad0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-15.html @@ -0,0 +1,159 @@ + + + + + + +T-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +T

    +
    +
    toString() - +Method in class pow.ivyclient.AcNetId +
    return information about the drone in a string format +
    toString() - +Method in exception pow.ivyclient.IvyConnectionExeption +
    display the exception on stdout +
    toString() - +Method in exception pow.webserver.AlreadyRegisteredUserException +
      +
    trustAllHostnames() - +Static method in class pow.webserver.SSLUtilities +
    Set the default Hostname Verifier to an instance of a fake class that + trust all hostnames. +
    trustAllHttpsCertificates() - +Static method in class pow.webserver.SSLUtilities +
    Set the default X509 Trust Manager to an instance of a fake class that + trust all certificates, even the self-signed ones. +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-16.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-16.html new file mode 100755 index 0000000000..ba0352830c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-16.html @@ -0,0 +1,165 @@ + + + + + + +U-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +U

    +
    +
    unserialize(String) - +Static method in class pow.webserver.UserTab +
    load the object from a file +
    updateTime() - +Method in class pow.ivyclient.BusIvy_ +
    update the 'inner clock' of the object when a message for this bus is detected + useful to know if the bus is still alive +
    uploadConfFile(AcNetId) - +Method in class pow.ivyclient.AcNetIdStorage +
    upload de fichier de conf sur le serveur + verifier que ca marche sur long fichier + si probleme changer avec : + factory.setSizeThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + upload.setSizeMax(yourMaxRequestSize); +
    User - Class in pow.webserver
    represents a ivy or a web user account + for the web user the account nest also the list of drones that the user can control + the list contains the ivy name of the drone (MJ5, TJ1...).
    User(String, String, Rights) - +Constructor for class pow.webserver.User +
    create a user account +
    UserTab - Class in pow.webserver
    User objects are stored in a UserTab object which can be serialized in a file on the server disk
    UserTab() - +Constructor for class pow.webserver.UserTab +
    create a empty list of users +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-17.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-17.html new file mode 100755 index 0000000000..e332ff12f2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-17.html @@ -0,0 +1,178 @@ + + + + + + +V-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +V

    +
    +
    valueOf(String) - +Static method in enum pow.ivyclient.AcStatus +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.DbMode +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.DbOrder +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.Rights +
    Returns the enum constant of this type with the specified name. +
    values() - +Static method in enum pow.ivyclient.AcStatus +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.DbMode +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.DbOrder +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.Rights +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    verify(String, String) - +Method in class pow.webserver.SSLUtilities._FakeHostnameVerifier +
    Deprecated. Always return true, indicating that the host name is an + acceptable match with the server's authentication scheme. +
    verify(String, SSLSession) - +Method in class pow.webserver.SSLUtilities.FakeHostnameVerifier +
    Always return true, indicating that the host name is + an acceptable match with the server's authentication scheme. +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-18.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-18.html new file mode 100755 index 0000000000..24b00d964c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-18.html @@ -0,0 +1,145 @@ + + + + + + +W-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +W

    +
    +
    write(String) - +Method in class pow.webserver.Log +
    write a string in log file and on stdout +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-19.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-19.html new file mode 100755 index 0000000000..71fb86119e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-19.html @@ -0,0 +1,418 @@ + + + + + + +S-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    +

    +S

    +
    +
    seek(String) - +Method in class pow.webserver.UserTab +
    return the user corresponding to the given login +
    seekAcNetId(String) - +Method in class pow.ivyclient.AcNetIdStorage +
    search the drone net id of a drone from its ivy id + if the drone is a new one, a new net id is requested to the server +
    send(int) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send to the web server the datagram containing the informations + about the aircraft +
    send(int, String, String[]) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send to the web server a specific order with parameters +
    send(int, String) - +Method in class pow.ivyclient.Ivy2Udp +
    This method send a particular message about an aircraft +
    serialize(String) - +Method in class pow.webserver.UserTab +
    Save the object in a file +
    Serveur - Class in pow.webserver
    Class which receive a datagramm from ivy bus via UDP + transforms it into a Pushlet event and send it to the Pushlet server + in order that it will be sent to web clients
    Serveur() - +Constructor for class pow.webserver.Serveur +
      +
    Serveur.IvyEventSource - Class in pow.webserver
     
    Serveur.IvyEventSource() - +Constructor for class pow.webserver.Serveur.IvyEventSource +
      +
    Servlets - Class in nl.justobjects.pushlet.util
    Servlet utilities.
    Servlets() - +Constructor for class nl.justobjects.pushlet.util.Servlets +
      +
    session - +Variable in class nl.justobjects.pushlet.core.Command +
    Pushlet session. +
    Session - Class in nl.justobjects.pushlet.core
    Represents client pushlet session state.
    SESSION_CLASS - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SESSION_ID_GENERATION - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SESSION_ID_GENERATION_RANDOMSTRING - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SESSION_ID_GENERATION_UUID - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SESSION_ID_SIZE - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
    Session management. +
    SESSION_MANAGER_CLASS - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SESSION_TIMEOUT_MINS - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SessionIvy - Class in pow.webserver
    store information about a specific ivy bus which is connected + to the server
    SessionIvy(String, int, AES, InetAddress) - +Constructor for class pow.webserver.SessionIvy +
    create a session which store information about an ivy bus client connected to the server + main information are its net address to send him orders from web users + and drones which are connected to this ivy bus +
    SessionManager - Class in nl.justobjects.pushlet.core
    Manages lifecycle of Sessions.
    setAddress(InetAddress) - +Method in class pow.ivyclient.BusIvy_ +
      +
    setBusIvy(BusIvy_) - +Method in class pow.webserver.SessionIvy +
    store the information of the ivy bus into the ivy session +
    setDebug(boolean) - +Method in class nl.justobjects.pushlet.client.PushletClient +
      +
    setField(String, String) - +Method in class nl.justobjects.pushlet.core.Event +
      +
    setField(String, int) - +Method in class nl.justobjects.pushlet.core.Event +
      +
    setField(String, long) - +Method in class nl.justobjects.pushlet.core.Event +
      +
    setHostnameVerification(boolean) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
    Set the host name verification flag. +
    setIvyInetAddress(InetAddress) - +Method in class pow.webserver.SessionIvy +
    set the ip adress of the ivy bus host +
    setLevel(int) - +Method in class nl.justobjects.pushlet.util.DefaultLogger +
    Set log level +
    setLevel(int) - +Static method in class nl.justobjects.pushlet.util.Log +
    Set log level +
    setLevel(int) - +Method in class nl.justobjects.pushlet.util.Log4jLogger +
      +
    setLevel(int) - +Method in interface nl.justobjects.pushlet.util.PushletLogger +
    Set log level +
    setMode(String) - +Method in class nl.justobjects.pushlet.core.Subscriber +
      +
    setNoCacheHeaders(HttpServletResponse) - +Static method in class nl.justobjects.pushlet.util.Servlets +
    Set HTTP headers to prevent caching. +
    setNom(String) - +Method in class pow.webserver.User +
    specify the login of the user +
    setOrder(DbOrder) - +Method in class pow.webserver.IvyMsg +
    specify how to store the message in database +
    setProxyOptions(String, String, String, String, String, String) - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Set proxy options and optional proxy authentication. +
    setPwd(String) - +Method in class pow.webserver.User +
    specify the user password, it's not stored in clear (md5 hash) +
    setReLogged(boolean) - +Method in class pow.ivyclient.IvyIHM +
    specify whether the module should reconnected or not +
    setResponseEvent(Event) - +Method in class nl.justobjects.pushlet.core.Command +
    Set pushlet response event. +
    setRights(Rights) - +Method in class pow.webserver.User +
    specify the type of right granted to the user +
    setServletContext(ServletContext) - +Method in interface nl.justobjects.pushlet.core.EventSource +
      +
    setServletContext(ServletContext) - +Method in class pow.webserver.Serveur.IvyEventSource +
    method qui renseigne la source sur la servlet qui l'a appelé + modification de la librairie pushlet + Pushlet.java + EventSource.java + EventSourceManager.java +
    setStorage() - +Method in class pow.ivyclient.Ivy2Udp +
    initiate the object which allow to store information about drones +
    setUserAgent(String) - +Method in class nl.justobjects.pushlet.core.Session +
    Set client HTTP UserAgent. +
    SGBDfeeder - Class in pow.webserver
    thread which waits for ivy messages sent by event source (serveur.java) + and stores them into a mysql database + the ivy messages are extracted from a blocking queue (fifo) + parameter of the database are extracted from conf file
    SGBDfeeder(String, String, String, DbMode) - +Constructor for class pow.webserver.SGBDfeeder +
    create a thread which fill the database with the message it extracts from the fifo +
    SOFTWARE_VERSION - +Static variable in class nl.justobjects.pushlet.Version +
    Version info extracted from the .jar manifest file (see build.xml and build.properties). +
    SOURCES_ACTIVATE - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    SSLUtilities - Class in pow.webserver
    This class provide various static methods that relax X509 certificate and + hostname verification while using the SSL over the HTTP protocol.
    SSLUtilities() - +Constructor for class pow.webserver.SSLUtilities +
      +
    SSLUtilities._FakeHostnameVerifier - Class in pow.webserver
    Deprecated. see SSLUtilities.FakeHostnameVerifier.
    SSLUtilities._FakeHostnameVerifier() - +Constructor for class pow.webserver.SSLUtilities._FakeHostnameVerifier +
    Deprecated.   +
    SSLUtilities._FakeX509TrustManager - Class in pow.webserver
    Deprecated. see SSLUtilities.FakeX509TrustManager.
    SSLUtilities._FakeX509TrustManager() - +Constructor for class pow.webserver.SSLUtilities._FakeX509TrustManager +
    Deprecated.   +
    SSLUtilities.FakeHostnameVerifier - Class in pow.webserver
    This class implements a fake hostname verificator, trusting any host + name.
    SSLUtilities.FakeHostnameVerifier() - +Constructor for class pow.webserver.SSLUtilities.FakeHostnameVerifier +
      +
    SSLUtilities.FakeX509TrustManager - Class in pow.webserver
    This class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates.
    SSLUtilities.FakeX509TrustManager() - +Constructor for class pow.webserver.SSLUtilities.FakeX509TrustManager +
      +
    start() - +Method in class nl.justobjects.pushlet.core.BrowserAdapter +
    Generic init. +
    start() - +Method in interface nl.justobjects.pushlet.core.ClientAdapter +
    Start event push. +
    start() - +Method in class nl.justobjects.pushlet.core.Dispatcher +
    Start Dispatcher. +
    start() - +Method in class nl.justobjects.pushlet.core.EventPullSource +
      +
    start(String, ServletContext) - +Static method in class nl.justobjects.pushlet.core.EventSourceManager +
    Initialize event sources from properties file. +
    start() - +Method in class nl.justobjects.pushlet.core.Session +
      +
    start() - +Method in class nl.justobjects.pushlet.core.SessionManager +
    Starts us. +
    start() - +Method in class nl.justobjects.pushlet.core.Subscriber +
      +
    START_DOCUMENT - +Static variable in class nl.justobjects.pushlet.core.BrowserAdapter +
      +
    startHeartBeat() - +Method in class pow.ivyclient.Ivy2Udp +
    create a thread which send heart beat message to the server +
    stop() - +Method in class nl.justobjects.pushlet.core.BrowserAdapter +
    End HTML page in client browser. +
    stop() - +Method in interface nl.justobjects.pushlet.core.ClientAdapter +
    Stop event push. +
    stop() - +Method in class nl.justobjects.pushlet.core.Dispatcher +
    Stop Dispatcher. +
    stop() - +Method in class nl.justobjects.pushlet.core.EventPullSource +
    Stop the event generator thread. +
    stop() - +Method in interface nl.justobjects.pushlet.core.EventSource +
    Halt the event source. +
    stop() - +Static method in class nl.justobjects.pushlet.core.EventSourceManager +
    Halt event sources. +
    stop() - +Method in class nl.justobjects.pushlet.core.Session +
      +
    stop() - +Method in class nl.justobjects.pushlet.core.SessionManager +
    Stopis us. +
    stop() - +Method in class nl.justobjects.pushlet.core.Subscriber +
      +
    stop() - +Method in class pow.webserver.Serveur.IvyEventSource +
    Desactivate the event source. +
    stop_thread() - +Method in class pow.ivyclient.HeartBeat +
    stop the heartbeat thread by ending the infinite loop +
    stop_thread() - +Method in class pow.ivyclient.Ivy2Udp +
    stop all the thread Ivy2Udp , HeartBeat and ivy2UdpWriting +
    stop_thread() - +Method in class pow.webserver.HeartBeat +
    stop the heartbeat process of the server +
    stopListen() - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Stop the listener. +
    StrictSSLProtocolSocketFactory - Class in pow.webserver
    A SecureProtocolSocketFactory that uses JSSE to create + SSL sockets.
    StrictSSLProtocolSocketFactory(boolean) - +Constructor for class pow.webserver.StrictSSLProtocolSocketFactory +
    Constructor for StrictSSLProtocolSocketFactory. +
    StrictSSLProtocolSocketFactory() - +Constructor for class pow.webserver.StrictSSLProtocolSocketFactory +
    Constructor for StrictSSLProtocolSocketFactory. +
    SUBJECT_META - +Static variable in interface nl.justobjects.pushlet.core.Protocol +
      +
    SUBJECT_META_JOINS - +Static variable in interface nl.justobjects.pushlet.core.Protocol +
      +
    SUBJECT_META_SUBS - +Static variable in interface nl.justobjects.pushlet.core.Protocol +
      +
    SUBJECT_SEPARATOR - +Static variable in class nl.justobjects.pushlet.core.Subscription +
      +
    subscribe(String, String) - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Subscribes, returning subscription id. +
    subscribe(String) - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Subscribes, returning subscription id. +
    Subscriber - Class in nl.justobjects.pushlet.core
    Handles data channel between dispatcher and client.
    SUBSCRIBER_CLASS - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    Subscription - Class in nl.justobjects.pushlet.core
    Represents single subject subscription
    SUBSCRIPTION_CLASS - +Static variable in interface nl.justobjects.pushlet.core.ConfigDefs +
      +
    Sys - Class in nl.justobjects.pushlet.util
    Utilities that interact with the underlying OS/JVM.
    Sys() - +Constructor for class nl.justobjects.pushlet.util.Sys +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-2.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-2.html new file mode 100755 index 0000000000..ef7517cb32 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-2.html @@ -0,0 +1,151 @@ + + + + + + +B-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +B

    +
    +
    bindMsg2Ivy() - +Method in class pow.ivyclient.Ivy2Udp +
    This method binds the object to some messages + of the bus Ivy. +
    BusIvy_ - Class in pow.ivyclient
    inner representation of an ivy bus + store the drones' information about the drones which belong to this ivy bus + store the IP adress of the machine where the ivy bus is working
    BusIvy_() - +Constructor for class pow.ivyclient.BusIvy_ +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-20.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-20.html new file mode 100755 index 0000000000..fa92eac20e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-20.html @@ -0,0 +1,195 @@ + + + + + + +T-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    +

    +T

    +
    +
    toQueryString() - +Method in class nl.justobjects.pushlet.core.Event +
    Convert to HTTP query string. +
    toString() - +Method in class nl.justobjects.pushlet.core.Controller +
      +
    toString() - +Method in class nl.justobjects.pushlet.core.Event +
      +
    toString() - +Method in class nl.justobjects.pushlet.core.Session +
      +
    toString() - +Method in class nl.justobjects.pushlet.core.Subscriber +
      +
    toString() - +Method in exception nl.justobjects.pushlet.util.PushletException +
      +
    toString() - +Method in class pow.ivyclient.AcNetId +
    return information about the drone in a string format +
    toString() - +Method in exception pow.ivyclient.IvyConnectionExeption +
    display the exception on stdout +
    toString() - +Method in exception pow.webserver.AlreadyRegisteredUserException +
      +
    toXML(boolean) - +Method in class nl.justobjects.pushlet.core.Event +
      +
    toXML() - +Method in class nl.justobjects.pushlet.core.Event +
      +
    trace(String) - +Method in class nl.justobjects.pushlet.util.DefaultLogger +
    Log message for trace level. +
    trace(String) - +Static method in class nl.justobjects.pushlet.util.Log +
    Log message for trace level. +
    trace(String) - +Method in class nl.justobjects.pushlet.util.Log4jLogger +
      +
    trace(String) - +Method in interface nl.justobjects.pushlet.util.PushletLogger +
    Log message for trace level. +
    trustAllHostnames() - +Static method in class pow.webserver.SSLUtilities +
    Set the default Hostname Verifier to an instance of a fake class that + trust all hostnames. +
    trustAllHttpsCertificates() - +Static method in class pow.webserver.SSLUtilities +
    Set the default X509 Trust Manager to an instance of a fake class that + trust all certificates, even the self-signed ones. +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-21.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-21.html new file mode 100755 index 0000000000..2f01bc8594 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-21.html @@ -0,0 +1,174 @@ + + + + + + +U-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    +

    +U

    +
    +
    unicast(Event, String) - +Method in class nl.justobjects.pushlet.core.Dispatcher +
    Send event to specific subscriber. +
    unserialize(String) - +Static method in class pow.webserver.UserTab +
    load the object from a file +
    unsubscribe(String) - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Unsubscribes with subscription id. +
    unsubscribe() - +Method in class nl.justobjects.pushlet.client.PushletClient +
    Unsubscribes from all subjects. +
    updateTime() - +Method in class pow.ivyclient.BusIvy_ +
    update the 'inner clock' of the object when a message for this bus is detected + useful to know if the bus is still alive +
    uploadConfFile(AcNetId) - +Method in class pow.ivyclient.AcNetIdStorage +
    upload de fichier de conf sur le serveur + verifier que ca marche sur long fichier + si probleme changer avec : + factory.setSizeThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + upload.setSizeMax(yourMaxRequestSize); +
    User - Class in pow.webserver
    represents a ivy or a web user account + for the web user the account nest also the list of drones that the user can control + the list contains the ivy name of the drone (MJ5, TJ1...).
    User(String, String, Rights) - +Constructor for class pow.webserver.User +
    create a user account +
    UserTab - Class in pow.webserver
    User objects are stored in a UserTab object which can be serialized in a file on the server disk
    UserTab() - +Constructor for class pow.webserver.UserTab +
    create a empty list of users +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-22.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-22.html new file mode 100755 index 0000000000..1f47703d80 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-22.html @@ -0,0 +1,181 @@ + + + + + + +V-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    +

    +V

    +
    +
    valueOf(String) - +Static method in enum pow.ivyclient.AcStatus +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.DbMode +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.DbOrder +
    Returns the enum constant of this type with the specified name. +
    valueOf(String) - +Static method in enum pow.webserver.Rights +
    Returns the enum constant of this type with the specified name. +
    values() - +Static method in enum pow.ivyclient.AcStatus +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.DbMode +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.DbOrder +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    values() - +Static method in enum pow.webserver.Rights +
    Returns an array containing the constants of this enum type, in +the order they are declared. +
    verify(String, String) - +Method in class pow.webserver.SSLUtilities._FakeHostnameVerifier +
    Deprecated. Always return true, indicating that the host name is an + acceptable match with the server's authentication scheme. +
    verify(String, SSLSession) - +Method in class pow.webserver.SSLUtilities.FakeHostnameVerifier +
    Always return true, indicating that the host name is + an acceptable match with the server's authentication scheme. +
    Version - Class in nl.justobjects.pushlet
    Version info class.
    Version() - +Constructor for class nl.justobjects.pushlet.Version +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-23.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-23.html new file mode 100755 index 0000000000..0fbdc3afaf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-23.html @@ -0,0 +1,172 @@ + + + + + + +W-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    +

    +W

    +
    +
    warn(String) - +Method in class nl.justobjects.pushlet.core.Session +
    Exceptional print util. +
    warn(String) - +Method in class nl.justobjects.pushlet.util.DefaultLogger +
    Log message for warning level. +
    warn(String, Throwable) - +Method in class nl.justobjects.pushlet.util.DefaultLogger +
    Log message for warning level with exception. +
    warn(String) - +Static method in class nl.justobjects.pushlet.util.Log +
    Log message for warning level. +
    warn(String, Throwable) - +Static method in class nl.justobjects.pushlet.util.Log +
    Log message for warning level with exception. +
    warn(String) - +Method in class nl.justobjects.pushlet.util.Log4jLogger +
      +
    warn(String, Throwable) - +Method in class nl.justobjects.pushlet.util.Log4jLogger +
      +
    warn(String) - +Method in interface nl.justobjects.pushlet.util.PushletLogger +
    Log message for warning level. +
    warn(String, Throwable) - +Method in interface nl.justobjects.pushlet.util.PushletLogger +
    Log message for warning level with exception. +
    write(String) - +Method in class pow.webserver.Log +
    write a string in log file and on stdout +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E F G H I J K L M N O P Q R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-3.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-3.html new file mode 100755 index 0000000000..fb7a78756a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-3.html @@ -0,0 +1,177 @@ + + + + + + +C-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +C

    +
    +
    canControl(String) - +Method in class pow.webserver.User +
    inform whether the user can pilot a drone or not +
    checkClientTrusted(X509Certificate[], String) - +Method in class pow.webserver.SSLUtilities.FakeX509TrustManager +
    Always trust for client SSL chain peer certificate + chain with any authType authentication types. +
    checkServerTrusted(X509Certificate[], String) - +Method in class pow.webserver.SSLUtilities.FakeX509TrustManager +
    Always trust for server SSL chain peer certificate + chain with any authType exchange algorithm types. +
    checkUser(String, String) - +Method in class pow.webserver.UserTab +
    Check if the password of the user having the specified login is correct +
    clearListDrone() - +Method in class pow.webserver.User +
    reset the list of drone that the web user can control +
    Conf - Class in pow.webserver
    store useful data about the server configuration + and database connection by + reading a specific file place in the 'conf' folder of + the web application
    Conf(String, String) - +Constructor for class pow.webserver.Conf +
      +
    createSocket(String, int, InetAddress, int) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
      +
    createSocket(String, int, InetAddress, int, HttpConnectionParams) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
    Attempts to get a new socket connection to the given host within the given time limit. +
    createSocket(String, int) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
      +
    createSocket(Socket, String, int, boolean) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-4.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-4.html new file mode 100755 index 0000000000..75db18322f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-4.html @@ -0,0 +1,152 @@ + + + + + + +D-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +D

    +
    +
    DbMode - Enum in pow.webserver
    specify how the database works
    DbOrder - Enum in pow.webserver
    represents 4 kind of message stored in database + CONNECT first connection of an ivy bus --> inform db + DECONNECT ivy bus deconnected --> inform db + ADD add message to db
    decrypt(byte[]) - +Method in class pow.AES +
    decrypt a byte array with AES algorithm + see @link org.apache.commons.codec.binary.Hex to convert byte Array into hexString +
    displayDrones() - +Method in class pow.ivyclient.BusIvy_ +
    display information on stdout about the drones present on the bus +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-5.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-5.html new file mode 100755 index 0000000000..5d453456a1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-5.html @@ -0,0 +1,151 @@ + + + + + + +E-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +E

    +
    +
    encode(String) - +Static method in class pow.webserver.Md5 +
      +
    encrypt(byte[]) - +Method in class pow.AES +
    encrypt a byte array with AES algorithm +
    equals(Object) - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-6.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-6.html new file mode 100755 index 0000000000..4aa4bb7cdb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-6.html @@ -0,0 +1,314 @@ + + + + + + +G-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +G

    +
    +
    getAcceptedIssuers() - +Method in class pow.webserver.SSLUtilities._FakeX509TrustManager +
    Deprecated. Return an empty array of certificate authority certificates which + are trusted for authenticating peers. +
    getAcceptedIssuers() - +Method in class pow.webserver.SSLUtilities.FakeX509TrustManager +
    Return an empty array of certificate authority certificates which + are trusted for authenticating peers. +
    getAcIvyId(int) - +Method in class pow.ivyclient.AcNetIdStorage +
    do the link between the id of the drone on the web and is true id on its ivy bus +
    getAcNetId(String) - +Method in class pow.ivyclient.AcNetIdStorage +
    Return the identity object of the drone on the web +
    getAddress() - +Method in class pow.ivyclient.BusIvy_ +
    provides the IP adress of the host hosting the bus +
    getBusIvy() - +Method in class pow.webserver.SessionIvy +
      +
    getCipher() - +Method in class pow.webserver.SessionIvy +
      +
    getColor() - +Method in class pow.ivyclient.AcNetId +
    provides the color of the drone on the GCS view +
    getDataBaseName() - +Method in class pow.webserver.Conf +
      +
    getDataEventTimeoutTime() - +Method in class pow.webserver.Conf +
      +
    getDbMode() - +Method in class pow.webserver.Conf +
      +
    getDBPassword() - +Method in class pow.webserver.Conf +
      +
    getDBUserName() - +Method in class pow.webserver.Conf +
      +
    getDieEventTimeoutTime() - +Method in class pow.webserver.Conf +
      +
    getDrones() - +Method in class pow.ivyclient.BusIvy_ +
    get a array list containing the ivy id of the drones present on the bus +
    getHostnameVerification() - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
    Gets the status of the host name verification flag. +
    getIdOnIvy() - +Method in class pow.ivyclient.AcNetId +
    provides the id of the drone on the ivy bus +
    getIdOnWeb() - +Method in class pow.ivyclient.AcNetId +
    provides the id of the drone on the web +
    getItrUsr(String) - +Method in class pow.webserver.UserTab +
    return the list of all drone which may be controlled by the user +
    getIvyInetAddress() - +Method in class pow.webserver.SessionIvy +
      +
    getIvyMsg() - +Method in class pow.webserver.IvyMsg +
      +
    getIvyWebId() - +Method in class pow.ivyclient.Ivy2Udp +
    return the id of the bus for the server + this id is provided by the server and is unique +
    getKey() - +Method in class pow.AES +
    get the cipher key +
    getListDrone() - +Method in class pow.webserver.User +
    the list of drone that the web user can control +
    getLogin() - +Method in class pow.webserver.SessionIvy +
      +
    getLogin() - +Method in class pow.webserver.User +
      +
    getLoginIterator() - +Method in class pow.webserver.UserTab +
      +
    getName() - +Method in class pow.ivyclient.AcNetId +
    provides the name of the drone on the ivy bus +
    getNewDroneWebId(String) - +Method in class pow.ivyclient.AcNetIdStorage +
    ask a unique new web id to the server for a new drone detected on the ivy bus +
    getNumMsg() - +Method in class pow.webserver.IvyMsg +
      +
    getOrder() - +Method in class pow.webserver.IvyMsg +
      +
    getOrderResponseTimeout() - +Method in class pow.webserver.Conf +
      +
    getParamsEncrypt() - +Method in class pow.AES +
    get the init parameter of the cipher object in order to initialyse correctly a + remote cipher +
    getPassword() - +Method in class pow.webserver.User +
      +
    getPlnPath() - +Method in class pow.ivyclient.AcNetId +
    provides the path of the xml file (on the server) containing + the information of the flightplan of the drone + (waypoints and blocks of instructions) +
    getQueueFIFO() - +Method in class pow.webserver.SGBDfeeder +
      +
    getRights() - +Method in class pow.webserver.User +
      +
    getServerName() - +Method in class pow.ivyclient.PowUrl +
    provides the server name to which the module is connected +
    getSetItr() - +Method in class pow.webserver.User +
      +
    getSettingPath() - +Method in class pow.ivyclient.AcNetId +
    provides the path of the xml file (on the server) containing the settings + of the drone +
    getSocketTimeout() - +Method in class pow.webserver.Conf +
      +
    getStorage() - +Method in class pow.ivyclient.Ivy2Udp +
    provides the structure where data about the drone present on the ivy bus are stored +
    getTime2checkDeadBuses() - +Method in class pow.webserver.Conf +
      +
    getTime2resetFilter() - +Method in class pow.webserver.Conf +
      +
    getTimeMsg() - +Method in class pow.webserver.IvyMsg +
      +
    getTimeToSendValues() - +Method in class pow.webserver.Conf +
      +
    getUdpSize() - +Method in class pow.webserver.Conf +
      +
    getWebId() - +Method in class pow.ivyclient.Ivy2Udp +
    request a single id for the bus to the web server + method get + see @link http://hc.apache.org/httpclient-3.x/tutorial.html + see @link blogs.sun.com/gc/entry/unable_to_find_valid_certification + see @link http://blogs.sun.com/andreas/entry/no_more_unable_to_find +
    getWebId(String) - +Method in class pow.webserver.Ivy2TomcatHttpServer +
    contact database if any to have a new webid +
    getWebId() - +Method in class pow.webserver.IvyMsg +
      +
    getWebId() - +Method in class pow.webserver.SessionIvy +
      +
    getWebUrl() - +Method in class pow.ivyclient.PowUrl +
    provides the complete URL to log on the POW server +
    Greeting - Class in pow.webserver
    Servlet implementation class Greeting + Handles the connection request from a new web client + check the login's information and rights
    Greeting() - +Constructor for class pow.webserver.Greeting +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-7.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-7.html new file mode 100755 index 0000000000..00c9ae97ef --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-7.html @@ -0,0 +1,152 @@ + + + + + + +H-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +H

    +
    +
    hashCode() - +Method in class pow.webserver.StrictSSLProtocolSocketFactory +
      +
    HeartBeat - Class in pow.ivyclient
    thread which send a periodic message to a client or server to say that the connection + is still alive (period has to be less than the socket timeout of the the server)
    HeartBeat(AES, int, InetAddress, int, long) - +Constructor for class pow.ivyclient.HeartBeat +
    define the parameter of the heartbeat message +
    HeartBeat - Class in pow.webserver
     
    HeartBeat(ServletContext, int, int) - +Constructor for class pow.webserver.HeartBeat +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-8.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-8.html new file mode 100755 index 0000000000..381dcb3fdc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-8.html @@ -0,0 +1,209 @@ + + + + + + +I-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +I

    +
    +
    init(ServletConfig) - +Method in class pow.webserver.AjaxRqst +
    init the servlet +
    init(ServletConfig) - +Method in class pow.webserver.Greeting +
      +
    init(ServletConfig) - +Method in class pow.webserver.Ivy2TomcatHttpServer +
      +
    insert(User) - +Method in class pow.webserver.UserTab +
    insert a user in the list +
    InstallCert - Class in pow
    query the server about its certificate and create a 'jssecacerts' file to copy + into /usr/lib/jvm/java-x-x/jre/lib/security + allow a java http client to connect to https server
    InstallCert() - +Constructor for class pow.InstallCert +
      +
    isAlive() - +Method in class pow.ivyclient.BusIvy_ +
    inform if the bus is alive +
    isClientTrusted(X509Certificate[]) - +Method in class pow.webserver.SSLUtilities._FakeX509TrustManager +
    Deprecated. Always return true, trusting for client SSL + chain peer certificate chain. +
    isInside(String) - +Method in class pow.webserver.UserTab +
    check if an user with this logging exists yet +
    isNew(String) - +Method in class pow.ivyclient.MsgFilter +
    inform whether the message is new or not +
    isOwnBy(int) - +Method in class pow.ivyclient.BusIvy_ +
    inform if a drone is present or not on the bus +
    IsPwdTrue(String) - +Method in class pow.webserver.User +
    check if the password given in argument corresponds to the password user +
    isServerTrusted(X509Certificate[]) - +Method in class pow.webserver.SSLUtilities._FakeX509TrustManager +
    Deprecated. Always return true, trusting for server SSL + chain peer certificate chain. +
    Ivy2TomcatHttpServer - Class in pow.webserver
    Handles the connection request from a new ivy bus + provide a unique id for the ivy bus + provide a unique id for each new drone on a ivy bus + handles the uploading of the configuration files for each new drone on a ivy bus
    Ivy2TomcatHttpServer() - +Constructor for class pow.webserver.Ivy2TomcatHttpServer +
      +
    Ivy2Udp - Class in pow.ivyclient
    It contact the server to get an identifier, some configuration parameter and + the key to encrypt and decrypt messages.
    Ivy2Udp(IvyIHM, PowUrl, String, String) - +Constructor for class pow.ivyclient.Ivy2Udp +
    create an object which listens on the local ivy bus and send messages to the server +
    Ivy2UdpWriting - Class in pow.ivyclient
    This class aims to give order to the drones according to the datagrams it + receive from the web
    IvyConnectionExeption - Exception in pow.ivyclient
     
    IvyConnectionExeption(String) - +Constructor for exception pow.ivyclient.IvyConnectionExeption +
    create an ivy exception with a particular message +
    IvyIHM - Class in pow.ivyclient
    represent the interface for a ivy user who wants to connect a bus ivy to + the web server
    IvyIHM() - +Constructor for class pow.ivyclient.IvyIHM +
    construct the interface +
    IvyMsg - Class in pow.webserver
    represents information which are sended by the source event to the database on the queue fifo
    IvyMsg(int, long, String, String, DbOrder) - +Constructor for class pow.webserver.IvyMsg +
      +
    IvyMsg(int, long, String, String) - +Constructor for class pow.webserver.IvyMsg +
      +
    IvyMsg(int) - +Constructor for class pow.webserver.IvyMsg +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-9.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-9.html new file mode 100755 index 0000000000..a1977be29b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index-files/index-9.html @@ -0,0 +1,146 @@ + + + + + + +K-Index + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    +

    +K

    +
    +
    kill() - +Method in class pow.webserver.SGBDfeeder +
    stop the thread by ending run method + used caused Thread.stop is now deprecated +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +A B C D E G H I K L M P R S T U V W
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index.html new file mode 100755 index 0000000000..3e4fc5343b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/index.html @@ -0,0 +1,39 @@ + + + + + + +Generated Documentation (Untitled) + + + + + + + + + + + +<H2> +Frame Alert</H2> + +<P> +This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. +<BR> +Link to<A HREF="overview-summary.html">Non-frame version.</A> + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/Version.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/Version.html new file mode 100755 index 0000000000..b99c8fc894 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/Version.html @@ -0,0 +1,293 @@ + + + + + + +Version + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet +
    +Class Version

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.Version
    +
    +
    +
    +
    public class Version
    extends java.lang.Object
    + + +

    +Version info class. + +

    Purpose

    + Extract version info from jar manifest file. +

    + +

    +

    +
    Version:
    +
    $Id: Version.java,v 1.4 2006/05/06 00:10:11 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    +
    + +

    + + + + + + + + + + + + + + + +
    +Field Summary
    +static java.lang.StringBUILD_DATE + +
    +           
    +static java.lang.StringSOFTWARE_VERSION + +
    +          Version info extracted from the .jar manifest file (see build.xml and build.properties).
    +  + + + + + + + + + + +
    +Constructor Summary
    Version() + +
    +           
    +  + + + + + + + +
    +Method Summary
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +SOFTWARE_VERSION

    +
    +public static final java.lang.String SOFTWARE_VERSION
    +
    +
    Version info extracted from the .jar manifest file (see build.xml and build.properties). +

    +

    +
    +
    +
    + +

    +BUILD_DATE

    +
    +public static final java.lang.String BUILD_DATE
    +
    +
    +
    +
    + + + + + + + + +
    +Constructor Detail
    + +

    +Version

    +
    +public Version()
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/class-use/Version.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/class-use/Version.html new file mode 100755 index 0000000000..3c6002aceb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/class-use/Version.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.Version + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.Version

    +
    +No usage of nl.justobjects.pushlet.Version +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClient.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClient.html new file mode 100755 index 0000000000..3a1bfe9e6f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClient.html @@ -0,0 +1,696 @@ + + + + + + +PushletClient + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.client +
    +Class PushletClient

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.client.PushletClient
    +
    +
    +
    All Implemented Interfaces:
    Protocol
    +
    +
    +
    +
    public class PushletClient
    extends java.lang.Object
    implements Protocol
    + + +

    +Client API for Java HTTP client applets or apps. +

    + Use this class within Java client applications or applets. + Implement a PushletClientListener to receive callbacks for + data-related Event objects pushed by the server. +

    + This class may also be used as a base class and be extended + for custom clients, hence the presence of many proteced methods. +

    + +

    +

    +
    Version:
    +
    $Id: PushletClient.java,v 1.19 2009/06/04 12:46:35 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    See Also:
    PushletClientListener, +nl.justobjects.pushlet.test.PushletApplet, +nl.justobjects.pushlet.test.PushletPingApplication
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + + + + +
    +Constructor Summary
    PushletClient(java.lang.String aPushletURL) + +
    +          Constructor with full pushlet URL.
    PushletClient(java.lang.String aHost, + int aPort) + +
    +          Constructor with host and port using default URI.
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidjoin() + +
    +          Join server, starts session.
    + voidjoinListen(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Immediate listener: joins/subscribes and listens in one action.
    + voidleave() + +
    +          Leave server, stops session.
    + voidlisten(PushletClientListener aListener) + +
    +          Open data channel.
    + voidlisten(PushletClientListener aListener, + java.lang.String aMode) + +
    +          Open data channel in stream or push mode.
    + voidlisten(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Open data channel in stream or push mode with a subject.
    + voidpublish(java.lang.String aSubject, + java.util.Map theAttributes) + +
    +          Publish an event through server.
    + voidsetDebug(boolean b) + +
    +           
    + voidsetProxyOptions(java.lang.String aProxyHost, + java.lang.String aProxyPort, + java.lang.String theNonProxyHosts, + java.lang.String aUserName, + java.lang.String aPassword, + java.lang.String anNTLMDomain) + +
    +          Set proxy options and optional proxy authentication.
    + voidstopListen() + +
    +          Stop the listener.
    + java.lang.Stringsubscribe(java.lang.String aSubject) + +
    +          Subscribes, returning subscription id.
    + java.lang.Stringsubscribe(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Subscribes, returning subscription id.
    + voidunsubscribe() + +
    +          Unsubscribes from all subjects.
    + voidunsubscribe(java.lang.String aSubscriptionId) + +
    +          Unsubscribes with subscription id.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +PushletClient

    +
    +public PushletClient(java.lang.String aPushletURL)
    +
    +
    Constructor with full pushlet URL. +

    +

    +
    + +

    +PushletClient

    +
    +public PushletClient(java.lang.String aHost,
    +                     int aPort)
    +
    +
    Constructor with host and port using default URI. +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +setProxyOptions

    +
    +public void setProxyOptions(java.lang.String aProxyHost,
    +                            java.lang.String aProxyPort,
    +                            java.lang.String theNonProxyHosts,
    +                            java.lang.String aUserName,
    +                            java.lang.String aPassword,
    +                            java.lang.String anNTLMDomain)
    +
    +
    Set proxy options and optional proxy authentication. +

    + Contributed by Dele Olajide + See http://groups.yahoo.com/group/pushlet/message/634 +

    + Usage: + PushletClient pushletClient = new PushletClient("http:://www.domain.com/pushlet"); + pushletClient.setProxyOptions("proxy.bla.com", "8080", ....); +

    + use pushletClient further as normal +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +join

    +
    +public void join()
    +          throws PushletException
    +
    +
    Join server, starts session. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +leave

    +
    +public void leave()
    +           throws PushletException
    +
    +
    Leave server, stops session. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +listen

    +
    +public void listen(PushletClientListener aListener)
    +            throws PushletException
    +
    +
    Open data channel. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +listen

    +
    +public void listen(PushletClientListener aListener,
    +                   java.lang.String aMode)
    +            throws PushletException
    +
    +
    Open data channel in stream or push mode. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +listen

    +
    +public void listen(PushletClientListener aListener,
    +                   java.lang.String aMode,
    +                   java.lang.String aSubject)
    +            throws PushletException
    +
    +
    Open data channel in stream or push mode with a subject. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +joinListen

    +
    +public void joinListen(PushletClientListener aListener,
    +                       java.lang.String aMode,
    +                       java.lang.String aSubject)
    +                throws PushletException
    +
    +
    Immediate listener: joins/subscribes and listens in one action. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +publish

    +
    +public void publish(java.lang.String aSubject,
    +                    java.util.Map theAttributes)
    +             throws PushletException
    +
    +
    Publish an event through server. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +subscribe

    +
    +public java.lang.String subscribe(java.lang.String aSubject,
    +                                  java.lang.String aLabel)
    +                           throws PushletException
    +
    +
    Subscribes, returning subscription id. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +subscribe

    +
    +public java.lang.String subscribe(java.lang.String aSubject)
    +                           throws PushletException
    +
    +
    Subscribes, returning subscription id. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +unsubscribe

    +
    +public void unsubscribe(java.lang.String aSubscriptionId)
    +                 throws PushletException
    +
    +
    Unsubscribes with subscription id. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +unsubscribe

    +
    +public void unsubscribe()
    +                 throws PushletException
    +
    +
    Unsubscribes from all subjects. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +stopListen

    +
    +public void stopListen()
    +                throws PushletException
    +
    +
    Stop the listener. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +setDebug

    +
    +public void setDebug(boolean b)
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClientListener.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClientListener.html new file mode 100755 index 0000000000..dc0dc06a3d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/PushletClientListener.html @@ -0,0 +1,314 @@ + + + + + + +PushletClientListener + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.client +
    +Interface PushletClientListener

    +
    +
    All Superinterfaces:
    Protocol
    +
    +
    +
    +
    public interface PushletClientListener
    extends Protocol
    + + +

    +Interface for listener of the PushletClient object. +

    + +

    +

    +
    Version:
    +
    $Id: PushletClientListener.java,v 1.5 2005/02/21 11:50:37 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidonAbort(Event theEvent) + +
    +          Abort event from server.
    + voidonData(Event theEvent) + +
    +          Data event from server.
    + voidonError(java.lang.String message) + +
    +          Error occurred.
    + voidonHeartbeat(Event theEvent) + +
    +          Heartbeat event from server.
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +onAbort

    +
    +void onAbort(Event theEvent)
    +
    +
    Abort event from server. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +onData

    +
    +void onData(Event theEvent)
    +
    +
    Data event from server. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +onHeartbeat

    +
    +void onHeartbeat(Event theEvent)
    +
    +
    Heartbeat event from server. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +onError

    +
    +void onError(java.lang.String message)
    +
    +
    Error occurred. +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClient.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClient.html new file mode 100755 index 0000000000..ee9de5ed2a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClient.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.client.PushletClient + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.client.PushletClient

    +
    +No usage of nl.justobjects.pushlet.client.PushletClient +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClientListener.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClientListener.html new file mode 100755 index 0000000000..54096cc2e6 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/class-use/PushletClientListener.html @@ -0,0 +1,209 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.client.PushletClientListener + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.client.PushletClientListener

    +
    + + + + + + + + + +
    +Packages that use PushletClientListener
    nl.justobjects.pushlet.client  
    +  +

    + + + + + +
    +Uses of PushletClientListener in nl.justobjects.pushlet.client
    +  +

    + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.client with parameters of type PushletClientListener
    + voidPushletClient.joinListen(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Immediate listener: joins/subscribes and listens in one action.
    + voidPushletClient.listen(PushletClientListener aListener) + +
    +          Open data channel.
    + voidPushletClient.listen(PushletClientListener aListener, + java.lang.String aMode) + +
    +          Open data channel in stream or push mode.
    + voidPushletClient.listen(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Open data channel in stream or push mode with a subject.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-frame.html new file mode 100755 index 0000000000..5e670aaa30 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-frame.html @@ -0,0 +1,43 @@ + + + + + + +nl.justobjects.pushlet.client + + + + + + + + + + + +nl.justobjects.pushlet.client + + + + +
    +Interfaces  + +
    +PushletClientListener
    + + + + + + +
    +Classes  + +
    +PushletClient
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-summary.html new file mode 100755 index 0000000000..c573989e6d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-summary.html @@ -0,0 +1,171 @@ + + + + + + +nl.justobjects.pushlet.client + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package nl.justobjects.pushlet.client +

    + + + + + + + + + +
    +Interface Summary
    PushletClientListenerInterface for listener of the PushletClient object.
    +  + +

    + + + + + + + + + +
    +Class Summary
    PushletClientClient API for Java HTTP client applets or apps.
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-tree.html new file mode 100755 index 0000000000..ac3b686de0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-tree.html @@ -0,0 +1,161 @@ + + + + + + +nl.justobjects.pushlet.client Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package nl.justobjects.pushlet.client +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    +
      +
    • java.lang.Object +
    +

    +Interface Hierarchy +

    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-use.html new file mode 100755 index 0000000000..090031e6d3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/client/package-use.html @@ -0,0 +1,170 @@ + + + + + + +Uses of Package nl.justobjects.pushlet.client + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    nl.justobjects.pushlet.client

    +
    + + + + + + + + + +
    +Packages that use nl.justobjects.pushlet.client
    nl.justobjects.pushlet.client  
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.client used by nl.justobjects.pushlet.client
    PushletClientListener + +
    +          Interface for listener of the PushletClient object.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/BrowserAdapter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/BrowserAdapter.html new file mode 100755 index 0000000000..f258736f54 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/BrowserAdapter.html @@ -0,0 +1,389 @@ + + + + + + +BrowserAdapter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class BrowserAdapter

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.BrowserAdapter
    +
    +
    +
    All Implemented Interfaces:
    ClientAdapter, Protocol
    +
    +
    +
    +
    public class BrowserAdapter
    extends java.lang.Object
    implements ClientAdapter, Protocol
    + + +

    +Generic implementation of ClientAdapter for browser clients. +

    + +

    +

    +
    Version:
    +
    $Id: BrowserAdapter.java,v 1.6 2007/11/09 13:15:35 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + +
    +Field Summary
    +static java.lang.StringEND_DOCUMENT + +
    +           
    +static java.lang.StringSTART_DOCUMENT + +
    +           
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + +
    +Constructor Summary
    BrowserAdapter(javax.servlet.http.HttpServletResponse aServletResponse) + +
    +          Constructor.
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidpush(Event anEvent) + +
    +          Push Event to client.
    + voidstart() + +
    +          Generic init.
    + voidstop() + +
    +          End HTML page in client browser.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +START_DOCUMENT

    +
    +public static final java.lang.String START_DOCUMENT
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +END_DOCUMENT

    +
    +public static final java.lang.String END_DOCUMENT
    +
    +
    +
    See Also:
    Constant Field Values
    +
    + + + + + + + + +
    +Constructor Detail
    + +

    +BrowserAdapter

    +
    +public BrowserAdapter(javax.servlet.http.HttpServletResponse aServletResponse)
    +
    +
    Constructor. +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +start

    +
    +public void start()
    +           throws java.io.IOException
    +
    +
    Generic init. +

    +

    +
    Specified by:
    start in interface ClientAdapter
    +
    +
    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +push

    +
    +public void push(Event anEvent)
    +          throws java.io.IOException
    +
    +
    Push Event to client. +

    +

    +
    Specified by:
    push in interface ClientAdapter
    +
    +
    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    End HTML page in client browser. +

    +

    +
    Specified by:
    stop in interface ClientAdapter
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ClientAdapter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ClientAdapter.html new file mode 100755 index 0000000000..201dafd676 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ClientAdapter.html @@ -0,0 +1,272 @@ + + + + + + +ClientAdapter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Interface ClientAdapter

    +
    +
    All Known Implementing Classes:
    BrowserAdapter
    +
    +
    +
    +
    public interface ClientAdapter
    + + +

    +Adapter interface for encapsulation of specific HTTP clients. +

    + +

    +

    +
    Version:
    +
    $Id: ClientAdapter.java,v 1.8 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidpush(Event anEvent) + +
    +          Push single Event to client.
    + voidstart() + +
    +          Start event push.
    + voidstop() + +
    +          Stop event push.
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +start

    +
    +void start()
    +           throws java.io.IOException
    +
    +
    Start event push. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +push

    +
    +void push(Event anEvent)
    +          throws java.io.IOException
    +
    +
    Push single Event to client. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +stop

    +
    +void stop()
    +          throws java.io.IOException
    +
    +
    Stop event push. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Command.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Command.html new file mode 100755 index 0000000000..73bea47fbe --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Command.html @@ -0,0 +1,425 @@ + + + + + + +Command + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Command

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Command
    +
    +
    +
    All Implemented Interfaces:
    Protocol
    +
    +
    +
    +
    public class Command
    extends java.lang.Object
    implements Protocol
    + + +

    +Wraps pushlet request/response data. +

    + +

    +

    +
    Version:
    +
    $Id: Command.java,v 1.4 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + +
    +Field Summary
    + javax.servlet.http.HttpServletRequesthttpReq + +
    +          HTTP Servlet GET/POST request.
    + javax.servlet.http.HttpServletResponsehttpRsp + +
    +          HTTP Servlet GET/POST response.
    + EventreqEvent + +
    +          Pushlet request event.
    + Sessionsession + +
    +          Pushlet session.
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static Commandcreate(Session aSession, + Event aReqEvent, + javax.servlet.http.HttpServletRequest aHTTPReq, + javax.servlet.http.HttpServletResponse aHTTPRsp) + +
    +          Create new Command object.
    + ClientAdaptergetClientAdapter() + +
    +          Get client adapter for request.
    + EventgetResponseEvent() + +
    +          Get pushlet response event.
    + voidsetResponseEvent(Event aResponseEvent) + +
    +          Set pushlet response event.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +reqEvent

    +
    +public final Event reqEvent
    +
    +
    Pushlet request event. +

    +

    +
    +
    +
    + +

    +httpReq

    +
    +public final javax.servlet.http.HttpServletRequest httpReq
    +
    +
    HTTP Servlet GET/POST request. +

    +

    +
    +
    +
    + +

    +httpRsp

    +
    +public final javax.servlet.http.HttpServletResponse httpRsp
    +
    +
    HTTP Servlet GET/POST response. +

    +

    +
    +
    +
    + +

    +session

    +
    +public final Session session
    +
    +
    Pushlet session. +

    +

    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +create

    +
    +public static Command create(Session aSession,
    +                             Event aReqEvent,
    +                             javax.servlet.http.HttpServletRequest aHTTPReq,
    +                             javax.servlet.http.HttpServletResponse aHTTPRsp)
    +
    +
    Create new Command object. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +setResponseEvent

    +
    +public void setResponseEvent(Event aResponseEvent)
    +
    +
    Set pushlet response event. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getResponseEvent

    +
    +public Event getResponseEvent()
    +
    +
    Get pushlet response event. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getClientAdapter

    +
    +public ClientAdapter getClientAdapter()
    +                               throws PushletException
    +
    +
    Get client adapter for request. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Config.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Config.html new file mode 100755 index 0000000000..107318ea00 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Config.html @@ -0,0 +1,482 @@ + + + + + + +Config + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Config

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Config
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs
    +
    +
    +
    +
    public class Config
    extends java.lang.Object
    implements ConfigDefs
    + + +

    +Loads and maintains overall configuration. +

    + +

    +

    +
    Version:
    +
    $Id: Config.java,v 1.5 2007/11/23 21:10:17 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + +
    +Constructor Summary
    Config() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static java.lang.ObjectcreateObject(java.lang.String aClassNameProp, + java.lang.String aDefault) + +
    +          Factory method: create object from property denoting class name.
    +static booleangetBoolProperty(java.lang.String aName) + +
    +           
    +static java.lang.ClassgetClass(java.lang.String aClassNameProp, + java.lang.String aDefault) + +
    +          Factory method: create object from property denoting class name.
    +static intgetIntProperty(java.lang.String aName) + +
    +           
    +static longgetLongProperty(java.lang.String aName) + +
    +           
    +static java.lang.StringgetProperty(java.lang.String aName) + +
    +           
    +static java.lang.StringgetProperty(java.lang.String aName, + java.lang.String aDefault) + +
    +           
    +static booleanhasProperty(java.lang.String aName) + +
    +           
    +static voidload(java.lang.String aDirPath) + +
    +          Initialize event sources from properties file.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Config

    +
    +public Config()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +createObject

    +
    +public static java.lang.Object createObject(java.lang.String aClassNameProp,
    +                                            java.lang.String aDefault)
    +                                     throws PushletException
    +
    +
    Factory method: create object from property denoting class name. +

    +

    +
    +
    +
    +
    Parameters:
    aClassNameProp - property name e.g. "session.class" +
    Returns:
    an instance of class denoted by property +
    Throws: +
    PushletException - when class cannot be instantiated
    +
    +
    +
    + +

    +getClass

    +
    +public static java.lang.Class getClass(java.lang.String aClassNameProp,
    +                                       java.lang.String aDefault)
    +                                throws PushletException
    +
    +
    Factory method: create object from property denoting class name. +

    +

    +
    +
    +
    +
    Parameters:
    aClassNameProp - property name e.g. "session.class" +
    Returns:
    a Class object denoted by property +
    Throws: +
    PushletException - when class cannot be instantiated
    +
    +
    +
    + +

    +load

    +
    +public static void load(java.lang.String aDirPath)
    +
    +
    Initialize event sources from properties file. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getProperty

    +
    +public static java.lang.String getProperty(java.lang.String aName,
    +                                           java.lang.String aDefault)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getProperty

    +
    +public static java.lang.String getProperty(java.lang.String aName)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getBoolProperty

    +
    +public static boolean getBoolProperty(java.lang.String aName)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getIntProperty

    +
    +public static int getIntProperty(java.lang.String aName)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getLongProperty

    +
    +public static long getLongProperty(java.lang.String aName)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +hasProperty

    +
    +public static boolean hasProperty(java.lang.String aName)
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ConfigDefs.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ConfigDefs.html new file mode 100755 index 0000000000..f6889854e5 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/ConfigDefs.html @@ -0,0 +1,770 @@ + + + + + + +ConfigDefs + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Interface ConfigDefs

    +
    +
    All Known Subinterfaces:
    PushletLogger
    +
    +
    +
    All Known Implementing Classes:
    Config, Controller, DefaultLogger, Dispatcher, Log, Log4jLogger, Session, SessionManager, Subscriber, Subscription
    +
    +
    +
    +
    public interface ConfigDefs
    + + +

    +Definition of config property strings. +

    + +

    +

    +
    Version:
    +
    $Id: ConfigDefs.java,v 1.9 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Field Summary
    +static java.lang.StringCONTROLLER_CLASS + +
    +          Class factory definitions, used to insert your custom classes.
    +static java.lang.StringDISPATCHER_CLASS + +
    +           
    +static java.lang.StringLISTEN_FORCE_PULL_AGENTS + +
    +           
    +static java.lang.StringLISTEN_FORCE_PULL_ALL + +
    +          Listening modes.
    +static java.lang.StringLOG_LEVEL + +
    +          Logging
    +static intLOG_LEVEL_DEBUG + +
    +           
    +static intLOG_LEVEL_ERROR + +
    +           
    +static intLOG_LEVEL_FATAL + +
    +           
    +static intLOG_LEVEL_INFO + +
    +           
    +static intLOG_LEVEL_TRACE + +
    +           
    +static intLOG_LEVEL_WARN + +
    +           
    +static java.lang.StringLOGGER_CLASS + +
    +           
    +static java.lang.StringPOLL_REFRESH_TIMEOUT_MILLIS + +
    +           
    +static java.lang.StringPOLL_REFRESH_WAIT_MAX_MILLIS + +
    +           
    +static java.lang.StringPOLL_REFRESH_WAIT_MIN_MILLIS + +
    +           
    +static java.lang.StringPULL_REFRESH_TIMEOUT_MILLIS + +
    +           
    +static java.lang.StringPULL_REFRESH_WAIT_MAX_MILLIS + +
    +           
    +static java.lang.StringPULL_REFRESH_WAIT_MIN_MILLIS + +
    +           
    +static java.lang.StringQUEUE_READ_TIMEOUT_MILLIS + +
    +           
    +static java.lang.StringQUEUE_SIZE + +
    +          Queues
    +static java.lang.StringQUEUE_WRITE_TIMEOUT_MILLIS + +
    +           
    +static java.lang.StringSESSION_CLASS + +
    +           
    +static java.lang.StringSESSION_ID_GENERATION + +
    +           
    +static java.lang.StringSESSION_ID_GENERATION_RANDOMSTRING + +
    +           
    +static java.lang.StringSESSION_ID_GENERATION_UUID + +
    +           
    +static java.lang.StringSESSION_ID_SIZE + +
    +          Session management.
    +static java.lang.StringSESSION_MANAGER_CLASS + +
    +           
    +static java.lang.StringSESSION_TIMEOUT_MINS + +
    +           
    +static java.lang.StringSOURCES_ACTIVATE + +
    +           
    +static java.lang.StringSUBSCRIBER_CLASS + +
    +           
    +static java.lang.StringSUBSCRIPTION_CLASS + +
    +           
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +CONTROLLER_CLASS

    +
    +static final java.lang.String CONTROLLER_CLASS
    +
    +
    Class factory definitions, used to insert your custom classes. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +DISPATCHER_CLASS

    +
    +static final java.lang.String DISPATCHER_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOGGER_CLASS

    +
    +static final java.lang.String LOGGER_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_MANAGER_CLASS

    +
    +static final java.lang.String SESSION_MANAGER_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_CLASS

    +
    +static final java.lang.String SESSION_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBSCRIBER_CLASS

    +
    +static final java.lang.String SUBSCRIBER_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBSCRIPTION_CLASS

    +
    +static final java.lang.String SUBSCRIPTION_CLASS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_ID_SIZE

    +
    +static final java.lang.String SESSION_ID_SIZE
    +
    +
    Session management. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_ID_GENERATION

    +
    +static final java.lang.String SESSION_ID_GENERATION
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_ID_GENERATION_UUID

    +
    +static final java.lang.String SESSION_ID_GENERATION_UUID
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_ID_GENERATION_RANDOMSTRING

    +
    +static final java.lang.String SESSION_ID_GENERATION_RANDOMSTRING
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SESSION_TIMEOUT_MINS

    +
    +static final java.lang.String SESSION_TIMEOUT_MINS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SOURCES_ACTIVATE

    +
    +static final java.lang.String SOURCES_ACTIVATE
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL

    +
    +static final java.lang.String LOG_LEVEL
    +
    +
    Logging +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_FATAL

    +
    +static final int LOG_LEVEL_FATAL
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_ERROR

    +
    +static final int LOG_LEVEL_ERROR
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_WARN

    +
    +static final int LOG_LEVEL_WARN
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_INFO

    +
    +static final int LOG_LEVEL_INFO
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_DEBUG

    +
    +static final int LOG_LEVEL_DEBUG
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LOG_LEVEL_TRACE

    +
    +static final int LOG_LEVEL_TRACE
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +QUEUE_SIZE

    +
    +static final java.lang.String QUEUE_SIZE
    +
    +
    Queues +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +QUEUE_READ_TIMEOUT_MILLIS

    +
    +static final java.lang.String QUEUE_READ_TIMEOUT_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +QUEUE_WRITE_TIMEOUT_MILLIS

    +
    +static final java.lang.String QUEUE_WRITE_TIMEOUT_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LISTEN_FORCE_PULL_ALL

    +
    +static final java.lang.String LISTEN_FORCE_PULL_ALL
    +
    +
    Listening modes. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +LISTEN_FORCE_PULL_AGENTS

    +
    +static final java.lang.String LISTEN_FORCE_PULL_AGENTS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +PULL_REFRESH_TIMEOUT_MILLIS

    +
    +static final java.lang.String PULL_REFRESH_TIMEOUT_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +PULL_REFRESH_WAIT_MIN_MILLIS

    +
    +static final java.lang.String PULL_REFRESH_WAIT_MIN_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +PULL_REFRESH_WAIT_MAX_MILLIS

    +
    +static final java.lang.String PULL_REFRESH_WAIT_MAX_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +POLL_REFRESH_TIMEOUT_MILLIS

    +
    +static final java.lang.String POLL_REFRESH_TIMEOUT_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +POLL_REFRESH_WAIT_MIN_MILLIS

    +
    +static final java.lang.String POLL_REFRESH_WAIT_MIN_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +POLL_REFRESH_WAIT_MAX_MILLIS

    +
    +static final java.lang.String POLL_REFRESH_WAIT_MAX_MILLIS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Controller.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Controller.html new file mode 100755 index 0000000000..b6842eae9a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Controller.html @@ -0,0 +1,336 @@ + + + + + + +Controller + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Controller

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Controller
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, Protocol
    +
    +
    +
    +
    public class Controller
    extends java.lang.Object
    implements Protocol, ConfigDefs
    + + +

    +Handles servlet requests from client. +

    + +

    +

    +
    Version:
    +
    $Id: Controller.java,v 1.9 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static Controllercreate(Session aSession) + +
    +          Create instance through factory method.
    + voiddoCommand(Command aCommand) + +
    +          Handle command.
    + SubscribergetSubscriber() + +
    +           
    + java.lang.StringtoString() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +create

    +
    +public static Controller create(Session aSession)
    +                         throws PushletException
    +
    +
    Create instance through factory method. +

    +

    +
    +
    +
    +
    Parameters:
    aSession - the parent Session +
    Returns:
    a Controller object (or derived) +
    Throws: +
    PushletException - exception, usually misconfiguration
    +
    +
    +
    + +

    +doCommand

    +
    +public void doCommand(Command aCommand)
    +
    +
    Handle command. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Object
    +
    +
    +
    +
    +
    +
    + +

    +getSubscriber

    +
    +public Subscriber getSubscriber()
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Dispatcher.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Dispatcher.html new file mode 100755 index 0000000000..85c774ebbf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Dispatcher.html @@ -0,0 +1,389 @@ + + + + + + +Dispatcher + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Dispatcher

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Dispatcher
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, Protocol
    +
    +
    +
    +
    public class Dispatcher
    extends java.lang.Object
    implements Protocol, ConfigDefs
    + + +

    +Routes Events to Subscribers. +

    + +

    +

    +
    Version:
    +
    $Id: Dispatcher.java,v 1.9 2007/12/04 13:55:53 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidbroadcast(Event anEvent) + +
    +          Send event to all subscribers.
    +static DispatchergetInstance() + +
    +          Singleton pattern: get single instance.
    + voidmulticast(Event anEvent) + +
    +          Send event to subscribers matching Event subject.
    + voidstart() + +
    +          Start Dispatcher.
    + voidstop() + +
    +          Stop Dispatcher.
    + voidunicast(Event event, + java.lang.String aSessionId) + +
    +          Send event to specific subscriber.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +getInstance

    +
    +public static Dispatcher getInstance()
    +
    +
    Singleton pattern: get single instance. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +broadcast

    +
    +public void broadcast(Event anEvent)
    +
    +
    Send event to all subscribers. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +multicast

    +
    +public void multicast(Event anEvent)
    +
    +
    Send event to subscribers matching Event subject. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +unicast

    +
    +public void unicast(Event event,
    +                    java.lang.String aSessionId)
    +
    +
    Send event to specific subscriber. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +start

    +
    +public void start()
    +           throws PushletException
    +
    +
    Start Dispatcher. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    Stop Dispatcher. +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Event.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Event.html new file mode 100755 index 0000000000..5bfc1a307f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Event.html @@ -0,0 +1,638 @@ + + + + + + +Event + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Event

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Event
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, Protocol
    +
    +
    +
    +
    public class Event
    extends java.lang.Object
    implements Protocol, java.io.Serializable
    + + +

    +Represents the event data. +

    + +

    +

    +
    Version:
    +
    $Id: Event.java,v 1.13 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + + + + + + + +
    +Constructor Summary
    Event(java.util.Map theAttributes) + +
    +           
    Event(java.lang.String anEventType) + +
    +           
    Event(java.lang.String anEventType, + java.util.Map theAttributes) + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.Objectclone() + +
    +           
    +static EventcreateDataEvent(java.lang.String aSubject) + +
    +           
    +static EventcreateDataEvent(java.lang.String aSubject, + java.util.Map theAttributes) + +
    +           
    + java.lang.StringgetEventType() + +
    +           
    + java.lang.StringgetField(java.lang.String name) + +
    +           
    + java.lang.StringgetField(java.lang.String name, + java.lang.String aDefault) + +
    +          Return field; if null return default.
    + java.util.IteratorgetFieldNames() + +
    +           
    + java.lang.StringgetSubject() + +
    +           
    + voidsetField(java.lang.String name, + int value) + +
    +           
    + voidsetField(java.lang.String name, + long value) + +
    +           
    + voidsetField(java.lang.String name, + java.lang.String value) + +
    +           
    + java.lang.StringtoQueryString() + +
    +          Convert to HTTP query string.
    + java.lang.StringtoString() + +
    +           
    + java.lang.StringtoXML() + +
    +           
    + java.lang.StringtoXML(boolean strict) + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Event

    +
    +public Event(java.lang.String anEventType)
    +
    +
    +
    + +

    +Event

    +
    +public Event(java.lang.String anEventType,
    +             java.util.Map theAttributes)
    +
    +
    +
    + +

    +Event

    +
    +public Event(java.util.Map theAttributes)
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +createDataEvent

    +
    +public static Event createDataEvent(java.lang.String aSubject)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +createDataEvent

    +
    +public static Event createDataEvent(java.lang.String aSubject,
    +                                    java.util.Map theAttributes)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getEventType

    +
    +public java.lang.String getEventType()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getSubject

    +
    +public java.lang.String getSubject()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +setField

    +
    +public void setField(java.lang.String name,
    +                     java.lang.String value)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +setField

    +
    +public void setField(java.lang.String name,
    +                     int value)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +setField

    +
    +public void setField(java.lang.String name,
    +                     long value)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getField

    +
    +public java.lang.String getField(java.lang.String name)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getField

    +
    +public java.lang.String getField(java.lang.String name,
    +                                 java.lang.String aDefault)
    +
    +
    Return field; if null return default. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getFieldNames

    +
    +public java.util.Iterator getFieldNames()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Object
    +
    +
    +
    +
    +
    +
    + +

    +toQueryString

    +
    +public java.lang.String toQueryString()
    +
    +
    Convert to HTTP query string. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +toXML

    +
    +public java.lang.String toXML(boolean strict)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +toXML

    +
    +public java.lang.String toXML()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +clone

    +
    +public java.lang.Object clone()
    +
    +
    +
    Overrides:
    clone in class java.lang.Object
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventParser.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventParser.html new file mode 100755 index 0000000000..c62654c513 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventParser.html @@ -0,0 +1,303 @@ + + + + + + +EventParser + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class EventParser

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.EventParser
    +
    +
    +
    +
    public class EventParser
    extends java.lang.Object
    + + +

    +Parses XML into Event objects. +

    + +

    +

    +
    Version:
    +
    $Id: EventParser.java,v 1.3 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static voidmain(java.lang.String[] args) + +
    +          Test method: use files to test.
    +static Eventparse(java.io.File aFile) + +
    +          Parse Event from a File.
    +static Eventparse(java.io.Reader aReader) + +
    +          Parse Event from input Reader.
    +static Eventparse(java.lang.String aString) + +
    +          Parse Event from a String.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +parse

    +
    +public static Event parse(java.io.File aFile)
    +                   throws java.io.IOException
    +
    +
    Parse Event from a File. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +parse

    +
    +public static Event parse(java.io.Reader aReader)
    +                   throws java.io.IOException
    +
    +
    Parse Event from input Reader. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +parse

    +
    +public static Event parse(java.lang.String aString)
    +                   throws java.io.IOException
    +
    +
    Parse Event from a String. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +main

    +
    +public static void main(java.lang.String[] args)
    +
    +
    Test method: use files to test. +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventPullSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventPullSource.html new file mode 100755 index 0000000000..ebaa4d6b4c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventPullSource.html @@ -0,0 +1,389 @@ + + + + + + +EventPullSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class EventPullSource

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.EventPullSource
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable, EventSource
    +
    +
    +
    +
    public abstract class EventPullSource
    extends java.lang.Object
    implements EventSource, java.lang.Runnable
    + + +

    +ABC for specifc EventPullSources. +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    EventPullSource() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidactivate() + +
    +          Activate the event generator thread.
    + booleanisAlive() + +
    +           
    + voidpassivate() + +
    +          Deactivate the event generator thread.
    + voidrun() + +
    +          Main loop: sleep, generate event and publish.
    + voidstart() + +
    +           
    + voidstop() + +
    +          Stop the event generator thread.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    + + + + + + + +
    Methods inherited from interface nl.justobjects.pushlet.core.EventSource
    setServletContext
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +EventPullSource

    +
    +public EventPullSource()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +start

    +
    +public void start()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +isAlive

    +
    +public boolean isAlive()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    Stop the event generator thread. +

    +

    +
    Specified by:
    stop in interface EventSource
    +
    +
    +
    +
    +
    +
    + +

    +activate

    +
    +public void activate()
    +
    +
    Activate the event generator thread. +

    +

    +
    Specified by:
    activate in interface EventSource
    +
    +
    +
    +
    +
    +
    + +

    +passivate

    +
    +public void passivate()
    +
    +
    Deactivate the event generator thread. +

    +

    +
    Specified by:
    passivate in interface EventSource
    +
    +
    +
    +
    +
    +
    + +

    +run

    +
    +public void run()
    +
    +
    Main loop: sleep, generate event and publish. +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventQueue.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventQueue.html new file mode 100755 index 0000000000..1eada8010d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventQueue.html @@ -0,0 +1,492 @@ + + + + + + +EventQueue + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class EventQueue

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.EventQueue
    +
    +
    +
    +
    public class EventQueue
    extends java.lang.Object
    + + +

    +FIFO queue with guarded suspension. + Purpose
    +

    + Implementation
    + FIFO queue class implemented with circular array. The enQueue() and + deQueue() methods use guarded suspension according to a readers/writers + pattern, implemented with java.lang.Object.wait()/notify(). +

    + Examples
    +

    +
    +

    + +

    +

    +
    Version:
    +
    $Id: EventQueue.java,v 1.3 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + +
    +Constructor Summary
    EventQueue() + +
    +          Construct queue with default (8) capacity.
    EventQueue(int capacity) + +
    +          Construct queue with specified capacity.
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + EventdeQueue() + +
    +          Get head; if empty wait until something in queue.
    + EventdeQueue(long maxWaitTime) + +
    +          Get head; if empty wait for specified time at max.
    + Event[]deQueueAll(long maxWaitTime) + +
    +          Get all queued Events.
    + booleanenQueue(Event item) + +
    +          Put item in queue; waits() indefinitely if queue is full.
    + booleanenQueue(Event item, + long maxWaitTime) + +
    +          Put item in queue; if full wait maxtime.
    + intgetSize() + +
    +           
    + booleanisEmpty() + +
    +          Is the queue empty ?
    + booleanisFull() + +
    +          Is the queue full ?
    +static voidmain(java.lang.String[] args) + +
    +           
    +static voidp(java.lang.String s) + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +EventQueue

    +
    +public EventQueue()
    +
    +
    Construct queue with default (8) capacity. +

    +

    +
    + +

    +EventQueue

    +
    +public EventQueue(int capacity)
    +
    +
    Construct queue with specified capacity. +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +enQueue

    +
    +public boolean enQueue(Event item)
    +                throws java.lang.InterruptedException
    +
    +
    Put item in queue; waits() indefinitely if queue is full. +

    +

    + +
    Throws: +
    java.lang.InterruptedException
    +
    +
    +
    + +

    +enQueue

    +
    +public boolean enQueue(Event item,
    +                       long maxWaitTime)
    +                throws java.lang.InterruptedException
    +
    +
    Put item in queue; if full wait maxtime. +

    +

    + +
    Throws: +
    java.lang.InterruptedException
    +
    +
    +
    + +

    +deQueue

    +
    +public Event deQueue()
    +              throws java.lang.InterruptedException
    +
    +
    Get head; if empty wait until something in queue. +

    +

    + +
    Throws: +
    java.lang.InterruptedException
    +
    +
    +
    + +

    +deQueue

    +
    +public Event deQueue(long maxWaitTime)
    +              throws java.lang.InterruptedException
    +
    +
    Get head; if empty wait for specified time at max. +

    +

    + +
    Throws: +
    java.lang.InterruptedException
    +
    +
    +
    + +

    +deQueueAll

    +
    +public Event[] deQueueAll(long maxWaitTime)
    +                   throws java.lang.InterruptedException
    +
    +
    Get all queued Events. +

    +

    + +
    Throws: +
    java.lang.InterruptedException
    +
    +
    +
    + +

    +getSize

    +
    +public int getSize()
    +
    +
    +
    +
    +
    +
    + +

    +isEmpty

    +
    +public boolean isEmpty()
    +
    +
    Is the queue empty ? +

    +

    +
    +
    +
    +
    + +

    +isFull

    +
    +public boolean isFull()
    +
    +
    Is the queue full ? +

    +

    +
    +
    +
    +
    + +

    +p

    +
    +public static void p(java.lang.String s)
    +
    +
    +
    +
    +
    +
    + +

    +main

    +
    +public static void main(java.lang.String[] args)
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSource.html new file mode 100755 index 0000000000..ecb763b418 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSource.html @@ -0,0 +1,276 @@ + + + + + + +EventSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Interface EventSource

    +
    +
    All Known Implementing Classes:
    EventPullSource, Serveur.IvyEventSource
    +
    +
    +
    +
    public interface EventSource
    + + +

    +Interface for specifc Event(Pull/Push)Sources. +

    + +

    +


    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidactivate() + +
    +          Activate the event source.
    + voidpassivate() + +
    +          Deactivate the event source.
    + voidsetServletContext(javax.servlet.ServletContext srvCtxt) + +
    +           
    + voidstop() + +
    +          Halt the event source.
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +activate

    +
    +void activate()
    +
    +
    Activate the event source. +

    +

    +
    +
    +
    +
    + +

    +passivate

    +
    +void passivate()
    +
    +
    Deactivate the event source. +

    +

    +
    +
    +
    +
    + +

    +stop

    +
    +void stop()
    +
    +
    Halt the event source. +

    +

    +
    +
    +
    +
    + +

    +setServletContext

    +
    +void setServletContext(javax.servlet.ServletContext srvCtxt)
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSourceManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSourceManager.html new file mode 100755 index 0000000000..248045a8a6 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/EventSourceManager.html @@ -0,0 +1,329 @@ + + + + + + +EventSourceManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class EventSourceManager

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.EventSourceManager
    +
    +
    +
    +
    public class EventSourceManager
    extends java.lang.Object
    + + +

    +Maintains lifecycle of event sources. +

    + +

    +

    +
    Version:
    +
    $Id: EventSourceManager.java,v 1.14 2007/11/10 13:44:02 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    EventSourceManager() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static voidactivate() + +
    +          Activate all event sources.
    +static voidpassivate() + +
    +          Deactivate all event sources.
    +static voidstart(java.lang.String aDirPath, + javax.servlet.ServletContext srvCtxt) + +
    +          Initialize event sources from properties file.
    +static voidstop() + +
    +          Halt event sources.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +EventSourceManager

    +
    +public EventSourceManager()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +start

    +
    +public static void start(java.lang.String aDirPath,
    +                         javax.servlet.ServletContext srvCtxt)
    +
    +
    Initialize event sources from properties file. +

    +

    +
    +
    +
    +
    + +

    +activate

    +
    +public static void activate()
    +
    +
    Activate all event sources. +

    +

    +
    +
    +
    +
    + +

    +passivate

    +
    +public static void passivate()
    +
    +
    Deactivate all event sources. +

    +

    +
    +
    +
    +
    + +

    +stop

    +
    +public static void stop()
    +
    +
    Halt event sources. +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Protocol.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Protocol.html new file mode 100755 index 0000000000..a335a5b6ef --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Protocol.html @@ -0,0 +1,1112 @@ + + + + + + +Protocol + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Interface Protocol

    +
    +
    All Known Subinterfaces:
    PushletClientListener
    +
    +
    +
    All Known Implementing Classes:
    BrowserAdapter, Command, Controller, Dispatcher, Event, Pushlet, PushletClient, Session, Subscriber
    +
    +
    +
    +
    public interface Protocol
    + + +

    +Constants for Pushlet protocols. +

    + +

    +

    +
    Version:
    +
    $Id: Protocol.java,v 1.15 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Field Summary
    +static java.lang.StringDEFAULT_SERVLET_URI + +
    +          Default URI .
    +static java.lang.StringE_ABORT + +
    +          S-->C Client should abort, permanent error.
    +static java.lang.StringE_DATA + +
    +          S-->C Data.
    +static java.lang.StringE_HEARTBEAT + +
    +          S-->C or C-->S Heartbeat.
    +static java.lang.StringE_HEARTBEAT_ACK + +
    +          S-->C S-->C or C-->S Heartbeat confirmed.
    +static java.lang.StringE_JOIN + +
    +          C-->S Request to join server.
    +static java.lang.StringE_JOIN_ACK + +
    +          S-->C Acknowledgement of join.
    +static java.lang.StringE_JOIN_LISTEN + +
    +          C-->S Request to join server.
    +static java.lang.StringE_JOIN_LISTEN_ACK + +
    +          S-->C Acknowledgement of join.
    +static java.lang.StringE_LEAVE + +
    +          C-->S Client leaves server.
    +static java.lang.StringE_LEAVE_ACK + +
    +          S-->C Ack of leave.
    +static java.lang.StringE_LISTEN + +
    +          C-->S Client starts listening.
    +static java.lang.StringE_LISTEN_ACK + +
    +          S-->C Ack of listen.
    +static java.lang.StringE_NACK + +
    +          S-->C Client error response, transitional error.
    +static java.lang.StringE_PUBLISH + +
    +          C-->S Publish to subject.
    +static java.lang.StringE_PUBLISH_ACK + +
    +          S-->C Publish to subject acknowledge.
    +static java.lang.StringE_REFRESH + +
    +          S-->C or C-->S client refresh of data channel.
    +static java.lang.StringE_REFRESH_ACK + +
    +          S-->C client should refresh data channel.
    +static java.lang.StringE_SUBSCRIBE + +
    +          C-->S Subscribe to subject request.
    +static java.lang.StringE_SUBSCRIBE_ACK + +
    +          S-->C Subscribe to subject acknowledge.
    +static java.lang.StringE_UNSUBSCRIBE + +
    +          C-->S Unsubscribe from subject request.
    +static java.lang.StringE_UNSUBSCRIBE_ACK + +
    +          S--C Unsubscribe from subject acknowledge.
    +static java.lang.StringFORMAT_JAVASCRIPT + +
    +          JavaScript callback.
    +static java.lang.StringFORMAT_SERIALIZED_JAVA_OBJECT + +
    +          Java serialized object.
    +static java.lang.StringFORMAT_XML + +
    +          Stream of XML documents.
    +static java.lang.StringFORMAT_XML_STRICT + +
    +          Single XML document containing zero or more events.
    +static java.lang.StringMODE_POLL + +
    +           
    +static java.lang.StringMODE_PULL + +
    +           
    +static java.lang.StringMODE_STREAM + +
    +           
    +static java.lang.StringP_EVENT + +
    +          Event type (join, leave, data, subscribe etc) .
    +static java.lang.StringP_FORMAT + +
    +          Format to receive events
    +static java.lang.StringP_FROM + +
    +          Originator of Event.
    +static java.lang.StringP_ID + +
    +          Identifier for client instance within server.
    +static java.lang.StringP_MODE + +
    +          Protocol mode.
    +static java.lang.StringP_REASON + +
    +          Reason for errors.
    +static java.lang.StringP_SEQ + +
    +          Event sequence number, numbers per-client.
    +static java.lang.StringP_SUBJECT + +
    +          Subject (topic) of data event.
    +static java.lang.StringP_SUBSCRIPTION_ID + +
    +          Subscription id, identifies single subscription.
    +static java.lang.StringP_SUBSCRIPTION_LABEL + +
    +          Subscription label, may be used to return user-specific + token with a data event, e.g. the name of a function for a callback.
    +static java.lang.StringP_TIME + +
    +          Time in seconds since 1970
    +static java.lang.StringP_TO + +
    +          Addressee of Event, subject or client p_id.
    +static java.lang.StringP_URL + +
    +          URL attribute.
    +static java.lang.StringP_WAIT + +
    +          Wait attribute.
    +static java.lang.StringSUBJECT_META + +
    +           
    +static java.lang.StringSUBJECT_META_JOINS + +
    +           
    +static java.lang.StringSUBJECT_META_SUBS + +
    +           
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +DEFAULT_SERVLET_URI

    +
    +static final java.lang.String DEFAULT_SERVLET_URI
    +
    +
    Default URI . +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_EVENT

    +
    +static final java.lang.String P_EVENT
    +
    +
    Event type (join, leave, data, subscribe etc) . +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_TIME

    +
    +static final java.lang.String P_TIME
    +
    +
    Time in seconds since 1970 +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_SEQ

    +
    +static final java.lang.String P_SEQ
    +
    +
    Event sequence number, numbers per-client. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_SUBJECT

    +
    +static final java.lang.String P_SUBJECT
    +
    +
    Subject (topic) of data event. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_FROM

    +
    +static final java.lang.String P_FROM
    +
    +
    Originator of Event. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_TO

    +
    +static final java.lang.String P_TO
    +
    +
    Addressee of Event, subject or client p_id. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_ID

    +
    +static final java.lang.String P_ID
    +
    +
    Identifier for client instance within server. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_SUBSCRIPTION_ID

    +
    +static final java.lang.String P_SUBSCRIPTION_ID
    +
    +
    Subscription id, identifies single subscription. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_FORMAT

    +
    +static final java.lang.String P_FORMAT
    +
    +
    Format to receive events +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_MODE

    +
    +static final java.lang.String P_MODE
    +
    +
    Protocol mode. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_REASON

    +
    +static final java.lang.String P_REASON
    +
    +
    Reason for errors. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_URL

    +
    +static final java.lang.String P_URL
    +
    +
    URL attribute. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_WAIT

    +
    +static final java.lang.String P_WAIT
    +
    +
    Wait attribute. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +P_SUBSCRIPTION_LABEL

    +
    +static final java.lang.String P_SUBSCRIPTION_LABEL
    +
    +
    Subscription label, may be used to return user-specific + token with a data event, e.g. the name of a function for a callback. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_JOIN

    +
    +static final java.lang.String E_JOIN
    +
    +
    C-->S Request to join server. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_JOIN_ACK

    +
    +static final java.lang.String E_JOIN_ACK
    +
    +
    S-->C Acknowledgement of join. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_JOIN_LISTEN

    +
    +static final java.lang.String E_JOIN_LISTEN
    +
    +
    C-->S Request to join server. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_JOIN_LISTEN_ACK

    +
    +static final java.lang.String E_JOIN_LISTEN_ACK
    +
    +
    S-->C Acknowledgement of join. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_LISTEN

    +
    +static final java.lang.String E_LISTEN
    +
    +
    C-->S Client starts listening. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_LISTEN_ACK

    +
    +static final java.lang.String E_LISTEN_ACK
    +
    +
    S-->C Ack of listen. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_LEAVE

    +
    +static final java.lang.String E_LEAVE
    +
    +
    C-->S Client leaves server. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_LEAVE_ACK

    +
    +static final java.lang.String E_LEAVE_ACK
    +
    +
    S-->C Ack of leave. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_PUBLISH

    +
    +static final java.lang.String E_PUBLISH
    +
    +
    C-->S Publish to subject. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_PUBLISH_ACK

    +
    +static final java.lang.String E_PUBLISH_ACK
    +
    +
    S-->C Publish to subject acknowledge. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_SUBSCRIBE

    +
    +static final java.lang.String E_SUBSCRIBE
    +
    +
    C-->S Subscribe to subject request. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_SUBSCRIBE_ACK

    +
    +static final java.lang.String E_SUBSCRIBE_ACK
    +
    +
    S-->C Subscribe to subject acknowledge. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_UNSUBSCRIBE

    +
    +static final java.lang.String E_UNSUBSCRIBE
    +
    +
    C-->S Unsubscribe from subject request. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_UNSUBSCRIBE_ACK

    +
    +static final java.lang.String E_UNSUBSCRIBE_ACK
    +
    +
    S--C Unsubscribe from subject acknowledge. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_NACK

    +
    +static final java.lang.String E_NACK
    +
    +
    S-->C Client error response, transitional error. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_ABORT

    +
    +static final java.lang.String E_ABORT
    +
    +
    S-->C Client should abort, permanent error. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_DATA

    +
    +static final java.lang.String E_DATA
    +
    +
    S-->C Data. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_HEARTBEAT

    +
    +static final java.lang.String E_HEARTBEAT
    +
    +
    S-->C or C-->S Heartbeat. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_HEARTBEAT_ACK

    +
    +static final java.lang.String E_HEARTBEAT_ACK
    +
    +
    S-->C S-->C or C-->S Heartbeat confirmed. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_REFRESH

    +
    +static final java.lang.String E_REFRESH
    +
    +
    S-->C or C-->S client refresh of data channel. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +E_REFRESH_ACK

    +
    +static final java.lang.String E_REFRESH_ACK
    +
    +
    S-->C client should refresh data channel. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +FORMAT_JAVASCRIPT

    +
    +static final java.lang.String FORMAT_JAVASCRIPT
    +
    +
    JavaScript callback. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +FORMAT_SERIALIZED_JAVA_OBJECT

    +
    +static final java.lang.String FORMAT_SERIALIZED_JAVA_OBJECT
    +
    +
    Java serialized object. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +FORMAT_XML

    +
    +static final java.lang.String FORMAT_XML
    +
    +
    Stream of XML documents. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +FORMAT_XML_STRICT

    +
    +static final java.lang.String FORMAT_XML_STRICT
    +
    +
    Single XML document containing zero or more events. +

    +

    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +MODE_STREAM

    +
    +static final java.lang.String MODE_STREAM
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +MODE_PULL

    +
    +static final java.lang.String MODE_PULL
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +MODE_POLL

    +
    +static final java.lang.String MODE_POLL
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBJECT_META

    +
    +static final java.lang.String SUBJECT_META
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBJECT_META_SUBS

    +
    +static final java.lang.String SUBJECT_META_SUBS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBJECT_META_JOINS

    +
    +static final java.lang.String SUBJECT_META_JOINS
    +
    +
    +
    See Also:
    Constant Field Values
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Session.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Session.html new file mode 100755 index 0000000000..2b1ba1363b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Session.html @@ -0,0 +1,673 @@ + + + + + + +Session + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Session

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Session
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, Protocol
    +
    +
    +
    +
    public class Session
    extends java.lang.Object
    implements Protocol, ConfigDefs
    + + +

    +Represents client pushlet session state. +

    + +

    +

    +
    Version:
    +
    $Id: Session.java,v 1.8 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + +
    +Field Summary
    +static java.lang.String[]FORCED_PULL_AGENTS + +
    +           
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidage(long aDeltaMillis) + +
    +          Decrease time to live.
    +static Sessioncreate(java.lang.String anId) + +
    +          Create instance through factory method.
    + voiddebug(java.lang.String s) + +
    +          Exceptional print util.
    + java.lang.StringgetAddress() + +
    +          Return (remote) Subscriber client's IP address.
    + ControllergetController() + +
    +          Return command controller.
    + java.lang.StringgetFormat() + +
    +          Return Event format to send to client.
    + java.lang.StringgetId() + +
    +          Return (remote) Subscriber client's unique id.
    + SubscribergetSubscriber() + +
    +          Return subscriber.
    + java.lang.StringgetUserAgent() + +
    +          Return remote HTTP User-Agent.
    + voidinfo(java.lang.String s) + +
    +          Info.
    + booleanisExpired() + +
    +          Has session timed out?
    + voidkick() + +
    +          Keep alive by resetting TTL.
    + voidsetUserAgent(java.lang.String aUserAgent) + +
    +          Set client HTTP UserAgent.
    + voidstart() + +
    +           
    + voidstop() + +
    +           
    + java.lang.StringtoString() + +
    +           
    + voidwarn(java.lang.String s) + +
    +          Exceptional print util.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +FORCED_PULL_AGENTS

    +
    +public static java.lang.String[] FORCED_PULL_AGENTS
    +
    +
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +create

    +
    +public static Session create(java.lang.String anId)
    +                      throws PushletException
    +
    +
    Create instance through factory method. +

    +

    +
    +
    +
    +
    Parameters:
    anId - a session id +
    Returns:
    a Session object (or derived) +
    Throws: +
    PushletException - exception, usually misconfiguration
    +
    +
    +
    + +

    +getAddress

    +
    +public java.lang.String getAddress()
    +
    +
    Return (remote) Subscriber client's IP address. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getController

    +
    +public Controller getController()
    +
    +
    Return command controller. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getFormat

    +
    +public java.lang.String getFormat()
    +
    +
    Return Event format to send to client. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getId

    +
    +public java.lang.String getId()
    +
    +
    Return (remote) Subscriber client's unique id. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSubscriber

    +
    +public Subscriber getSubscriber()
    +
    +
    Return subscriber. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getUserAgent

    +
    +public java.lang.String getUserAgent()
    +
    +
    Return remote HTTP User-Agent. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +setUserAgent

    +
    +public void setUserAgent(java.lang.String aUserAgent)
    +
    +
    Set client HTTP UserAgent. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +age

    +
    +public void age(long aDeltaMillis)
    +
    +
    Decrease time to live. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +isExpired

    +
    +public boolean isExpired()
    +
    +
    Has session timed out? +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +kick

    +
    +public void kick()
    +
    +
    Keep alive by resetting TTL. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +start

    +
    +public void start()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +info

    +
    +public void info(java.lang.String s)
    +
    +
    Info. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +warn

    +
    +public void warn(java.lang.String s)
    +
    +
    Exceptional print util. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +debug

    +
    +public void debug(java.lang.String s)
    +
    +
    Exceptional print util. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Object
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/SessionManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/SessionManager.html new file mode 100755 index 0000000000..9f0c7d945c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/SessionManager.html @@ -0,0 +1,532 @@ + + + + + + +SessionManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class SessionManager

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.SessionManager
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs
    +
    +
    +
    +
    public class SessionManager
    extends java.lang.Object
    implements ConfigDefs
    + + +

    +Manages lifecycle of Sessions. +

    + +

    +

    +
    Version:
    +
    $Id: SessionManager.java,v 1.12 2007/12/04 13:55:53 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidaddSession(Session session) + +
    +          Add session.
    + voidapply(java.lang.Object visitor, + java.lang.reflect.Method method, + java.lang.Object[] args) + +
    +          Visitor pattern implementation for Session iteration.
    + SessioncreateSession(Event anEvent) + +
    +          Create new Session (but add later).
    +static SessionManagergetInstance() + +
    +          Singleton pattern: get single instance.
    + SessiongetSession(java.lang.String anId) + +
    +          Get Session by session id.
    + intgetSessionCount() + +
    +          Get number of listening Sessions.
    + Session[]getSessions() + +
    +          Get copy of listening Sessions.
    + java.lang.StringgetStatus() + +
    +          Get status info.
    + booleanhasSession(java.lang.String anId) + +
    +          Is Session present?.
    + SessionremoveSession(Session aSession) + +
    +          Register session for removal.
    + voidstart() + +
    +          Starts us.
    + voidstop() + +
    +          Stopis us.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +apply

    +
    +public void apply(java.lang.Object visitor,
    +                  java.lang.reflect.Method method,
    +                  java.lang.Object[] args)
    +
    +
    Visitor pattern implementation for Session iteration. +

    + This method can be used to iterate over all Sessions in a threadsafe way. + See Dispatcher.multicast and broadcast methods for examples. +

    +

    +
    +
    +
    +
    Parameters:
    visitor - the object that should implement method parm
    method - the method to be called from visitor
    args - arguments to be passed in visit method, args[0] will always be Session object
    +
    +
    +
    + +

    +createSession

    +
    +public Session createSession(Event anEvent)
    +                      throws PushletException
    +
    +
    Create new Session (but add later). +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +getInstance

    +
    +public static SessionManager getInstance()
    +
    +
    Singleton pattern: get single instance. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSession

    +
    +public Session getSession(java.lang.String anId)
    +
    +
    Get Session by session id. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSessions

    +
    +public Session[] getSessions()
    +
    +
    Get copy of listening Sessions. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSessionCount

    +
    +public int getSessionCount()
    +
    +
    Get number of listening Sessions. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getStatus

    +
    +public java.lang.String getStatus()
    +
    +
    Get status info. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +hasSession

    +
    +public boolean hasSession(java.lang.String anId)
    +
    +
    Is Session present?. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +addSession

    +
    +public void addSession(Session session)
    +
    +
    Add session. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +removeSession

    +
    +public Session removeSession(Session aSession)
    +
    +
    Register session for removal. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +start

    +
    +public void start()
    +           throws PushletException
    +
    +
    Starts us. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    Stopis us. +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscriber.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscriber.html new file mode 100755 index 0000000000..d94f64ef82 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscriber.html @@ -0,0 +1,670 @@ + + + + + + +Subscriber + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Subscriber

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Subscriber
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, Protocol
    +
    +
    +
    +
    public class Subscriber
    extends java.lang.Object
    implements Protocol, ConfigDefs
    + + +

    +Handles data channel between dispatcher and client. +

    + +

    +

    +
    Version:
    +
    $Id: Subscriber.java,v 1.26 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + SubscriptionaddSubscription(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Add a subscription.
    + voidbailout() + +
    +           
    +static Subscribercreate(Session aSession) + +
    +          Create instance through factory method.
    + voidfetchEvents(Command aCommand) + +
    +          Get events from queue and push to client.
    + java.lang.StringgetId() + +
    +          Get (session) id.
    + java.lang.StringgetMode() + +
    +           
    + longgetRefreshTimeMillis() + +
    +           
    + SessiongetSession() + +
    +          Return client session.
    + Subscription[]getSubscriptions() + +
    +          Return subscriptions.
    + booleanisActive() + +
    +          Are we still active to handle events.
    + Subscriptionmatch(Event event) + +
    +          Determine if we should receive event.
    + voidonEvent(Event theEvent) + +
    +          Event from Dispatcher: enqueue it.
    + SubscriptionremoveSubscription(java.lang.String aSubscriptionId) + +
    +          Remove a subscription.
    + voidremoveSubscriptions() + +
    +          Remove all subscriptions.
    + voidsetMode(java.lang.String aMode) + +
    +           
    + voidstart() + +
    +           
    + voidstop() + +
    +           
    + java.lang.StringtoString() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +create

    +
    +public static Subscriber create(Session aSession)
    +                         throws PushletException
    +
    +
    Create instance through factory method. +

    +

    +
    +
    +
    +
    Parameters:
    aSession - the parent Session +
    Returns:
    a Subscriber object (or derived) +
    Throws: +
    PushletException - exception, usually misconfiguration
    +
    +
    +
    + +

    +start

    +
    +public void start()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +bailout

    +
    +public void bailout()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +isActive

    +
    +public boolean isActive()
    +
    +
    Are we still active to handle events. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSession

    +
    +public Session getSession()
    +
    +
    Return client session. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getId

    +
    +public java.lang.String getId()
    +
    +
    Get (session) id. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getSubscriptions

    +
    +public Subscription[] getSubscriptions()
    +
    +
    Return subscriptions. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +addSubscription

    +
    +public Subscription addSubscription(java.lang.String aSubject,
    +                                    java.lang.String aLabel)
    +                             throws PushletException
    +
    +
    Add a subscription. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +removeSubscription

    +
    +public Subscription removeSubscription(java.lang.String aSubscriptionId)
    +
    +
    Remove a subscription. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +removeSubscriptions

    +
    +public void removeSubscriptions()
    +
    +
    Remove all subscriptions. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getMode

    +
    +public java.lang.String getMode()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +setMode

    +
    +public void setMode(java.lang.String aMode)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getRefreshTimeMillis

    +
    +public long getRefreshTimeMillis()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +fetchEvents

    +
    +public void fetchEvents(Command aCommand)
    +                 throws PushletException
    +
    +
    Get events from queue and push to client. +

    +

    +
    +
    +
    + +
    Throws: +
    PushletException
    +
    +
    +
    + +

    +match

    +
    +public Subscription match(Event event)
    +
    +
    Determine if we should receive event. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +onEvent

    +
    +public void onEvent(Event theEvent)
    +
    +
    Event from Dispatcher: enqueue it. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Object
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscription.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscription.html new file mode 100755 index 0000000000..02faa6ca52 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/Subscription.html @@ -0,0 +1,424 @@ + + + + + + +Subscription + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.core +
    +Class Subscription

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.core.Subscription
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs
    +
    +
    +
    +
    public class Subscription
    extends java.lang.Object
    implements ConfigDefs
    + + +

    +Represents single subject subscription +

    + +

    +

    +
    Version:
    +
    $Id: Subscription.java,v 1.5 2007/11/23 14:33:07 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + + + + + +
    +Field Summary
    +static intID_SIZE + +
    +           
    +static java.lang.StringSUBJECT_SEPARATOR + +
    +           
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static Subscriptioncreate(java.lang.String aSubject) + +
    +          Create instance through factory method.
    +static Subscriptioncreate(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Create instance through factory method.
    + java.lang.StringgetId() + +
    +           
    + java.lang.StringgetLabel() + +
    +           
    + java.lang.StringgetSubject() + +
    +           
    + booleanmatch(Event event) + +
    +          Determine if Event matches subscription.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Field Detail
    + +

    +ID_SIZE

    +
    +public static final int ID_SIZE
    +
    +
    +
    See Also:
    Constant Field Values
    +
    +
    + +

    +SUBJECT_SEPARATOR

    +
    +public static final java.lang.String SUBJECT_SEPARATOR
    +
    +
    +
    See Also:
    Constant Field Values
    +
    + + + + + + + + +
    +Method Detail
    + +

    +create

    +
    +public static Subscription create(java.lang.String aSubject)
    +                           throws PushletException
    +
    +
    Create instance through factory method. +

    +

    +
    +
    +
    +
    Parameters:
    aSubject - the subject (topic). +
    Returns:
    a Subscription object (or derived) +
    Throws: +
    PushletException - exception, usually misconfiguration
    +
    +
    +
    + +

    +create

    +
    +public static Subscription create(java.lang.String aSubject,
    +                                  java.lang.String aLabel)
    +                           throws PushletException
    +
    +
    Create instance through factory method. +

    +

    +
    +
    +
    +
    Parameters:
    aSubject - the subject (topic).
    aLabel - the subject label (optional). +
    Returns:
    a Subscription object (or derived) +
    Throws: +
    PushletException - exception, usually misconfiguration
    +
    +
    +
    + +

    +getId

    +
    +public java.lang.String getId()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getLabel

    +
    +public java.lang.String getLabel()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +getSubject

    +
    +public java.lang.String getSubject()
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +match

    +
    +public boolean match(Event event)
    +
    +
    Determine if Event matches subscription. +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/BrowserAdapter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/BrowserAdapter.html new file mode 100755 index 0000000000..0f2c153c8c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/BrowserAdapter.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.BrowserAdapter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.BrowserAdapter

    +
    +No usage of nl.justobjects.pushlet.core.BrowserAdapter +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ClientAdapter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ClientAdapter.html new file mode 100755 index 0000000000..68e17479dd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ClientAdapter.html @@ -0,0 +1,196 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.core.ClientAdapter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.core.ClientAdapter

    +
    + + + + + + + + + +
    +Packages that use ClientAdapter
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of ClientAdapter in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Classes in nl.justobjects.pushlet.core that implement ClientAdapter
    + classBrowserAdapter + +
    +          Generic implementation of ClientAdapter for browser clients.
    +  +

    + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return ClientAdapter
    + ClientAdapterCommand.getClientAdapter() + +
    +          Get client adapter for request.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Command.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Command.html new file mode 100755 index 0000000000..94a71ddd61 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Command.html @@ -0,0 +1,207 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Command + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Command

    +
    + + + + + + + + + +
    +Packages that use Command
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Command in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Command
    +static CommandCommand.create(Session aSession, + Event aReqEvent, + javax.servlet.http.HttpServletRequest aHTTPReq, + javax.servlet.http.HttpServletResponse aHTTPRsp) + +
    +          Create new Command object.
    +  +

    + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core with parameters of type Command
    + voidController.doCommand(Command aCommand) + +
    +          Handle command.
    + voidSubscriber.fetchEvents(Command aCommand) + +
    +          Get events from queue and push to client.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Config.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Config.html new file mode 100755 index 0000000000..46255ef603 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Config.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Config + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Config

    +
    +No usage of nl.justobjects.pushlet.core.Config +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ConfigDefs.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ConfigDefs.html new file mode 100755 index 0000000000..dfb3985ab3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/ConfigDefs.html @@ -0,0 +1,289 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.core.ConfigDefs + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.core.ConfigDefs

    +
    + + + + + + + + + + + + + +
    +Packages that use ConfigDefs
    nl.justobjects.pushlet.core  
    nl.justobjects.pushlet.util  
    +  +

    + + + + + +
    +Uses of ConfigDefs in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Classes in nl.justobjects.pushlet.core that implement ConfigDefs
    + classConfig + +
    +          Loads and maintains overall configuration.
    + classController + +
    +          Handles servlet requests from client.
    + classDispatcher + +
    +          Routes Events to Subscribers.
    + classSession + +
    +          Represents client pushlet session state.
    + classSessionManager + +
    +          Manages lifecycle of Sessions.
    + classSubscriber + +
    +          Handles data channel between dispatcher and client.
    + classSubscription + +
    +          Represents single subject subscription
    +  +

    + + + + + +
    +Uses of ConfigDefs in nl.justobjects.pushlet.util
    +  +

    + + + + + + + + + +
    Subinterfaces of ConfigDefs in nl.justobjects.pushlet.util
    + interfacePushletLogger + +
    +          Logger interface to allow different logging providers.
    +  +

    + + + + + + + + + + + + + + + + + +
    Classes in nl.justobjects.pushlet.util that implement ConfigDefs
    + classDefaultLogger + +
    +          Default logger.
    + classLog + +
    +          Logging wrapper.
    + classLog4jLogger + +
    +          Logger to use Log4j for logging.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Controller.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Controller.html new file mode 100755 index 0000000000..4f520ef738 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Controller.html @@ -0,0 +1,188 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Controller + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Controller

    +
    + + + + + + + + + +
    +Packages that use Controller
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Controller in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Controller
    +static ControllerController.create(Session aSession) + +
    +          Create instance through factory method.
    + ControllerSession.getController() + +
    +          Return command controller.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Dispatcher.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Dispatcher.html new file mode 100755 index 0000000000..c8ccd83bca --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Dispatcher.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Dispatcher + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Dispatcher

    +
    + + + + + + + + + +
    +Packages that use Dispatcher
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Dispatcher in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Dispatcher
    +static DispatcherDispatcher.getInstance() + +
    +          Singleton pattern: get single instance.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Event.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Event.html new file mode 100755 index 0000000000..50717b0574 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Event.html @@ -0,0 +1,423 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Event + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Event

    +
    + + + + + + + + + + + + + +
    +Packages that use Event
    nl.justobjects.pushlet.client  
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Event in nl.justobjects.pushlet.client
    +  +

    + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.client with parameters of type Event
    + voidPushletClientListener.onAbort(Event theEvent) + +
    +          Abort event from server.
    + voidPushletClientListener.onData(Event theEvent) + +
    +          Data event from server.
    + voidPushletClientListener.onHeartbeat(Event theEvent) + +
    +          Heartbeat event from server.
    +  +

    + + + + + +
    +Uses of Event in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Fields in nl.justobjects.pushlet.core declared as Event
    + EventCommand.reqEvent + +
    +          Pushlet request event.
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Event
    +static EventEvent.createDataEvent(java.lang.String aSubject) + +
    +           
    +static EventEvent.createDataEvent(java.lang.String aSubject, + java.util.Map theAttributes) + +
    +           
    + EventEventQueue.deQueue() + +
    +          Get head; if empty wait until something in queue.
    + EventEventQueue.deQueue(long maxWaitTime) + +
    +          Get head; if empty wait for specified time at max.
    + Event[]EventQueue.deQueueAll(long maxWaitTime) + +
    +          Get all queued Events.
    + EventCommand.getResponseEvent() + +
    +          Get pushlet response event.
    +static EventEventParser.parse(java.io.File aFile) + +
    +          Parse Event from a File.
    +static EventEventParser.parse(java.io.Reader aReader) + +
    +          Parse Event from input Reader.
    +static EventEventParser.parse(java.lang.String aString) + +
    +          Parse Event from a String.
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core with parameters of type Event
    + voidDispatcher.broadcast(Event anEvent) + +
    +          Send event to all subscribers.
    +static CommandCommand.create(Session aSession, + Event aReqEvent, + javax.servlet.http.HttpServletRequest aHTTPReq, + javax.servlet.http.HttpServletResponse aHTTPRsp) + +
    +          Create new Command object.
    + SessionSessionManager.createSession(Event anEvent) + +
    +          Create new Session (but add later).
    + booleanEventQueue.enQueue(Event item) + +
    +          Put item in queue; waits() indefinitely if queue is full.
    + booleanEventQueue.enQueue(Event item, + long maxWaitTime) + +
    +          Put item in queue; if full wait maxtime.
    + booleanSubscription.match(Event event) + +
    +          Determine if Event matches subscription.
    + SubscriptionSubscriber.match(Event event) + +
    +          Determine if we should receive event.
    + voidDispatcher.multicast(Event anEvent) + +
    +          Send event to subscribers matching Event subject.
    + voidSubscriber.onEvent(Event theEvent) + +
    +          Event from Dispatcher: enqueue it.
    + voidClientAdapter.push(Event anEvent) + +
    +          Push single Event to client.
    + voidBrowserAdapter.push(Event anEvent) + +
    +          Push Event to client.
    + voidCommand.setResponseEvent(Event aResponseEvent) + +
    +          Set pushlet response event.
    + voidDispatcher.unicast(Event event, + java.lang.String aSessionId) + +
    +          Send event to specific subscriber.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventParser.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventParser.html new file mode 100755 index 0000000000..8d75087ded --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventParser.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.EventParser + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.EventParser

    +
    +No usage of nl.justobjects.pushlet.core.EventParser +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventPullSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventPullSource.html new file mode 100755 index 0000000000..b5b040cdba --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventPullSource.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.EventPullSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.EventPullSource

    +
    +No usage of nl.justobjects.pushlet.core.EventPullSource +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventQueue.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventQueue.html new file mode 100755 index 0000000000..fb00ab765a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventQueue.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.EventQueue + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.EventQueue

    +
    +No usage of nl.justobjects.pushlet.core.EventQueue +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSource.html new file mode 100755 index 0000000000..56109cb391 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSource.html @@ -0,0 +1,209 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.core.EventSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.core.EventSource

    +
    + + + + + + + + + + + + + +
    +Packages that use EventSource
    nl.justobjects.pushlet.core  
    pow.webserver  
    +  +

    + + + + + +
    +Uses of EventSource in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Classes in nl.justobjects.pushlet.core that implement EventSource
    + classEventPullSource + +
    +          ABC for specifc EventPullSources.
    +  +

    + + + + + +
    +Uses of EventSource in pow.webserver
    +  +

    + + + + + + + + + +
    Classes in pow.webserver that implement EventSource
    +static classServeur.IvyEventSource + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSourceManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSourceManager.html new file mode 100755 index 0000000000..1be8aada5b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/EventSourceManager.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.EventSourceManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.EventSourceManager

    +
    +No usage of nl.justobjects.pushlet.core.EventSourceManager +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Protocol.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Protocol.html new file mode 100755 index 0000000000..c5ac055017 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Protocol.html @@ -0,0 +1,302 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.core.Protocol + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.core.Protocol

    +
    + + + + + + + + + + + + + + + + + +
    +Packages that use Protocol
    nl.justobjects.pushlet.client  
    nl.justobjects.pushlet.core  
    nl.justobjects.pushlet.servlet  
    +  +

    + + + + + +
    +Uses of Protocol in nl.justobjects.pushlet.client
    +  +

    + + + + + + + + + +
    Subinterfaces of Protocol in nl.justobjects.pushlet.client
    + interfacePushletClientListener + +
    +          Interface for listener of the PushletClient object.
    +  +

    + + + + + + + + + +
    Classes in nl.justobjects.pushlet.client that implement Protocol
    + classPushletClient + +
    +          Client API for Java HTTP client applets or apps.
    +  +

    + + + + + +
    +Uses of Protocol in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Classes in nl.justobjects.pushlet.core that implement Protocol
    + classBrowserAdapter + +
    +          Generic implementation of ClientAdapter for browser clients.
    + classCommand + +
    +          Wraps pushlet request/response data.
    + classController + +
    +          Handles servlet requests from client.
    + classDispatcher + +
    +          Routes Events to Subscribers.
    + classEvent + +
    +          Represents the event data.
    + classSession + +
    +          Represents client pushlet session state.
    + classSubscriber + +
    +          Handles data channel between dispatcher and client.
    +  +

    + + + + + +
    +Uses of Protocol in nl.justobjects.pushlet.servlet
    +  +

    + + + + + + + + + +
    Classes in nl.justobjects.pushlet.servlet that implement Protocol
    + classPushlet + +
    +          Servlet runs a Subscriber per request.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Session.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Session.html new file mode 100755 index 0000000000..994d9fa1be --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Session.html @@ -0,0 +1,287 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Session + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Session

    +
    + + + + + + + + + +
    +Packages that use Session
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Session in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Fields in nl.justobjects.pushlet.core declared as Session
    + SessionCommand.session + +
    +          Pushlet session.
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Session
    +static SessionSession.create(java.lang.String anId) + +
    +          Create instance through factory method.
    + SessionSessionManager.createSession(Event anEvent) + +
    +          Create new Session (but add later).
    + SessionSubscriber.getSession() + +
    +          Return client session.
    + SessionSessionManager.getSession(java.lang.String anId) + +
    +          Get Session by session id.
    + Session[]SessionManager.getSessions() + +
    +          Get copy of listening Sessions.
    + SessionSessionManager.removeSession(Session aSession) + +
    +          Register session for removal.
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core with parameters of type Session
    + voidSessionManager.addSession(Session session) + +
    +          Add session.
    +static SubscriberSubscriber.create(Session aSession) + +
    +          Create instance through factory method.
    +static ControllerController.create(Session aSession) + +
    +          Create instance through factory method.
    +static CommandCommand.create(Session aSession, + Event aReqEvent, + javax.servlet.http.HttpServletRequest aHTTPReq, + javax.servlet.http.HttpServletResponse aHTTPRsp) + +
    +          Create new Command object.
    + SessionSessionManager.removeSession(Session aSession) + +
    +          Register session for removal.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/SessionManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/SessionManager.html new file mode 100755 index 0000000000..3850cbaf0f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/SessionManager.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.SessionManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.SessionManager

    +
    + + + + + + + + + +
    +Packages that use SessionManager
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of SessionManager in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return SessionManager
    +static SessionManagerSessionManager.getInstance() + +
    +          Singleton pattern: get single instance.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscriber.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscriber.html new file mode 100755 index 0000000000..90e5e479cc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscriber.html @@ -0,0 +1,196 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Subscriber + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Subscriber

    +
    + + + + + + + + + +
    +Packages that use Subscriber
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Subscriber in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Subscriber
    +static SubscriberSubscriber.create(Session aSession) + +
    +          Create instance through factory method.
    + SubscriberSession.getSubscriber() + +
    +          Return subscriber.
    + SubscriberController.getSubscriber() + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscription.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscription.html new file mode 100755 index 0000000000..d5cca49ecf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/class-use/Subscription.html @@ -0,0 +1,222 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.core.Subscription + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.core.Subscription

    +
    + + + + + + + + + +
    +Packages that use Subscription
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of Subscription in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that return Subscription
    + SubscriptionSubscriber.addSubscription(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Add a subscription.
    +static SubscriptionSubscription.create(java.lang.String aSubject) + +
    +          Create instance through factory method.
    +static SubscriptionSubscription.create(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Create instance through factory method.
    + Subscription[]Subscriber.getSubscriptions() + +
    +          Return subscriptions.
    + SubscriptionSubscriber.match(Event event) + +
    +          Determine if we should receive event.
    + SubscriptionSubscriber.removeSubscription(java.lang.String aSubscriptionId) + +
    +          Remove a subscription.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-frame.html new file mode 100755 index 0000000000..119c97abb3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-frame.html @@ -0,0 +1,75 @@ + + + + + + +nl.justobjects.pushlet.core + + + + + + + + + + + +nl.justobjects.pushlet.core + + + + +
    +Interfaces  + +
    +ClientAdapter +
    +ConfigDefs +
    +EventSource +
    +Protocol
    + + + + + + +
    +Classes  + +
    +BrowserAdapter +
    +Command +
    +Config +
    +Controller +
    +Dispatcher +
    +Event +
    +EventParser +
    +EventPullSource +
    +EventQueue +
    +EventSourceManager +
    +Session +
    +SessionManager +
    +Subscriber +
    +Subscription
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-summary.html new file mode 100755 index 0000000000..407d1ab569 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-summary.html @@ -0,0 +1,235 @@ + + + + + + +nl.justobjects.pushlet.core + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package nl.justobjects.pushlet.core +

    + + + + + + + + + + + + + + + + + + + + + +
    +Interface Summary
    ClientAdapterAdapter interface for encapsulation of specific HTTP clients.
    ConfigDefsDefinition of config property strings.
    EventSourceInterface for specifc Event(Pull/Push)Sources.
    ProtocolConstants for Pushlet protocols.
    +  + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Class Summary
    BrowserAdapterGeneric implementation of ClientAdapter for browser clients.
    CommandWraps pushlet request/response data.
    ConfigLoads and maintains overall configuration.
    ControllerHandles servlet requests from client.
    DispatcherRoutes Events to Subscribers.
    EventRepresents the event data.
    EventParserParses XML into Event objects.
    EventPullSourceABC for specifc EventPullSources.
    EventQueueFIFO queue with guarded suspension.
    EventSourceManagerMaintains lifecycle of event sources.
    SessionRepresents client pushlet session state.
    SessionManagerManages lifecycle of Sessions.
    SubscriberHandles data channel between dispatcher and client.
    SubscriptionRepresents single subject subscription
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-tree.html new file mode 100755 index 0000000000..f3cb407847 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-tree.html @@ -0,0 +1,169 @@ + + + + + + +nl.justobjects.pushlet.core Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package nl.justobjects.pushlet.core +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    + +

    +Interface Hierarchy +

    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-use.html new file mode 100755 index 0000000000..cadd226116 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/core/package-use.html @@ -0,0 +1,318 @@ + + + + + + +Uses of Package nl.justobjects.pushlet.core + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    nl.justobjects.pushlet.core

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Packages that use nl.justobjects.pushlet.core
    nl.justobjects.pushlet.client  
    nl.justobjects.pushlet.core  
    nl.justobjects.pushlet.servlet  
    nl.justobjects.pushlet.util  
    pow.webserver  
    +  +

    + + + + + + + + + + + +
    +Classes in nl.justobjects.pushlet.core used by nl.justobjects.pushlet.client
    Event + +
    +          Represents the event data.
    Protocol + +
    +          Constants for Pushlet protocols.
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Classes in nl.justobjects.pushlet.core used by nl.justobjects.pushlet.core
    ClientAdapter + +
    +          Adapter interface for encapsulation of specific HTTP clients.
    Command + +
    +          Wraps pushlet request/response data.
    ConfigDefs + +
    +          Definition of config property strings.
    Controller + +
    +          Handles servlet requests from client.
    Dispatcher + +
    +          Routes Events to Subscribers.
    Event + +
    +          Represents the event data.
    EventSource + +
    +          Interface for specifc Event(Pull/Push)Sources.
    Protocol + +
    +          Constants for Pushlet protocols.
    Session + +
    +          Represents client pushlet session state.
    SessionManager + +
    +          Manages lifecycle of Sessions.
    Subscriber + +
    +          Handles data channel between dispatcher and client.
    Subscription + +
    +          Represents single subject subscription
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.core used by nl.justobjects.pushlet.servlet
    Protocol + +
    +          Constants for Pushlet protocols.
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.core used by nl.justobjects.pushlet.util
    ConfigDefs + +
    +          Definition of config property strings.
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.core used by pow.webserver
    EventSource + +
    +          Interface for specifc Event(Pull/Push)Sources.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-frame.html new file mode 100755 index 0000000000..94d69f80bf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-frame.html @@ -0,0 +1,32 @@ + + + + + + +nl.justobjects.pushlet + + + + + + + + + + + +nl.justobjects.pushlet + + + + +
    +Classes  + +
    +Version
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-summary.html new file mode 100755 index 0000000000..eaa2e994bd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-summary.html @@ -0,0 +1,157 @@ + + + + + + +nl.justobjects.pushlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package nl.justobjects.pushlet +

    + + + + + + + + + +
    +Class Summary
    VersionVersion info class.
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-tree.html new file mode 100755 index 0000000000..bfff2aa261 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-tree.html @@ -0,0 +1,153 @@ + + + + + + +nl.justobjects.pushlet Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package nl.justobjects.pushlet +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    +
      +
    • java.lang.Object +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-use.html new file mode 100755 index 0000000000..8c57ff1ce2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/package-use.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Package nl.justobjects.pushlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    nl.justobjects.pushlet

    +
    +No usage of nl.justobjects.pushlet +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/Pushlet.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/Pushlet.html new file mode 100755 index 0000000000..13187fa22c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/Pushlet.html @@ -0,0 +1,393 @@ + + + + + + +Pushlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.servlet +
    +Class Pushlet

    +
    +java.lang.Object
    +  extended by javax.servlet.GenericServlet
    +      extended by javax.servlet.http.HttpServlet
    +          extended by nl.justobjects.pushlet.servlet.Pushlet
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig, Protocol
    +
    +
    +
    +
    public class Pushlet
    extends javax.servlet.http.HttpServlet
    implements Protocol
    + + +

    +Servlet runs a Subscriber per request. +

    + +

    +

    +
    Version:
    +
    $Id: Pushlet.java,v 1.23 2007/12/04 13:55:53 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.Protocol
    DEFAULT_SERVLET_URI, E_ABORT, E_DATA, E_HEARTBEAT, E_HEARTBEAT_ACK, E_JOIN, E_JOIN_ACK, E_JOIN_LISTEN, E_JOIN_LISTEN_ACK, E_LEAVE, E_LEAVE_ACK, E_LISTEN, E_LISTEN_ACK, E_NACK, E_PUBLISH, E_PUBLISH_ACK, E_REFRESH, E_REFRESH_ACK, E_SUBSCRIBE, E_SUBSCRIBE_ACK, E_UNSUBSCRIBE, E_UNSUBSCRIBE_ACK, FORMAT_JAVASCRIPT, FORMAT_SERIALIZED_JAVA_OBJECT, FORMAT_XML, FORMAT_XML_STRICT, MODE_POLL, MODE_PULL, MODE_STREAM, P_EVENT, P_FORMAT, P_FROM, P_ID, P_MODE, P_REASON, P_SEQ, P_SUBJECT, P_SUBSCRIPTION_ID, P_SUBSCRIPTION_LABEL, P_TIME, P_TO, P_URL, P_WAIT, SUBJECT_META, SUBJECT_META_JOINS, SUBJECT_META_SUBS
    +  + + + + + + + + + + +
    +Constructor Summary
    Pushlet() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voiddestroy() + +
    +           
    + voiddoGet(javax.servlet.http.HttpServletRequest request, + javax.servlet.http.HttpServletResponse response) + +
    +          Servlet GET request: handles event requests.
    + voiddoPost(javax.servlet.http.HttpServletRequest request, + javax.servlet.http.HttpServletResponse response) + +
    +          Servlet POST request: extracts event data from body.
    + voidinit() + +
    +           
    + + + + + + + +
    Methods inherited from class javax.servlet.http.HttpServlet
    service
    + + + + + + + +
    Methods inherited from class javax.servlet.GenericServlet
    getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Pushlet

    +
    +public Pushlet()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init()
    +          throws javax.servlet.ServletException
    +
    +
    +
    Overrides:
    init in class javax.servlet.GenericServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException
    +
    +
    +
    + +

    +destroy

    +
    +public void destroy()
    +
    +
    +
    Specified by:
    destroy in interface javax.servlet.Servlet
    Overrides:
    destroy in class javax.servlet.GenericServlet
    +
    +
    +
    +
    +
    +
    + +

    +doGet

    +
    +public void doGet(javax.servlet.http.HttpServletRequest request,
    +                  javax.servlet.http.HttpServletResponse response)
    +           throws javax.servlet.ServletException,
    +                  java.io.IOException
    +
    +
    Servlet GET request: handles event requests. +

    +

    +
    Overrides:
    doGet in class javax.servlet.http.HttpServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException +
    java.io.IOException
    +
    +
    +
    + +

    +doPost

    +
    +public void doPost(javax.servlet.http.HttpServletRequest request,
    +                   javax.servlet.http.HttpServletResponse response)
    +            throws javax.servlet.ServletException,
    +                   java.io.IOException
    +
    +
    Servlet POST request: extracts event data from body. +

    +

    +
    Overrides:
    doPost in class javax.servlet.http.HttpServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException +
    java.io.IOException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/class-use/Pushlet.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/class-use/Pushlet.html new file mode 100755 index 0000000000..35d5559cdf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/class-use/Pushlet.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.servlet.Pushlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.servlet.Pushlet

    +
    +No usage of nl.justobjects.pushlet.servlet.Pushlet +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-frame.html new file mode 100755 index 0000000000..dbfc6c327c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-frame.html @@ -0,0 +1,32 @@ + + + + + + +nl.justobjects.pushlet.servlet + + + + + + + + + + + +nl.justobjects.pushlet.servlet + + + + +
    +Classes  + +
    +Pushlet
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-summary.html new file mode 100755 index 0000000000..f27cba36c1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-summary.html @@ -0,0 +1,157 @@ + + + + + + +nl.justobjects.pushlet.servlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package nl.justobjects.pushlet.servlet +

    + + + + + + + + + +
    +Class Summary
    PushletServlet runs a Subscriber per request.
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-tree.html new file mode 100755 index 0000000000..f123e72142 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-tree.html @@ -0,0 +1,160 @@ + + + + + + +nl.justobjects.pushlet.servlet Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package nl.justobjects.pushlet.servlet +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    +
      +
    • java.lang.Object
        +
      • javax.servlet.GenericServlet (implements java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig) +
          +
        • javax.servlet.http.HttpServlet (implements java.io.Serializable) +
            +
          • nl.justobjects.pushlet.servlet.Pushlet (implements nl.justobjects.pushlet.core.Protocol) +
          +
        +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-use.html new file mode 100755 index 0000000000..6d7fc88a89 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/servlet/package-use.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Package nl.justobjects.pushlet.servlet + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    nl.justobjects.pushlet.servlet

    +
    +No usage of nl.justobjects.pushlet.servlet +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/DefaultLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/DefaultLogger.html new file mode 100755 index 0000000000..848a70a702 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/DefaultLogger.html @@ -0,0 +1,538 @@ + + + + + + +DefaultLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class DefaultLogger

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.DefaultLogger
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, PushletLogger
    +
    +
    +
    +
    public class DefaultLogger
    extends java.lang.Object
    implements PushletLogger
    + + +

    +Default logger. +

    + Logs to stdout. Override this class by setting "logger.class" in pushlet.properties to your own logger + to integrate your own logging library. +

    + +

    +

    +
    Version:
    +
    $Id: DefaultLogger.java,v 1.2 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + +
    +Constructor Summary
    DefaultLogger() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voiddebug(java.lang.String aMessage) + +
    +          Log message for debug level.
    + voiderror(java.lang.String aMessage) + +
    +          Log message for error level.
    + voiderror(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (error level with exception).
    + voidfatal(java.lang.String aMessage) + +
    +          Log message for fatal level.
    + voidfatal(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (fatal level with exception).
    + voidinfo(java.lang.String aMessage) + +
    +          Log message for info level.
    + voidinit() + +
    +          Method allowing to initialize our logger
    + voidsetLevel(int aLevel) + +
    +          Set log level
    + voidtrace(java.lang.String aMessage) + +
    +          Log message for trace level.
    + voidwarn(java.lang.String aMessage) + +
    +          Log message for warning level.
    + voidwarn(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message for warning level with exception.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +DefaultLogger

    +
    +public DefaultLogger()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init()
    +
    +
    Description copied from interface: PushletLogger
    +
    Method allowing to initialize our logger +

    +

    +
    Specified by:
    init in interface PushletLogger
    +
    +
    +
    +
    +
    +
    + +

    +trace

    +
    +public void trace(java.lang.String aMessage)
    +
    +
    Log message for trace level. +

    +

    +
    Specified by:
    trace in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +debug

    +
    +public void debug(java.lang.String aMessage)
    +
    +
    Log message for debug level. +

    +

    +
    Specified by:
    debug in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +info

    +
    +public void info(java.lang.String aMessage)
    +
    +
    Log message for info level. +

    +

    +
    Specified by:
    info in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public void warn(java.lang.String aMessage)
    +
    +
    Log message for warning level. +

    +

    +
    Specified by:
    warn in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public void warn(java.lang.String aMessage,
    +                 java.lang.Throwable aThrowable)
    +
    +
    Log message for warning level with exception. +

    +

    +
    Specified by:
    warn in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +error

    +
    +public void error(java.lang.String aMessage)
    +
    +
    Log message for error level. +

    +

    +
    Specified by:
    error in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +error

    +
    +public void error(java.lang.String aMessage,
    +                  java.lang.Throwable aThrowable)
    +
    +
    Log message (error level with exception). +

    +

    +
    Specified by:
    error in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +fatal

    +
    +public void fatal(java.lang.String aMessage)
    +
    +
    Log message for fatal level. +

    +

    +
    Specified by:
    fatal in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +fatal

    +
    +public void fatal(java.lang.String aMessage,
    +                  java.lang.Throwable aThrowable)
    +
    +
    Log message (fatal level with exception). +

    +

    +
    Specified by:
    fatal in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +setLevel

    +
    +public void setLevel(int aLevel)
    +
    +
    Set log level +

    +

    +
    Specified by:
    setLevel in interface PushletLogger
    +
    +
    +
    Parameters:
    aLevel - the message to be logged
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log.html new file mode 100755 index 0000000000..e3ebf07a3e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log.html @@ -0,0 +1,538 @@ + + + + + + +Log + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class Log

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.Log
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs
    +
    +
    +
    +
    public class Log
    extends java.lang.Object
    implements ConfigDefs
    + + +

    +Logging wrapper. +

    + Provides a hook to direct logging to your own logging library. Override the DefaultLogger class by setting + "logger.class" in pushlet.properties to your own logger + to integrate your own logging library. +

    + +

    +

    +
    Version:
    +
    $Id: Log.java,v 1.5 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + +
    +Constructor Summary
    Log() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static voiddebug(java.lang.String aMessage) + +
    +          Log message for debug level.
    +static voiderror(java.lang.String aMessage) + +
    +          Log message for error level.
    +static voiderror(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (error level with exception).
    +static voidfatal(java.lang.String aMessage) + +
    +          Log message for fatal level.
    +static voidfatal(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (fatal level with exception).
    +static voidinfo(java.lang.String aMessage) + +
    +          Log message for info level.
    +static voidinit() + +
    +          General purpose initialization.
    +static voidsetLevel(int aLevel) + +
    +          Set log level
    +static voidtrace(java.lang.String aMessage) + +
    +          Log message for trace level.
    +static voidwarn(java.lang.String aMessage) + +
    +          Log message for warning level.
    +static voidwarn(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message for warning level with exception.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Log

    +
    +public Log()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public static void init()
    +
    +
    General purpose initialization. +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +trace

    +
    +public static void trace(java.lang.String aMessage)
    +
    +
    Log message for trace level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +debug

    +
    +public static void debug(java.lang.String aMessage)
    +
    +
    Log message for debug level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +info

    +
    +public static void info(java.lang.String aMessage)
    +
    +
    Log message for info level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public static void warn(java.lang.String aMessage)
    +
    +
    Log message for warning level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public static void warn(java.lang.String aMessage,
    +                        java.lang.Throwable aThrowable)
    +
    +
    Log message for warning level with exception. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +error

    +
    +public static void error(java.lang.String aMessage)
    +
    +
    Log message for error level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +error

    +
    +public static void error(java.lang.String aMessage,
    +                         java.lang.Throwable aThrowable)
    +
    +
    Log message (error level with exception). +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +fatal

    +
    +public static void fatal(java.lang.String aMessage)
    +
    +
    Log message for fatal level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +fatal

    +
    +public static void fatal(java.lang.String aMessage,
    +                         java.lang.Throwable aThrowable)
    +
    +
    Log message (fatal level with exception). +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +setLevel

    +
    +public static void setLevel(int aLevel)
    +
    +
    Set log level +

    +

    +
    +
    +
    +
    Parameters:
    aLevel - the message to be logged
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log4jLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log4jLogger.html new file mode 100755 index 0000000000..bd4fcaf448 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Log4jLogger.html @@ -0,0 +1,548 @@ + + + + + + +Log4jLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class Log4jLogger

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.Log4jLogger
    +
    +
    +
    All Implemented Interfaces:
    ConfigDefs, PushletLogger
    +
    +
    +
    +
    public class Log4jLogger
    extends java.lang.Object
    implements PushletLogger
    + + +

    +Logger to use Log4j for logging. +

    + Logs using Log4j. + This class will require a log4j library in the classpath of the Pushlet. +

    + +

    +

    +
    Version:
    +
    $Id: Log4jLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Uli Romahn
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + +
    +Constructor Summary
    Log4jLogger() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voiddebug(java.lang.String aMessage) + +
    +          Log message for debug level.
    + voiderror(java.lang.String aMessage) + +
    +          Log message for error level.
    + voiderror(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (error level with exception).
    + voidfatal(java.lang.String aMessage) + +
    +          Log message for fatal level.
    + voidfatal(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (fatal level with exception).
    + voidinfo(java.lang.String aMessage) + +
    +          Log message for info level.
    + voidinit() + +
    +          Method allowing to initialize our logger
    + voidsetLevel(int aLevel) + +
    +          Set log level
    + voidtrace(java.lang.String aMessage) + +
    +          Log message for trace level.
    + voidwarn(java.lang.String aMessage) + +
    +          Log message for warning level.
    + voidwarn(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message for warning level with exception.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Log4jLogger

    +
    +public Log4jLogger()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init()
    +
    +
    Description copied from interface: PushletLogger
    +
    Method allowing to initialize our logger +

    +

    +
    Specified by:
    init in interface PushletLogger
    +
    +
    +
    +
    +
    +
    + +

    +debug

    +
    +public void debug(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for debug level. +

    +

    +
    Specified by:
    debug in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +error

    +
    +public void error(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for error level. +

    +

    +
    Specified by:
    error in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +error

    +
    +public void error(java.lang.String aMessage,
    +                  java.lang.Throwable aThrowable)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message (error level with exception). +

    +

    +
    Specified by:
    error in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +fatal

    +
    +public void fatal(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for fatal level. +

    +

    +
    Specified by:
    fatal in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +fatal

    +
    +public void fatal(java.lang.String aMessage,
    +                  java.lang.Throwable aThrowable)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message (fatal level with exception). +

    +

    +
    Specified by:
    fatal in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +info

    +
    +public void info(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for info level. +

    +

    +
    Specified by:
    info in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +trace

    +
    +public void trace(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for trace level. +

    +

    +
    Specified by:
    trace in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public void warn(java.lang.String aMessage)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for warning level. +

    +

    +
    Specified by:
    warn in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +public void warn(java.lang.String aMessage,
    +                 java.lang.Throwable aThrowable)
    +
    +
    Description copied from interface: PushletLogger
    +
    Log message for warning level with exception. +

    +

    +
    Specified by:
    warn in interface PushletLogger
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +setLevel

    +
    +public void setLevel(int aLevel)
    +
    +
    Description copied from interface: PushletLogger
    +
    Set log level +

    +

    +
    Specified by:
    setLevel in interface PushletLogger
    +
    +
    +
    Parameters:
    aLevel - a valid Level from ConfigDefs
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletException.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletException.html new file mode 100755 index 0000000000..86bd047644 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletException.html @@ -0,0 +1,309 @@ + + + + + + +PushletException + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class PushletException

    +
    +java.lang.Object
    +  extended by java.lang.Throwable
    +      extended by java.lang.Exception
    +          extended by nl.justobjects.pushlet.util.PushletException
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable
    +
    +
    +
    +
    public class PushletException
    extends java.lang.Exception
    + + +

    +Generic exception wrapper. +

    + +

    +

    +
    Version:
    +
    $Id: PushletException.java,v 1.1 2005/02/15 15:14:34 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + + + + + + + +
    +Constructor Summary
    PushletException(java.lang.String aMessage) + +
    +           
    PushletException(java.lang.String aMessage, + java.lang.Throwable t) + +
    +           
    PushletException(java.lang.Throwable t) + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringtoString() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Throwable
    fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +PushletException

    +
    +public PushletException(java.lang.String aMessage,
    +                        java.lang.Throwable t)
    +
    +
    +
    + +

    +PushletException

    +
    +public PushletException(java.lang.String aMessage)
    +
    +
    +
    + +

    +PushletException

    +
    +public PushletException(java.lang.Throwable t)
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Throwable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletLogger.html new file mode 100755 index 0000000000..434ae4992b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/PushletLogger.html @@ -0,0 +1,492 @@ + + + + + + +PushletLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Interface PushletLogger

    +
    +
    All Superinterfaces:
    ConfigDefs
    +
    +
    +
    All Known Implementing Classes:
    DefaultLogger, Log4jLogger
    +
    +
    +
    +
    public interface PushletLogger
    extends ConfigDefs
    + + +

    +Logger interface to allow different logging providers. +

    +

    + +

    +

    +
    Version:
    +
    $Id: PushletLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Ulrich Romahn
    +
    +
    + +

    + + + + + + + +
    +Field Summary
    + + + + + + + +
    Fields inherited from interface nl.justobjects.pushlet.core.ConfigDefs
    CONTROLLER_CLASS, DISPATCHER_CLASS, LISTEN_FORCE_PULL_AGENTS, LISTEN_FORCE_PULL_ALL, LOG_LEVEL, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_TRACE, LOG_LEVEL_WARN, LOGGER_CLASS, POLL_REFRESH_TIMEOUT_MILLIS, POLL_REFRESH_WAIT_MAX_MILLIS, POLL_REFRESH_WAIT_MIN_MILLIS, PULL_REFRESH_TIMEOUT_MILLIS, PULL_REFRESH_WAIT_MAX_MILLIS, PULL_REFRESH_WAIT_MIN_MILLIS, QUEUE_READ_TIMEOUT_MILLIS, QUEUE_SIZE, QUEUE_WRITE_TIMEOUT_MILLIS, SESSION_CLASS, SESSION_ID_GENERATION, SESSION_ID_GENERATION_RANDOMSTRING, SESSION_ID_GENERATION_UUID, SESSION_ID_SIZE, SESSION_MANAGER_CLASS, SESSION_TIMEOUT_MINS, SOURCES_ACTIVATE, SUBSCRIBER_CLASS, SUBSCRIPTION_CLASS
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voiddebug(java.lang.String aMessage) + +
    +          Log message for debug level.
    + voiderror(java.lang.String aMessage) + +
    +          Log message for error level.
    + voiderror(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (error level with exception).
    + voidfatal(java.lang.String aMessage) + +
    +          Log message for fatal level.
    + voidfatal(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message (fatal level with exception).
    + voidinfo(java.lang.String aMessage) + +
    +          Log message for info level.
    + voidinit() + +
    +          Method allowing to initialize our logger
    + voidsetLevel(int aLevel) + +
    +          Set log level
    + voidtrace(java.lang.String aMessage) + +
    +          Log message for trace level.
    + voidwarn(java.lang.String aMessage) + +
    +          Log message for warning level.
    + voidwarn(java.lang.String aMessage, + java.lang.Throwable aThrowable) + +
    +          Log message for warning level with exception.
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +void init()
    +
    +
    Method allowing to initialize our logger +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +trace

    +
    +void trace(java.lang.String aMessage)
    +
    +
    Log message for trace level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +debug

    +
    +void debug(java.lang.String aMessage)
    +
    +
    Log message for debug level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +info

    +
    +void info(java.lang.String aMessage)
    +
    +
    Log message for info level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +void warn(java.lang.String aMessage)
    +
    +
    Log message for warning level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +warn

    +
    +void warn(java.lang.String aMessage,
    +          java.lang.Throwable aThrowable)
    +
    +
    Log message for warning level with exception. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +error

    +
    +void error(java.lang.String aMessage)
    +
    +
    Log message for error level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +error

    +
    +void error(java.lang.String aMessage,
    +           java.lang.Throwable aThrowable)
    +
    +
    Log message (error level with exception). +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +fatal

    +
    +void fatal(java.lang.String aMessage)
    +
    +
    Log message for fatal level. +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    +
    +
    +
    + +

    +fatal

    +
    +void fatal(java.lang.String aMessage,
    +           java.lang.Throwable aThrowable)
    +
    +
    Log message (fatal level with exception). +

    +

    +
    +
    +
    +
    Parameters:
    aMessage - the message to be logged
    aThrowable - the exception
    +
    +
    +
    + +

    +setLevel

    +
    +void setLevel(int aLevel)
    +
    +
    Set log level +

    +

    +
    +
    +
    +
    Parameters:
    aLevel - a valid Level from ConfigDefs
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Rand.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Rand.html new file mode 100755 index 0000000000..406ce07389 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Rand.html @@ -0,0 +1,622 @@ + + + + + + +Rand + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class Rand

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.Rand
    +
    +
    +
    +
    public class Rand
    extends java.lang.Object
    + + +

    +Randomizing routines. +

    + +

    +

    +
    Version:
    +
    $Id: Rand.java,v 1.4 2007/12/07 12:57:40 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Rand() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static java.io.FilerandomBinaryFile(int aSize) + +
    +           
    +static byte[]randomBlob(int aSize) + +
    +           
    +static byterandomByte() + +
    +           
    +static byte[]randomBytes(int aSize) + +
    +           
    +static charrandomChar() + +
    +           
    +static doublerandomDouble() + +
    +           
    +static intrandomInt() + +
    +           
    +static intrandomInt(int min, + int max) + +
    +           
    +static longrandomLong() + +
    +           
    +static longrandomLong(long min, + long max) + +
    +           
    +static java.lang.StringrandomName(int aLength) + +
    +           
    +static charrandomNonVowel() + +
    +           
    +static voidrandomSleep(long min, + long max) + +
    +           
    +static java.lang.StringrandomString() + +
    +           
    +static java.lang.StringrandomString(int aLength) + +
    +           
    +static java.io.FilerandomTempDir() + +
    +           
    +static java.io.FilerandomTempFile() + +
    +           
    +static java.io.FilerandomTextFile(int aSize) + +
    +           
    +static charrandomVowel() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Rand

    +
    +public Rand()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +randomChar

    +
    +public static char randomChar()
    +
    +
    +
    +
    +
    +
    + +

    +randomVowel

    +
    +public static char randomVowel()
    +
    +
    +
    +
    +
    +
    + +

    +randomNonVowel

    +
    +public static char randomNonVowel()
    +
    +
    +
    +
    +
    +
    + +

    +randomTempDir

    +
    +public static java.io.File randomTempDir()
    +                                  throws java.lang.Exception
    +
    +
    + +
    Throws: +
    java.lang.Exception
    +
    +
    +
    + +

    +randomTempFile

    +
    +public static java.io.File randomTempFile()
    +                                   throws java.lang.Exception
    +
    +
    + +
    Throws: +
    java.lang.Exception
    +
    +
    +
    + +

    +randomBinaryFile

    +
    +public static java.io.File randomBinaryFile(int aSize)
    +                                     throws java.lang.Exception
    +
    +
    + +
    Throws: +
    java.lang.Exception
    +
    +
    +
    + +

    +randomTextFile

    +
    +public static java.io.File randomTextFile(int aSize)
    +                                   throws java.lang.Exception
    +
    +
    + +
    Throws: +
    java.lang.Exception
    +
    +
    +
    + +

    +randomBytes

    +
    +public static byte[] randomBytes(int aSize)
    +
    +
    +
    +
    +
    +
    + +

    +randomBlob

    +
    +public static byte[] randomBlob(int aSize)
    +
    +
    +
    +
    +
    +
    + +

    +randomByte

    +
    +public static byte randomByte()
    +
    +
    +
    +
    +
    +
    + +

    +randomDouble

    +
    +public static double randomDouble()
    +
    +
    +
    +
    +
    +
    + +

    +randomInt

    +
    +public static int randomInt()
    +
    +
    +
    +
    +
    +
    + +

    +randomInt

    +
    +public static int randomInt(int min,
    +                            int max)
    +
    +
    +
    +
    +
    +
    + +

    +randomLong

    +
    +public static long randomLong()
    +
    +
    +
    +
    +
    +
    + +

    +randomLong

    +
    +public static long randomLong(long min,
    +                              long max)
    +
    +
    +
    +
    +
    +
    + +

    +randomName

    +
    +public static java.lang.String randomName(int aLength)
    +
    +
    +
    +
    +
    +
    + +

    +randomSleep

    +
    +public static void randomSleep(long min,
    +                               long max)
    +
    +
    +
    +
    +
    +
    + +

    +randomString

    +
    +public static java.lang.String randomString(int aLength)
    +
    +
    +
    +
    +
    +
    + +

    +randomString

    +
    +public static java.lang.String randomString()
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Servlets.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Servlets.html new file mode 100755 index 0000000000..8166fff7e2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Servlets.html @@ -0,0 +1,312 @@ + + + + + + +Servlets + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class Servlets

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.Servlets
    +
    +
    +
    +
    public class Servlets
    extends java.lang.Object
    + + +

    +Servlet utilities. +

    + +

    +

    +
    Version:
    +
    $Id: Servlets.java,v 1.2 2007/11/23 21:10:17 justb Exp $
    +
    Author:
    +
    Just van den Broecke - Just Objects ©
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Servlets() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static java.lang.StringgetParameter(javax.servlet.http.HttpServletRequest aRequest, + java.lang.String aName) + +
    +          Get parameter; if not set or empty return null.
    +static java.lang.StringgetParameter(javax.servlet.http.HttpServletRequest aRequest, + java.lang.String aName, + java.lang.String aDefault) + +
    +          Get parameter; if not set or empty return specified default value.
    +static voidsetNoCacheHeaders(javax.servlet.http.HttpServletResponse aResponse) + +
    +          Set HTTP headers to prevent caching.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Servlets

    +
    +public Servlets()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getParameter

    +
    +public static java.lang.String getParameter(javax.servlet.http.HttpServletRequest aRequest,
    +                                            java.lang.String aName)
    +
    +
    Get parameter; if not set or empty return null. +

    +

    +
    +
    +
    +
    + +

    +getParameter

    +
    +public static java.lang.String getParameter(javax.servlet.http.HttpServletRequest aRequest,
    +                                            java.lang.String aName,
    +                                            java.lang.String aDefault)
    +
    +
    Get parameter; if not set or empty return specified default value. +

    +

    +
    +
    +
    +
    + +

    +setNoCacheHeaders

    +
    +public static void setNoCacheHeaders(javax.servlet.http.HttpServletResponse aResponse)
    +
    +
    Set HTTP headers to prevent caching. +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Sys.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Sys.html new file mode 100755 index 0000000000..033dbac5ec --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/Sys.html @@ -0,0 +1,351 @@ + + + + + + +Sys + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +nl.justobjects.pushlet.util +
    +Class Sys

    +
    +java.lang.Object
    +  extended by nl.justobjects.pushlet.util.Sys
    +
    +
    +
    +
    public class Sys
    extends java.lang.Object
    + + +

    +Utilities that interact with the underlying OS/JVM. +

    + +

    +

    +
    Version:
    +
    $Id: Sys.java,v 1.4 2007/11/10 14:17:18 justb Exp $
    +
    Author:
    +
    Just van den Broecke
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Sys() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static java.lang.StringforHTMLTag(java.lang.String aTagFragment) + +
    +          Replace characters having special meaning inside HTML tags + with their escaped equivalents, using character entities such as '&'.
    +static java.util.PropertiesloadPropertiesFile(java.lang.String aFilePath) + +
    +          Load properties file from file path.
    +static java.util.PropertiesloadPropertiesResource(java.lang.String aResourcePath) + +
    +          Load properties file from classpath.
    +static longnow() + +
    +          Shorthand for current time.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Sys

    +
    +public Sys()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +forHTMLTag

    +
    +public static java.lang.String forHTMLTag(java.lang.String aTagFragment)
    +
    +
    Replace characters having special meaning inside HTML tags + with their escaped equivalents, using character entities such as '&'. +

    +

    The escaped characters are : +

      +
    • < +
    • > +
    • " +
    • ' +
    • \ +
    • & +
    +

    +

    This method ensures that arbitrary text appearing inside a tag does not "confuse" + the tag. For example, HREF='Blah.do?Page=1&Sort=ASC' + does not comply with strict HTML because of the ampersand, and should be changed to + HREF='Blah.do?Page=1&Sort=ASC'. This is commonly seen in building + query strings. (In JSTL, the c:url tag performs this task automatically.) +

    +

    +
    +
    +
    +
    + +

    +loadPropertiesResource

    +
    +public static java.util.Properties loadPropertiesResource(java.lang.String aResourcePath)
    +                                                   throws java.io.IOException
    +
    +
    Load properties file from classpath. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +loadPropertiesFile

    +
    +public static java.util.Properties loadPropertiesFile(java.lang.String aFilePath)
    +                                               throws java.io.IOException
    +
    +
    Load properties file from file path. +

    +

    + +
    Throws: +
    java.io.IOException
    +
    +
    +
    + +

    +now

    +
    +public static long now()
    +
    +
    Shorthand for current time. +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/DefaultLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/DefaultLogger.html new file mode 100755 index 0000000000..61add5a443 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/DefaultLogger.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.DefaultLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.DefaultLogger

    +
    +No usage of nl.justobjects.pushlet.util.DefaultLogger +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log.html new file mode 100755 index 0000000000..ece188f484 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.Log + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.Log

    +
    +No usage of nl.justobjects.pushlet.util.Log +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log4jLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log4jLogger.html new file mode 100755 index 0000000000..60f499e256 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Log4jLogger.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.Log4jLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.Log4jLogger

    +
    +No usage of nl.justobjects.pushlet.util.Log4jLogger +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletException.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletException.html new file mode 100755 index 0000000000..fc784fd751 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletException.html @@ -0,0 +1,404 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.PushletException + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.PushletException

    +
    + + + + + + + + + + + + + +
    +Packages that use PushletException
    nl.justobjects.pushlet.client  
    nl.justobjects.pushlet.core  
    +  +

    + + + + + +
    +Uses of PushletException in nl.justobjects.pushlet.client
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.client that throw PushletException
    + voidPushletClient.join() + +
    +          Join server, starts session.
    + voidPushletClient.joinListen(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Immediate listener: joins/subscribes and listens in one action.
    + voidPushletClient.leave() + +
    +          Leave server, stops session.
    + voidPushletClient.listen(PushletClientListener aListener) + +
    +          Open data channel.
    + voidPushletClient.listen(PushletClientListener aListener, + java.lang.String aMode) + +
    +          Open data channel in stream or push mode.
    + voidPushletClient.listen(PushletClientListener aListener, + java.lang.String aMode, + java.lang.String aSubject) + +
    +          Open data channel in stream or push mode with a subject.
    + voidPushletClient.publish(java.lang.String aSubject, + java.util.Map theAttributes) + +
    +          Publish an event through server.
    + voidPushletClient.stopListen() + +
    +          Stop the listener.
    + java.lang.StringPushletClient.subscribe(java.lang.String aSubject) + +
    +          Subscribes, returning subscription id.
    + java.lang.StringPushletClient.subscribe(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Subscribes, returning subscription id.
    + voidPushletClient.unsubscribe() + +
    +          Unsubscribes from all subjects.
    + voidPushletClient.unsubscribe(java.lang.String aSubscriptionId) + +
    +          Unsubscribes with subscription id.
    +  +

    + + + + + +
    +Uses of PushletException in nl.justobjects.pushlet.core
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Methods in nl.justobjects.pushlet.core that throw PushletException
    + SubscriptionSubscriber.addSubscription(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Add a subscription.
    +static SubscriberSubscriber.create(Session aSession) + +
    +          Create instance through factory method.
    +static ControllerController.create(Session aSession) + +
    +          Create instance through factory method.
    +static SubscriptionSubscription.create(java.lang.String aSubject) + +
    +          Create instance through factory method.
    +static SessionSession.create(java.lang.String anId) + +
    +          Create instance through factory method.
    +static SubscriptionSubscription.create(java.lang.String aSubject, + java.lang.String aLabel) + +
    +          Create instance through factory method.
    +static java.lang.ObjectConfig.createObject(java.lang.String aClassNameProp, + java.lang.String aDefault) + +
    +          Factory method: create object from property denoting class name.
    + SessionSessionManager.createSession(Event anEvent) + +
    +          Create new Session (but add later).
    + voidSubscriber.fetchEvents(Command aCommand) + +
    +          Get events from queue and push to client.
    +static java.lang.ClassConfig.getClass(java.lang.String aClassNameProp, + java.lang.String aDefault) + +
    +          Factory method: create object from property denoting class name.
    + ClientAdapterCommand.getClientAdapter() + +
    +          Get client adapter for request.
    + voidSessionManager.start() + +
    +          Starts us.
    + voidDispatcher.start() + +
    +          Start Dispatcher.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletLogger.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletLogger.html new file mode 100755 index 0000000000..bac428fb26 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/PushletLogger.html @@ -0,0 +1,188 @@ + + + + + + +Uses of Interface nl.justobjects.pushlet.util.PushletLogger + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Interface
    nl.justobjects.pushlet.util.PushletLogger

    +
    + + + + + + + + + +
    +Packages that use PushletLogger
    nl.justobjects.pushlet.util  
    +  +

    + + + + + +
    +Uses of PushletLogger in nl.justobjects.pushlet.util
    +  +

    + + + + + + + + + + + + + +
    Classes in nl.justobjects.pushlet.util that implement PushletLogger
    + classDefaultLogger + +
    +          Default logger.
    + classLog4jLogger + +
    +          Logger to use Log4j for logging.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Rand.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Rand.html new file mode 100755 index 0000000000..d9c7ea1cb3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Rand.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.Rand + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.Rand

    +
    +No usage of nl.justobjects.pushlet.util.Rand +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Servlets.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Servlets.html new file mode 100755 index 0000000000..bde66d502d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Servlets.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.Servlets + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.Servlets

    +
    +No usage of nl.justobjects.pushlet.util.Servlets +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Sys.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Sys.html new file mode 100755 index 0000000000..08d21994c3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/class-use/Sys.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class nl.justobjects.pushlet.util.Sys + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    nl.justobjects.pushlet.util.Sys

    +
    +No usage of nl.justobjects.pushlet.util.Sys +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-frame.html new file mode 100755 index 0000000000..ca303f8d09 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-frame.html @@ -0,0 +1,64 @@ + + + + + + +nl.justobjects.pushlet.util + + + + + + + + + + + +nl.justobjects.pushlet.util + + + + +
    +Interfaces  + +
    +PushletLogger
    + + + + + + +
    +Classes  + +
    +DefaultLogger +
    +Log +
    +Log4jLogger +
    +Rand +
    +Servlets +
    +Sys
    + + + + + + +
    +Exceptions  + +
    +PushletException
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-summary.html new file mode 100755 index 0000000000..b49d7c9abc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-summary.html @@ -0,0 +1,205 @@ + + + + + + +nl.justobjects.pushlet.util + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package nl.justobjects.pushlet.util +

    + + + + + + + + + +
    +Interface Summary
    PushletLoggerLogger interface to allow different logging providers.
    +  + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Class Summary
    DefaultLoggerDefault logger.
    LogLogging wrapper.
    Log4jLoggerLogger to use Log4j for logging.
    RandRandomizing routines.
    ServletsServlet utilities.
    SysUtilities that interact with the underlying OS/JVM.
    +  + +

    + + + + + + + + + +
    +Exception Summary
    PushletExceptionGeneric exception wrapper.
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-tree.html new file mode 100755 index 0000000000..dc9b6206b8 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-tree.html @@ -0,0 +1,168 @@ + + + + + + +nl.justobjects.pushlet.util Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package nl.justobjects.pushlet.util +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    +
      +
    • java.lang.Object
        +
      • nl.justobjects.pushlet.util.DefaultLogger (implements nl.justobjects.pushlet.util.PushletLogger) +
      • nl.justobjects.pushlet.util.Log (implements nl.justobjects.pushlet.core.ConfigDefs) +
      • nl.justobjects.pushlet.util.Log4jLogger (implements nl.justobjects.pushlet.util.PushletLogger) +
      • nl.justobjects.pushlet.util.Rand
      • nl.justobjects.pushlet.util.Servlets
      • nl.justobjects.pushlet.util.Sys
      • java.lang.Throwable (implements java.io.Serializable) + +
      +
    +

    +Interface Hierarchy +

    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-use.html new file mode 100755 index 0000000000..fd4fe27f0a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/nl/justobjects/pushlet/util/package-use.html @@ -0,0 +1,208 @@ + + + + + + +Uses of Package nl.justobjects.pushlet.util + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    nl.justobjects.pushlet.util

    +
    + + + + + + + + + + + + + + + + + +
    +Packages that use nl.justobjects.pushlet.util
    nl.justobjects.pushlet.client  
    nl.justobjects.pushlet.core  
    nl.justobjects.pushlet.util  
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.util used by nl.justobjects.pushlet.client
    PushletException + +
    +          Generic exception wrapper.
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.util used by nl.justobjects.pushlet.core
    PushletException + +
    +          Generic exception wrapper.
    +  +

    + + + + + + + + +
    +Classes in nl.justobjects.pushlet.util used by nl.justobjects.pushlet.util
    PushletLogger + +
    +          Logger interface to allow different logging providers.
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-frame.html new file mode 100755 index 0000000000..70bcaf008e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-frame.html @@ -0,0 +1,46 @@ + + + + + + +Overview List + + + + + + + + + + + + + + + +
    +
    + + + + + +
    All Classes +

    + +Packages +
    +pow +
    +pow.ivyclient +
    +pow.webserver +
    +

    + +

    +  + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-summary.html new file mode 100755 index 0000000000..aa2f36c5fc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-summary.html @@ -0,0 +1,159 @@ + + + + + + +Overview + + + + + + + + + + + + +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + +
    +Packages
    pow 
    pow.ivyclient 
    pow.webserver 
    + +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-tree.html new file mode 100755 index 0000000000..96fd5faaeb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/overview-tree.html @@ -0,0 +1,187 @@ + + + + + + +Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For All Packages

    +
    +
    +
    Package Hierarchies:
    pow, pow.ivyclient, pow.webserver
    +
    +

    +Class Hierarchy +

    + +

    +Enum Hierarchy +

    +
      +
    • java.lang.Object
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/package-list b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/package-list new file mode 100755 index 0000000000..d58c57ef57 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/package-list @@ -0,0 +1,3 @@ +pow +pow.ivyclient +pow.webserver diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/AES.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/AES.html new file mode 100755 index 0000000000..563638a102 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/AES.html @@ -0,0 +1,424 @@ + + + + + + +AES + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow +
    +Class AES

    +
    +java.lang.Object
    +  extended by pow.AES
    +
    +
    +
    +
    public class AES
    extends java.lang.Object
    + + +

    +implements AES encryption and decryption algorithms + see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html + see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption +

    + +

    +


    + +

    + + + + + + + + + + + + + + + + + +
    +Constructor Summary
    AES() + +
    +          construct a cipher with a generated 128 bits key
    AES(byte[] key, + byte[] iv) + +
    +          construct a cipher from a key and a parameter array + usefull to create a remote decryption cypher
    AES(java.lang.String password) + +
    +          construct a cipher from an user specified key
    +  + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + byte[]decrypt(byte[] msg) + +
    +          decrypt a byte array with AES algorithm + see @link org.apache.commons.codec.binary.Hex to convert byte Array into hexString
    + byte[]encrypt(byte[] msg) + +
    +          encrypt a byte array with AES algorithm
    + byte[]getKey() + +
    +          get the cipher key
    + byte[]getParamsEncrypt() + +
    +          get the init parameter of the cipher object in order to initialyse correctly a + remote cipher
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +AES

    +
    +public AES()
    +    throws java.security.NoSuchAlgorithmException,
    +           javax.crypto.NoSuchPaddingException,
    +           java.security.InvalidKeyException,
    +           java.security.spec.InvalidParameterSpecException,
    +           java.security.InvalidAlgorithmParameterException
    +
    +
    construct a cipher with a generated 128 bits key +

    +

    + +
    Throws: +
    java.security.spec.InvalidParameterSpecException +
    java.security.InvalidAlgorithmParameterException +
    java.security.NoSuchAlgorithmException +
    javax.crypto.NoSuchPaddingException +
    java.security.InvalidKeyException
    +
    +
    + +

    +AES

    +
    +public AES(java.lang.String password)
    +    throws java.security.NoSuchAlgorithmException,
    +           javax.crypto.NoSuchPaddingException,
    +           java.security.InvalidKeyException,
    +           java.security.spec.InvalidParameterSpecException,
    +           java.security.InvalidAlgorithmParameterException,
    +           java.security.spec.InvalidKeySpecException
    +
    +
    construct a cipher from an user specified key +

    +

    +
    Parameters:
    password - a string representing the user key +
    Throws: +
    java.security.NoSuchAlgorithmException +
    javax.crypto.NoSuchPaddingException +
    java.security.InvalidKeyException +
    java.security.spec.InvalidParameterSpecException +
    java.security.InvalidAlgorithmParameterException +
    java.security.spec.InvalidKeySpecException
    +
    +
    + +

    +AES

    +
    +public AES(byte[] key,
    +           byte[] iv)
    +    throws java.security.InvalidKeyException,
    +           java.security.InvalidAlgorithmParameterException,
    +           java.security.NoSuchAlgorithmException,
    +           javax.crypto.NoSuchPaddingException
    +
    +
    construct a cipher from a key and a parameter array + usefull to create a remote decryption cypher +

    +

    +
    Parameters:
    key - the key in array byte format
    iv - parameter of the cipher +
    Throws: +
    java.security.InvalidKeyException +
    java.security.InvalidAlgorithmParameterException +
    java.security.NoSuchAlgorithmException +
    javax.crypto.NoSuchPaddingException
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getParamsEncrypt

    +
    +public byte[] getParamsEncrypt()
    +                        throws java.security.spec.InvalidParameterSpecException
    +
    +
    get the init parameter of the cipher object in order to initialyse correctly a + remote cipher +

    +

    + +
    Throws: +
    java.security.spec.InvalidParameterSpecException
    +
    +
    +
    + +

    +getKey

    +
    +public byte[] getKey()
    +
    +
    get the cipher key +

    +

    + +
    Returns:
    the cipher key in byte array
    +
    +
    +
    + +

    +encrypt

    +
    +public byte[] encrypt(byte[] msg)
    +               throws java.io.IOException,
    +                      javax.crypto.IllegalBlockSizeException,
    +                      javax.crypto.BadPaddingException
    +
    +
    encrypt a byte array with AES algorithm +

    +

    +
    Parameters:
    msg - +
    Returns:
    a byte array containing the ciphered data +
    Throws: +
    java.io.IOException +
    javax.crypto.BadPaddingException +
    javax.crypto.IllegalBlockSizeException
    See Also:
    to convert byte Array into hexString
    +
    +
    +
    + +

    +decrypt

    +
    +public byte[] decrypt(byte[] msg)
    +               throws java.io.IOException,
    +                      javax.crypto.IllegalBlockSizeException,
    +                      javax.crypto.BadPaddingException
    +
    +
    decrypt a byte array with AES algorithm + see @link org.apache.commons.codec.binary.Hex to convert byte Array into hexString +

    +

    +
    Parameters:
    msg - the msg to decrypt +
    Returns:
    the message decrypted +
    Throws: +
    java.io.IOException +
    javax.crypto.BadPaddingException +
    javax.crypto.IllegalBlockSizeException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/InstallCert.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/InstallCert.html new file mode 100755 index 0000000000..74e5602fa1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/InstallCert.html @@ -0,0 +1,261 @@ + + + + + + +InstallCert + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow +
    +Class InstallCert

    +
    +java.lang.Object
    +  extended by pow.InstallCert
    +
    +
    +
    +
    public class InstallCert
    extends java.lang.Object
    + + +

    +query the server about its certificate and create a 'jssecacerts' file to copy + into /usr/lib/jvm/java-x-x/jre/lib/security + allow a java http client to connect to https server +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    InstallCert() + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    +static voidmain(java.lang.String[] args) + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +InstallCert

    +
    +public InstallCert()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +main

    +
    +public static void main(java.lang.String[] args)
    +                 throws java.lang.Exception
    +
    +
    + +
    Throws: +
    java.lang.Exception
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/AES.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/AES.html new file mode 100755 index 0000000000..2b2c095905 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/AES.html @@ -0,0 +1,230 @@ + + + + + + +Uses of Class pow.AES + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.AES

    +
    + + + + + + + + + + + + + +
    +Packages that use AES
    pow.ivyclient  
    pow.webserver  
    +  +

    + + + + + +
    +Uses of AES in pow.ivyclient
    +  +

    + + + + + + + + +
    Constructors in pow.ivyclient with parameters of type AES
    HeartBeat(AES cipher, + int webId, + java.net.InetAddress srv, + int port2send, + long heartbeatPeriod) + +
    +          define the parameter of the heartbeat message
    +  +

    + + + + + +
    +Uses of AES in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that return AES
    + AESSessionIvy.getCipher() + +
    +           
    +  +

    + + + + + + + + +
    Constructors in pow.webserver with parameters of type AES
    SessionIvy(java.lang.String l, + int w, + AES c, + java.net.InetAddress IvyAddr) + +
    +          create a session which store information about an ivy bus client connected to the server + main information are its net address to send him orders from web users + and drones which are connected to this ivy bus
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/InstallCert.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/InstallCert.html new file mode 100755 index 0000000000..ee11ff6788 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/class-use/InstallCert.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.InstallCert + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.InstallCert

    +
    +No usage of pow.InstallCert +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetId.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetId.html new file mode 100755 index 0000000000..a65ac71f3a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetId.html @@ -0,0 +1,451 @@ + + + + + + +AcNetId + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class AcNetId

    +
    +java.lang.Object
    +  extended by pow.ivyclient.AcNetId
    +
    +
    +
    +
    public class AcNetId
    extends java.lang.Object
    + + +

    +this object represents the data concerning a drone extracted from Ivy + A drone has two identities. One on its ivy drone which can be the same as + another drone on a different ivy bus. The second identifier is the I.D. of the drone + on the web. This I.D. is unique. So a link has to be done between these two kind of id. +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + + + + +
    +Constructor Summary
    AcNetId(int idBusIvy, + java.lang.String idIvy, + java.lang.String n, + java.lang.String pln, + java.lang.String s, + java.lang.String c, + int maxACOnIvy) + +
    +           
    AcNetId(int idBusIvy, + java.lang.String droneWebId, + java.lang.String idIvy, + java.lang.String n, + java.lang.String pln, + java.lang.String s, + java.lang.String c, + int maxACOnIvy) + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringgetColor() + +
    +          provides the color of the drone on the GCS view
    + java.lang.StringgetIdOnIvy() + +
    +          provides the id of the drone on the ivy bus
    + java.lang.StringgetIdOnWeb() + +
    +          provides the id of the drone on the web
    + java.lang.StringgetName() + +
    +          provides the name of the drone on the ivy bus
    + java.lang.StringgetPlnPath() + +
    +          provides the path of the xml file (on the server) containing + the information of the flightplan of the drone + (waypoints and blocks of instructions)
    + java.lang.StringgetSettingPath() + +
    +          provides the path of the xml file (on the server) containing the settings + of the drone
    + java.lang.StringtoString() + +
    +          return information about the drone in a string format
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +AcNetId

    +
    +public AcNetId(int idBusIvy,
    +               java.lang.String idIvy,
    +               java.lang.String n,
    +               java.lang.String pln,
    +               java.lang.String s,
    +               java.lang.String c,
    +               int maxACOnIvy)
    +
    +
    +
    Parameters:
    idBusIvy - the id of the ivy bus
    idIvy - the identifier of the drone on ivy
    n - the name of the ivy drone (MJ5,TJ1...)
    pln - the full pathname of the configuration file FlightPlan.xml
    s - the full pathname of the configuration file Settings.xml
    c - the color of the drone on ivy (in hexa '#FF00FF' or with its common name 'red')
    maxACOnIvy - the maximal number of aircrafts on ivy bus (is no important anymore)
    +
    +
    + +

    +AcNetId

    +
    +public AcNetId(int idBusIvy,
    +               java.lang.String droneWebId,
    +               java.lang.String idIvy,
    +               java.lang.String n,
    +               java.lang.String pln,
    +               java.lang.String s,
    +               java.lang.String c,
    +               int maxACOnIvy)
    +
    +
    +
    Parameters:
    idBusIvy - the id of the ivy bus
    droneWebId - the identifier of the drone on the web
    idIvy - the identifier of the drone on ivy
    n - the name of the ivy drone (MJ5,TJ1...)
    pln - the full pathname of the configuration file FlightPlan.xml
    s - the full pathname of the configuration file Settings.xml
    c - the color of the drone on ivy (in hexa '#FF00FF' or with its common name 'red')
    maxACOnIvy - the maximal number of aircrafts on ivy bus (is no important anymore)
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getIdOnIvy

    +
    +public java.lang.String getIdOnIvy()
    +
    +
    provides the id of the drone on the ivy bus +

    +

    + +
    Returns:
    the id number of the drone on its ivy bus
    +
    +
    +
    + +

    +getName

    +
    +public java.lang.String getName()
    +
    +
    provides the name of the drone on the ivy bus +

    +

    + +
    Returns:
    the name of the drone on its ivy bus
    +
    +
    +
    + +

    +getIdOnWeb

    +
    +public java.lang.String getIdOnWeb()
    +
    +
    provides the id of the drone on the web +

    +

    + +
    Returns:
    the single id number of the drone on the web server
    +
    +
    +
    + +

    +getPlnPath

    +
    +public java.lang.String getPlnPath()
    +
    +
    provides the path of the xml file (on the server) containing + the information of the flightplan of the drone + (waypoints and blocks of instructions) +

    +

    + +
    Returns:
    the full path of the flight plan config file on the GCS station
    +
    +
    +
    + +

    +getSettingPath

    +
    +public java.lang.String getSettingPath()
    +
    +
    provides the path of the xml file (on the server) containing the settings + of the drone +

    +

    + +
    Returns:
    the full path of the settings file on the GCS station
    +
    +
    +
    + +

    +getColor

    +
    +public java.lang.String getColor()
    +
    +
    provides the color of the drone on the GCS view +

    +

    + +
    Returns:
    the color of the drone on the GCS station (either in string or in hexadecimal)
    +
    +
    +
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    return information about the drone in a string format +

    +

    +
    Overrides:
    toString in class java.lang.Object
    +
    +
    + +
    Returns:
    a string containing information about the drone
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetIdStorage.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetIdStorage.html new file mode 100755 index 0000000000..fc331284da --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcNetIdStorage.html @@ -0,0 +1,379 @@ + + + + + + +AcNetIdStorage + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class AcNetIdStorage

    +
    +java.lang.Object
    +  extended by pow.ivyclient.AcNetIdStorage
    +
    +
    +
    +
    public class AcNetIdStorage
    extends java.lang.Object
    + + +

    +this structure memorize all the drone which exist on the ivy bus. + A drone has two identities. One on its ivy drone which can be the same as + another drone on a different ivy bus. The second identifier is the I.D. of the drone + on the web. This I.D. is unique. So a link has to be done between these two kind of id. +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    AcNetIdStorage(int ii, + fr.dgac.ivy.Ivy b, + java.lang.String u, + int maxAC, + java.util.concurrent.ConcurrentHashMap<java.lang.String,AcStatus> states) + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringgetAcIvyId(int idOnWeb) + +
    +          do the link between the id of the drone on the web and is true id on its ivy bus
    + AcNetIdgetAcNetId(java.lang.String idOnIvy) + +
    +          Return the identity object of the drone on the web
    + java.lang.StringgetNewDroneWebId(java.lang.String IvyDroneId) + +
    +          ask a unique new web id to the server for a new drone detected on the ivy bus
    + voidseekAcNetId(java.lang.String s) + +
    +          search the drone net id of a drone from its ivy id + if the drone is a new one, a new net id is requested to the server
    + booleanuploadConfFile(AcNetId ac) + +
    +          upload de fichier de conf sur le serveur + verifier que ca marche sur long fichier + si probleme changer avec : + factory.setSizeThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + upload.setSizeMax(yourMaxRequestSize);
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +AcNetIdStorage

    +
    +public AcNetIdStorage(int ii,
    +                      fr.dgac.ivy.Ivy b,
    +                      java.lang.String u,
    +                      int maxAC,
    +                      java.util.concurrent.ConcurrentHashMap<java.lang.String,AcStatus> states)
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getAcNetId

    +
    +public AcNetId getAcNetId(java.lang.String idOnIvy)
    +
    +
    Return the identity object of the drone on the web +

    +

    +
    Parameters:
    idOnIvy - +
    Returns:
    the identity of the drone on the web or null if it is not present
    +
    +
    +
    + +

    +getAcIvyId

    +
    +public java.lang.String getAcIvyId(int idOnWeb)
    +
    +
    do the link between the id of the drone on the web and is true id on its ivy bus +

    +

    +
    Parameters:
    idOnWeb - the id of the drone on the web +
    Returns:
    the id of the drone on the ivy bus
    +
    +
    +
    + +

    +seekAcNetId

    +
    +public void seekAcNetId(java.lang.String s)
    +
    +
    search the drone net id of a drone from its ivy id + if the drone is a new one, a new net id is requested to the server +

    +

    +
    Parameters:
    s - the ivy id of the drone
    +
    +
    +
    + +

    +uploadConfFile

    +
    +public boolean uploadConfFile(AcNetId ac)
    +                       throws java.io.FileNotFoundException
    +
    +
    upload de fichier de conf sur le serveur + verifier que ca marche sur long fichier + si probleme changer avec : + factory.setSizeThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + upload.setSizeMax(yourMaxRequestSize); +

    +

    +
    Parameters:
    ac - the information object about the drone +
    Throws: +
    java.lang.InterruptedException +
    java.io.FileNotFoundException
    +
    +
    +
    + +

    +getNewDroneWebId

    +
    +public java.lang.String getNewDroneWebId(java.lang.String IvyDroneId)
    +                                  throws IvyConnectionExeption
    +
    +
    ask a unique new web id to the server for a new drone detected on the ivy bus +

    +

    +
    Parameters:
    IvyDroneId - the drone id on ivy +
    Returns:
    the new web drone id +
    Throws: +
    IvyConnectionExeption
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcStatus.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcStatus.html new file mode 100755 index 0000000000..19ecd9b9bb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/AcStatus.html @@ -0,0 +1,464 @@ + + + + + + +AcStatus + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Enum AcStatus

    +
    +java.lang.Object
    +  extended by java.lang.Enum<AcStatus>
    +      extended by pow.ivyclient.AcStatus
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Comparable<AcStatus>
    +
    +
    +
    +
    public enum AcStatus
    extends java.lang.Enum<AcStatus>
    + + +

    +implements the life cycle of a drone when it is detected on the ivy bus. + these steps are needed to prevent that a ivy message is processed before + that all information about the drone were retrieved + these status follow the steps that are followed by the module when a new drone + is detected on the bus +

    + +

    +

    +
    Author:
    +
    genin
    +
    See Also:
    Ivy2Udp
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Enum Constant Summary
    ALIVE + +
    +          the module can received ivy message for this drone and send them to the server
    ASKING_IVY_CONF + +
    +          a request about the configuration has been sent on ivy
    ASKING_WEB_ID + +
    +          the module sends request to the web server for having a web id for the drone
    CONF_NOTOK + +
    +          a problem occurred during the process
    CONF_OK + +
    +          the 2 configuration files have been uploaded successfully
    IVY_CONF_RECEIVED + +
    +          the configuration has been received from ivy
    UNKNOWN + +
    +          the system does not know this drone, information are requested
    UPLOADING_CONF + +
    +          the module upload the two configuration files of the drone on the server
    WEB_ID_RECEIVED + +
    +          the drone web id has been received from the server
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static AcStatusvalueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static AcStatus[]values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    + + + + + + + +
    Methods inherited from class java.lang.Enum
    compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
    + + + + + + + +
    Methods inherited from class java.lang.Object
    getClass, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Enum Constant Detail
    + +

    +UNKNOWN

    +
    +public static final AcStatus UNKNOWN
    +
    +
    the system does not know this drone, information are requested +

    +

    +
    +
    +
    + +

    +ASKING_IVY_CONF

    +
    +public static final AcStatus ASKING_IVY_CONF
    +
    +
    a request about the configuration has been sent on ivy +

    +

    +
    +
    +
    + +

    +IVY_CONF_RECEIVED

    +
    +public static final AcStatus IVY_CONF_RECEIVED
    +
    +
    the configuration has been received from ivy +

    +

    +
    +
    +
    + +

    +ASKING_WEB_ID

    +
    +public static final AcStatus ASKING_WEB_ID
    +
    +
    the module sends request to the web server for having a web id for the drone +

    +

    +
    +
    +
    + +

    +WEB_ID_RECEIVED

    +
    +public static final AcStatus WEB_ID_RECEIVED
    +
    +
    the drone web id has been received from the server +

    +

    +
    +
    +
    + +

    +UPLOADING_CONF

    +
    +public static final AcStatus UPLOADING_CONF
    +
    +
    the module upload the two configuration files of the drone on the server +

    +

    +
    +
    +
    + +

    +CONF_OK

    +
    +public static final AcStatus CONF_OK
    +
    +
    the 2 configuration files have been uploaded successfully +

    +

    +
    +
    +
    + +

    +ALIVE

    +
    +public static final AcStatus ALIVE
    +
    +
    the module can received ivy message for this drone and send them to the server +

    +

    +
    +
    +
    + +

    +CONF_NOTOK

    +
    +public static final AcStatus CONF_NOTOK
    +
    +
    a problem occurred during the process +

    +

    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +values

    +
    +public static AcStatus[] values()
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
    +for (AcStatus c : AcStatus.values())
    +    System.out.println(c);
    +
    +

    +

    + +
    Returns:
    an array containing the constants of this enum type, in +the order they are declared
    +
    +
    +
    + +

    +valueOf

    +
    +public static AcStatus valueOf(java.lang.String name)
    +
    +
    Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.) +

    +

    +
    Parameters:
    name - the name of the enum constant to be returned. +
    Returns:
    the enum constant with the specified name +
    Throws: +
    java.lang.IllegalArgumentException - if this enum type has no constant +with the specified name +
    java.lang.NullPointerException - if the argument is null
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/BusIvy_.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/BusIvy_.html new file mode 100755 index 0000000000..32962eb614 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/BusIvy_.html @@ -0,0 +1,411 @@ + + + + + + +BusIvy_ + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class BusIvy_

    +
    +java.lang.Object
    +  extended by pow.ivyclient.BusIvy_
    +
    +
    +
    +
    public class BusIvy_
    extends java.lang.Object
    + + +

    +inner representation of an ivy bus + store the drones' information about the drones which belong to this ivy bus + store the IP adress of the machine where the ivy bus is working +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    BusIvy_() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidaddDrones(int newDroneId) + +
    +          inform the bus that a new drone send information on this bus
    + voiddisplayDrones() + +
    +          display information on stdout about the drones present on the bus
    + java.net.InetAddressgetAddress() + +
    +          provides the IP adress of the host hosting the bus
    + java.util.ArrayList<java.lang.Integer>getDrones() + +
    +          get a array list containing the ivy id of the drones present on the bus
    + booleanisAlive() + +
    +          inform if the bus is alive
    + booleanisOwnBy(int myDroneId) + +
    +          inform if a drone is present or not on the bus
    + voidsetAddress(java.net.InetAddress myInetAddress) + +
    +           
    + voidupdateTime() + +
    +          update the 'inner clock' of the object when a message for this bus is detected + useful to know if the bus is still alive
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +BusIvy_

    +
    +public BusIvy_()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +setAddress

    +
    +public void setAddress(java.net.InetAddress myInetAddress)
    +
    +
    +
    Parameters:
    myInetAddress - the ip address of the ivy host
    +
    +
    +
    + +

    +updateTime

    +
    +public void updateTime()
    +
    +
    update the 'inner clock' of the object when a message for this bus is detected + useful to know if the bus is still alive +

    +

    +
    +
    +
    +
    + +

    +addDrones

    +
    +public void addDrones(int newDroneId)
    +
    +
    inform the bus that a new drone send information on this bus +

    +

    +
    Parameters:
    newDroneId - (the ivy id)
    +
    +
    +
    + +

    +getDrones

    +
    +public java.util.ArrayList<java.lang.Integer> getDrones()
    +
    +
    get a array list containing the ivy id of the drones present on the bus +

    +

    + +
    Returns:
    the array list containing the ivy id of the drones present on the bus
    +
    +
    +
    + +

    +displayDrones

    +
    +public void displayDrones()
    +
    +
    display information on stdout about the drones present on the bus +

    +

    +
    +
    +
    +
    + +

    +getAddress

    +
    +public java.net.InetAddress getAddress()
    +
    +
    provides the IP adress of the host hosting the bus +

    +

    + +
    Returns:
    the IP adress of the host hosting the bus
    +
    +
    +
    + +

    +isOwnBy

    +
    +public boolean isOwnBy(int myDroneId)
    +
    +
    inform if a drone is present or not on the bus +

    +

    +
    Parameters:
    myDroneId - the ivy id +
    Returns:
    true if the drone is present on the bus
    +
    +
    +
    + +

    +isAlive

    +
    +public boolean isAlive()
    +
    +
    inform if the bus is alive +

    +

    + +
    Returns:
    true if the last message was received less than 10 seconds ago
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/HeartBeat.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/HeartBeat.html new file mode 100755 index 0000000000..8cfab6db5e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/HeartBeat.html @@ -0,0 +1,305 @@ + + + + + + +HeartBeat + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class HeartBeat

    +
    +java.lang.Object
    +  extended by pow.ivyclient.HeartBeat
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable
    +
    +
    +
    +
    public class HeartBeat
    extends java.lang.Object
    implements java.lang.Runnable
    + + +

    +thread which send a periodic message to a client or server to say that the connection + is still alive (period has to be less than the socket timeout of the the server) +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    HeartBeat(AES cipher, + int webId, + java.net.InetAddress srv, + int port2send, + long heartbeatPeriod) + +
    +          define the parameter of the heartbeat message
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    + voidrun() + +
    +          send a periodic heartbeat message
    + voidstop_thread() + +
    +          stop the heartbeat thread by ending the infinite loop
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +HeartBeat

    +
    +public HeartBeat(AES cipher,
    +                 int webId,
    +                 java.net.InetAddress srv,
    +                 int port2send,
    +                 long heartbeatPeriod)
    +
    +
    define the parameter of the heartbeat message +

    +

    +
    Parameters:
    cipher - the way to encrypt message to be send on udp channel
    webId - the id of the bus
    srv - the ip address of the host hosting the ivy bus
    port2send - the udp port on which the heartbeat is sent
    heartbeatPeriod - the period of time to send heartbeat message
    +
    + + + + + + + + +
    +Method Detail
    + +

    +run

    +
    +public void run()
    +
    +
    send a periodic heartbeat message +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    +
    + +

    +stop_thread

    +
    +public void stop_thread()
    +
    +
    stop the heartbeat thread by ending the infinite loop +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2Udp.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2Udp.html new file mode 100755 index 0000000000..29f859c97c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2Udp.html @@ -0,0 +1,554 @@ + + + + + + +Ivy2Udp + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class Ivy2Udp

    +
    +java.lang.Object
    +  extended by pow.ivyclient.Ivy2Udp
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable
    +
    +
    +
    +
    public class Ivy2Udp
    extends java.lang.Object
    implements java.lang.Runnable
    + + +

    +It contact the server to get an identifier, some configuration parameter and + the key to encrypt and decrypt messages. + Then it listens messages on the ivy bus and send messages on active drones to the + web server. +

    + +

    +

    +
    Version:
    +
    2.0
    +
    Author:
    +
    jabln, thomas genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Ivy2Udp(IvyIHM ihm, + PowUrl urlObj, + java.lang.String login, + java.lang.String password) + +
    +          create an object which listens on the local ivy bus and send messages to the server
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidbindMsg2Ivy() + +
    +          This method binds the object to some messages + of the bus Ivy.
    + intgetIvyWebId() + +
    +          return the id of the bus for the server + this id is provided by the server and is unique
    + AcNetIdStoragegetStorage() + +
    +          provides the structure where data about the drone present on the ivy bus are stored
    + voidgetWebId() + +
    +          request a single id for the bus to the web server + method get + see @link http://hc.apache.org/httpclient-3.x/tutorial.html + see @link blogs.sun.com/gc/entry/unable_to_find_valid_certification + see @link http://blogs.sun.com/andreas/entry/no_more_unable_to_find
    + voidrun() + +
    +          listen the udp socket to get orders from web clients and send them to ivy
    + voidsend(int acId) + +
    +          This method send to the web server the datagram containing the informations + about the aircraft
    + voidsend(int acId, + java.lang.String s) + +
    +          This method send a particular message about an aircraft
    + voidsend(int acId, + java.lang.String s, + java.lang.String[] as) + +
    +          This method send to the web server a specific order with parameters
    + voidsetStorage() + +
    +          initiate the object which allow to store information about drones
    + voidstartHeartBeat() + +
    +          create a thread which send heart beat message to the server
    + voidstop_thread() + +
    +          stop all the thread Ivy2Udp , HeartBeat and ivy2UdpWriting
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Ivy2Udp

    +
    +public Ivy2Udp(IvyIHM ihm,
    +               PowUrl urlObj,
    +               java.lang.String login,
    +               java.lang.String password)
    +
    +
    create an object which listens on the local ivy bus and send messages to the server +

    +

    +
    Parameters:
    urlObj - describes information about the server
    login -
    password -
    +
    + + + + + + + + +
    +Method Detail
    + +

    +setStorage

    +
    +public void setStorage()
    +
    +
    initiate the object which allow to store information about drones +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getStorage

    +
    +public AcNetIdStorage getStorage()
    +
    +
    provides the structure where data about the drone present on the ivy bus are stored +

    +

    +
    +
    +
    + +
    Returns:
    the structure which allow to store information about drones
    +
    +
    +
    + +

    +getIvyWebId

    +
    +public int getIvyWebId()
    +
    +
    return the id of the bus for the server + this id is provided by the server and is unique +

    +

    +
    +
    +
    + +
    Returns:
    the unique id of this ivy bus for the server
    +
    +
    +
    + +

    +getWebId

    +
    +public void getWebId()
    +              throws IvyConnectionExeption
    +
    +
    request a single id for the bus to the web server + method get + see @link http://hc.apache.org/httpclient-3.x/tutorial.html + see @link blogs.sun.com/gc/entry/unable_to_find_valid_certification + see @link http://blogs.sun.com/andreas/entry/no_more_unable_to_find +

    +

    +
    +
    +
    + +
    Throws: +
    IvyConnectionExeption
    +
    +
    +
    + +

    +startHeartBeat

    +
    +public void startHeartBeat()
    +
    +
    create a thread which send heart beat message to the server +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +bindMsg2Ivy

    +
    +public void bindMsg2Ivy()
    +                 throws fr.dgac.ivy.IvyException
    +
    +
    This method binds the object to some messages + of the bus Ivy. Each information that is needed by the web server is put in an + array. This array is sent to server. +

    +

    +
    +
    +
    + +
    Throws: +
    fr.dgac.ivy.IvyException
    +
    +
    +
    + +

    +stop_thread

    +
    +public void stop_thread()
    +
    +
    stop all the thread Ivy2Udp , HeartBeat and ivy2UdpWriting +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +send

    +
    +public void send(int acId)
    +
    +
    This method send to the web server the datagram containing the informations + about the aircraft +

    +

    +
    +
    +
    +
    Parameters:
    acId - Line of the matrix containing the informations about the plane +
    Throws: +
    java.lang.Exception
    +
    +
    +
    + +

    +send

    +
    +public void send(int acId,
    +                 java.lang.String s,
    +                 java.lang.String[] as)
    +
    +
    This method send to the web server a specific order with parameters +

    +

    +
    +
    +
    +
    Parameters:
    acId - : Line of the matrix containing the informations about the plane
    s - : order
    as - : parameters
    +
    +
    +
    + +

    +send

    +
    +public void send(int acId,
    +                 java.lang.String s)
    +
    +
    This method send a particular message about an aircraft +

    +

    +
    +
    +
    +
    Parameters:
    acId - line of the matrix containing the informations about the plane
    s - message that is to be sent to send
    +
    +
    +
    + +

    +run

    +
    +public void run()
    +
    +
    listen the udp socket to get orders from web clients and send them to ivy +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2UdpWriting.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2UdpWriting.html new file mode 100755 index 0000000000..66eec584d3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/Ivy2UdpWriting.html @@ -0,0 +1,239 @@ + + + + + + +Ivy2UdpWriting + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class Ivy2UdpWriting

    +
    +java.lang.Object
    +  extended by pow.ivyclient.Ivy2UdpWriting
    +
    +
    +
    All Implemented Interfaces:
    fr.dgac.ivy.IvyMessageListener, java.util.EventListener
    +
    +
    +
    +
    public class Ivy2UdpWriting
    extends java.lang.Object
    implements fr.dgac.ivy.IvyMessageListener
    + + +

    +This class aims to give order to the drones according to the datagrams it + receive from the web +

    + +

    +

    +
    Author:
    +
    jabln
    +
    +
    + +

    + + + + + + + + + + + + +
    +Method Summary
    + voidreceive(fr.dgac.ivy.IvyClient client, + java.lang.String[] args) + +
    +          This method implements the method receive of the bus Ivy class.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Method Detail
    + +

    +receive

    +
    +public void receive(fr.dgac.ivy.IvyClient client,
    +                    java.lang.String[] args)
    +
    +
    This method implements the method receive of the bus Ivy class. + It sends the informations on the ivy bus and stop the binding +

    +

    +
    Specified by:
    receive in interface fr.dgac.ivy.IvyMessageListener
    +
    +
    +
    Parameters:
    client -
    args -
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyConnectionExeption.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyConnectionExeption.html new file mode 100755 index 0000000000..bc138ea490 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyConnectionExeption.html @@ -0,0 +1,277 @@ + + + + + + +IvyConnectionExeption + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class IvyConnectionExeption

    +
    +java.lang.Object
    +  extended by java.lang.Throwable
    +      extended by java.lang.Exception
    +          extended by pow.ivyclient.IvyConnectionExeption
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable
    +
    +
    +
    +
    public class IvyConnectionExeption
    extends java.lang.Exception
    + + +

    +

    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    IvyConnectionExeption(java.lang.String res) + +
    +          create an ivy exception with a particular message
    +  + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringtoString() + +
    +          display the exception on stdout
    + + + + + + + +
    Methods inherited from class java.lang.Throwable
    fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +IvyConnectionExeption

    +
    +public IvyConnectionExeption(java.lang.String res)
    +
    +
    create an ivy exception with a particular message +

    +

    +
    Parameters:
    res - the message
    +
    + + + + + + + + +
    +Method Detail
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    display the exception on stdout +

    +

    +
    Overrides:
    toString in class java.lang.Throwable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyIHM.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyIHM.html new file mode 100755 index 0000000000..61cd9c687b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/IvyIHM.html @@ -0,0 +1,319 @@ + + + + + + +IvyIHM + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class IvyIHM

    +
    +java.lang.Object
    +  extended by pow.ivyclient.IvyIHM
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable
    +
    +
    +
    +
    public class IvyIHM
    extends java.lang.Object
    implements java.lang.Runnable
    + + +

    +represent the interface for a ivy user who wants to connect a bus ivy to + the web server +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    IvyIHM() + +
    +          construct the interface
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    +static voidmain(java.lang.String[] args) + +
    +          launch the interface to connect the ivy bus to POW server
    + voidrun() + +
    +          loop to perform a periodic check for automatic reconnection
    + voidsetReLogged(boolean l) + +
    +          specify whether the module should reconnected or not
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +IvyIHM

    +
    +public IvyIHM()
    +
    +
    construct the interface +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +setReLogged

    +
    +public void setReLogged(boolean l)
    +
    +
    specify whether the module should reconnected or not +

    +

    +
    +
    +
    +
    Parameters:
    l - true or false
    +
    +
    +
    + +

    +run

    +
    +public void run()
    +
    +
    loop to perform a periodic check for automatic reconnection +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    +
    + +

    +main

    +
    +public static void main(java.lang.String[] args)
    +
    +
    launch the interface to connect the ivy bus to POW server +

    +

    +
    +
    +
    +
    Parameters:
    args -
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/MsgFilter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/MsgFilter.html new file mode 100755 index 0000000000..d6d98c7f36 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/MsgFilter.html @@ -0,0 +1,288 @@ + + + + + + +MsgFilter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class MsgFilter

    +
    +java.lang.Object
    +  extended by pow.ivyclient.MsgFilter
    +
    +
    +
    +
    public class MsgFilter
    extends java.lang.Object
    + + +

    +this class filters the message, thanks to their hash code + it is used because Paparazzi send periodic messages that are often the same + so we filter them to lighten the server load and the bandwidth of the udp channel +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    MsgFilter() + +
    +          create a message filter
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    + booleanisNew(java.lang.String msg) + +
    +          inform whether the message is new or not
    + voidresetfilter() + +
    +          empty the filter
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +MsgFilter

    +
    +public MsgFilter()
    +
    +
    create a message filter +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +isNew

    +
    +public boolean isNew(java.lang.String msg)
    +
    +
    inform whether the message is new or not +

    +

    +
    Parameters:
    msg - +
    Returns:
    true if the message is a new one and was added to the filter
    +
    +
    +
    + +

    +resetfilter

    +
    +public void resetfilter()
    +
    +
    empty the filter +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/PowUrl.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/PowUrl.html new file mode 100755 index 0000000000..0898ad21dd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/PowUrl.html @@ -0,0 +1,301 @@ + + + + + + +PowUrl + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.ivyclient +
    +Class PowUrl

    +
    +java.lang.Object
    +  extended by pow.ivyclient.PowUrl
    +
    +
    +
    +
    public class PowUrl
    extends java.lang.Object
    + + +

    +object which store all information about the url to log on the server +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    PowUrl(java.lang.String protocol, + java.lang.String server, + int port, + java.lang.String webapp, + java.lang.String servletName) + +
    +          create all the information requested to connect the ivy module to the server + when all parameters are correct can give an url like + https://paparazzi.fr/ServletPow/Login.srv
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringgetServerName() + +
    +          provides the server name to which the module is connected
    + java.lang.StringgetWebUrl() + +
    +          provides the complete URL to log on the POW server
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +PowUrl

    +
    +public PowUrl(java.lang.String protocol,
    +              java.lang.String server,
    +              int port,
    +              java.lang.String webapp,
    +              java.lang.String servletName)
    +
    +
    create all the information requested to connect the ivy module to the server + when all parameters are correct can give an url like + https://paparazzi.fr/ServletPow/Login.srv +

    +

    +
    Parameters:
    protocol - the protocol used to log to the server (HTTP by default)
    server - the server name (paparazzi.fr) for example
    port - a specific protocol port ( -1 means that this parameter is not used )
    webapp - the name of the application on the server (ServletPow for example)
    servletName - the name of the login servlet (Login.srv)
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getServerName

    +
    +public java.lang.String getServerName()
    +
    +
    provides the server name to which the module is connected +

    +

    + +
    Returns:
    server hostname
    +
    +
    +
    + +

    +getWebUrl

    +
    +public java.lang.String getWebUrl()
    +
    +
    provides the complete URL to log on the POW server +

    +

    + +
    Returns:
    the complete url to log in as a string
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetId.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetId.html new file mode 100755 index 0000000000..ca566cd3e4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetId.html @@ -0,0 +1,201 @@ + + + + + + +Uses of Class pow.ivyclient.AcNetId + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.AcNetId

    +
    + + + + + + + + + +
    +Packages that use AcNetId
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of AcNetId in pow.ivyclient
    +  +

    + + + + + + + + + +
    Methods in pow.ivyclient that return AcNetId
    + AcNetIdAcNetIdStorage.getAcNetId(java.lang.String idOnIvy) + +
    +          Return the identity object of the drone on the web
    +  +

    + + + + + + + + + +
    Methods in pow.ivyclient with parameters of type AcNetId
    + booleanAcNetIdStorage.uploadConfFile(AcNetId ac) + +
    +          upload de fichier de conf sur le serveur + verifier que ca marche sur long fichier + si probleme changer avec : + factory.setSizeThreshold(yourMaxMemorySize); + factory.setRepository(yourTempDirectory); + upload.setSizeMax(yourMaxRequestSize);
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetIdStorage.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetIdStorage.html new file mode 100755 index 0000000000..ff41618633 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcNetIdStorage.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class pow.ivyclient.AcNetIdStorage + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.AcNetIdStorage

    +
    + + + + + + + + + +
    +Packages that use AcNetIdStorage
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of AcNetIdStorage in pow.ivyclient
    +  +

    + + + + + + + + + +
    Methods in pow.ivyclient that return AcNetIdStorage
    + AcNetIdStorageIvy2Udp.getStorage() + +
    +          provides the structure where data about the drone present on the ivy bus are stored
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcStatus.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcStatus.html new file mode 100755 index 0000000000..19b8f1b54d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/AcStatus.html @@ -0,0 +1,207 @@ + + + + + + +Uses of Class pow.ivyclient.AcStatus + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.AcStatus

    +
    + + + + + + + + + +
    +Packages that use AcStatus
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of AcStatus in pow.ivyclient
    +  +

    + + + + + + + + + + + + + +
    Methods in pow.ivyclient that return AcStatus
    +static AcStatusAcStatus.valueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static AcStatus[]AcStatus.values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    +  +

    + + + + + + + + +
    Constructor parameters in pow.ivyclient with type arguments of type AcStatus
    AcNetIdStorage(int ii, + fr.dgac.ivy.Ivy b, + java.lang.String u, + int maxAC, + java.util.concurrent.ConcurrentHashMap<java.lang.String,AcStatus> states) + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/BusIvy_.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/BusIvy_.html new file mode 100755 index 0000000000..ac331b7e7c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/BusIvy_.html @@ -0,0 +1,196 @@ + + + + + + +Uses of Class pow.ivyclient.BusIvy_ + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.BusIvy_

    +
    + + + + + + + + + +
    +Packages that use BusIvy_
    pow.webserver  
    +  +

    + + + + + +
    +Uses of BusIvy_ in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that return BusIvy_
    + BusIvy_SessionIvy.getBusIvy() + +
    +           
    +  +

    + + + + + + + + + +
    Methods in pow.webserver with parameters of type BusIvy_
    + voidSessionIvy.setBusIvy(BusIvy_ b) + +
    +          store the information of the ivy bus into the ivy session
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/HeartBeat.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/HeartBeat.html new file mode 100755 index 0000000000..83fbc120e6 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/HeartBeat.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.ivyclient.HeartBeat + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.HeartBeat

    +
    +No usage of pow.ivyclient.HeartBeat +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2Udp.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2Udp.html new file mode 100755 index 0000000000..e84e016dce --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2Udp.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.ivyclient.Ivy2Udp + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.Ivy2Udp

    +
    +No usage of pow.ivyclient.Ivy2Udp +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2UdpWriting.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2UdpWriting.html new file mode 100755 index 0000000000..df8569e28f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/Ivy2UdpWriting.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.ivyclient.Ivy2UdpWriting + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.Ivy2UdpWriting

    +
    +No usage of pow.ivyclient.Ivy2UdpWriting +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyConnectionExeption.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyConnectionExeption.html new file mode 100755 index 0000000000..36374cd779 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyConnectionExeption.html @@ -0,0 +1,192 @@ + + + + + + +Uses of Class pow.ivyclient.IvyConnectionExeption + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.IvyConnectionExeption

    +
    + + + + + + + + + +
    +Packages that use IvyConnectionExeption
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of IvyConnectionExeption in pow.ivyclient
    +  +

    + + + + + + + + + + + + + +
    Methods in pow.ivyclient that throw IvyConnectionExeption
    + java.lang.StringAcNetIdStorage.getNewDroneWebId(java.lang.String IvyDroneId) + +
    +          ask a unique new web id to the server for a new drone detected on the ivy bus
    + voidIvy2Udp.getWebId() + +
    +          request a single id for the bus to the web server + method get + see @link http://hc.apache.org/httpclient-3.x/tutorial.html + see @link blogs.sun.com/gc/entry/unable_to_find_valid_certification + see @link http://blogs.sun.com/andreas/entry/no_more_unable_to_find
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyIHM.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyIHM.html new file mode 100755 index 0000000000..5aa1be8d71 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/IvyIHM.html @@ -0,0 +1,181 @@ + + + + + + +Uses of Class pow.ivyclient.IvyIHM + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.IvyIHM

    +
    + + + + + + + + + +
    +Packages that use IvyIHM
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of IvyIHM in pow.ivyclient
    +  +

    + + + + + + + + +
    Constructors in pow.ivyclient with parameters of type IvyIHM
    Ivy2Udp(IvyIHM ihm, + PowUrl urlObj, + java.lang.String login, + java.lang.String password) + +
    +          create an object which listens on the local ivy bus and send messages to the server
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/MsgFilter.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/MsgFilter.html new file mode 100755 index 0000000000..1468460156 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/MsgFilter.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.ivyclient.MsgFilter + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.MsgFilter

    +
    +No usage of pow.ivyclient.MsgFilter +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/PowUrl.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/PowUrl.html new file mode 100755 index 0000000000..b8b8ce4511 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/class-use/PowUrl.html @@ -0,0 +1,181 @@ + + + + + + +Uses of Class pow.ivyclient.PowUrl + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.ivyclient.PowUrl

    +
    + + + + + + + + + +
    +Packages that use PowUrl
    pow.ivyclient  
    +  +

    + + + + + +
    +Uses of PowUrl in pow.ivyclient
    +  +

    + + + + + + + + +
    Constructors in pow.ivyclient with parameters of type PowUrl
    Ivy2Udp(IvyIHM ihm, + PowUrl urlObj, + java.lang.String login, + java.lang.String password) + +
    +          create an object which listens on the local ivy bus and send messages to the server
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-frame.html new file mode 100755 index 0000000000..47b6910e50 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-frame.html @@ -0,0 +1,70 @@ + + + + + + +pow.ivyclient + + + + + + + + + + + +pow.ivyclient + + + + +
    +Classes  + +
    +AcNetId +
    +AcNetIdStorage +
    +BusIvy_ +
    +HeartBeat +
    +Ivy2Udp +
    +Ivy2UdpWriting +
    +IvyIHM +
    +MsgFilter +
    +PowUrl
    + + + + + + +
    +Enums  + +
    +AcStatus
    + + + + + + +
    +Exceptions  + +
    +IvyConnectionExeption
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-summary.html new file mode 100755 index 0000000000..b72600ebe4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-summary.html @@ -0,0 +1,226 @@ + + + + + + +pow.ivyclient + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package pow.ivyclient +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Class Summary
    AcNetIdthis object represents the data concerning a drone extracted from Ivy + A drone has two identities.
    AcNetIdStoragethis structure memorize all the drone which exist on the ivy bus.
    BusIvy_inner representation of an ivy bus + store the drones' information about the drones which belong to this ivy bus + store the IP adress of the machine where the ivy bus is working
    HeartBeatthread which send a periodic message to a client or server to say that the connection + is still alive (period has to be less than the socket timeout of the the server)
    Ivy2UdpIt contact the server to get an identifier, some configuration parameter and + the key to encrypt and decrypt messages.
    Ivy2UdpWritingThis class aims to give order to the drones according to the datagrams it + receive from the web
    IvyIHMrepresent the interface for a ivy user who wants to connect a bus ivy to + the web server
    MsgFilterthis class filters the message, thanks to their hash code + it is used because Paparazzi send periodic messages that are often the same + so we filter them to lighten the server load and the bandwidth of the udp channel
    PowUrlobject which store all information about the url to log on the server
    +  + +

    + + + + + + + + + +
    +Enum Summary
    AcStatusimplements the life cycle of a drone when it is detected on the ivy bus.
    +  + +

    + + + + + + + + + +
    +Exception Summary
    IvyConnectionExeption 
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-tree.html new file mode 100755 index 0000000000..95aa0d2349 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-tree.html @@ -0,0 +1,172 @@ + + + + + + +pow.ivyclient Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package pow.ivyclient +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    + +

    +Enum Hierarchy +

    +
      +
    • java.lang.Object
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-use.html new file mode 100755 index 0000000000..01bbf5521c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/ivyclient/package-use.html @@ -0,0 +1,223 @@ + + + + + + +Uses of Package pow.ivyclient + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    pow.ivyclient

    +
    + + + + + + + + + + + + + +
    +Packages that use pow.ivyclient
    pow.ivyclient  
    pow.webserver  
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + +
    +Classes in pow.ivyclient used by pow.ivyclient
    AcNetId + +
    +          this object represents the data concerning a drone extracted from Ivy + A drone has two identities.
    AcNetIdStorage + +
    +          this structure memorize all the drone which exist on the ivy bus.
    AcStatus + +
    +          implements the life cycle of a drone when it is detected on the ivy bus.
    IvyConnectionExeption + +
    +           
    IvyIHM + +
    +          represent the interface for a ivy user who wants to connect a bus ivy to + the web server
    PowUrl + +
    +          object which store all information about the url to log on the server
    +  +

    + + + + + + + + +
    +Classes in pow.ivyclient used by pow.webserver
    BusIvy_ + +
    +          inner representation of an ivy bus + store the drones' information about the drones which belong to this ivy bus + store the IP adress of the machine where the ivy bus is working
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-frame.html new file mode 100755 index 0000000000..9819cb6a07 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-frame.html @@ -0,0 +1,34 @@ + + + + + + +pow + + + + + + + + + + + +pow + + + + +
    +Classes  + +
    +AES +
    +InstallCert
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-summary.html new file mode 100755 index 0000000000..5153706328 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-summary.html @@ -0,0 +1,165 @@ + + + + + + +pow + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package pow +

    + + + + + + + + + + + + + +
    +Class Summary
    AESimplements AES encryption and decryption algorithms + see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html + see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption
    InstallCertquery the server about its certificate and create a 'jssecacerts' file to copy + into /usr/lib/jvm/java-x-x/jre/lib/security + allow a java http client to connect to https server
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-tree.html new file mode 100755 index 0000000000..dc0faed1fc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-tree.html @@ -0,0 +1,153 @@ + + + + + + +pow Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package pow +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-use.html new file mode 100755 index 0000000000..8f4b510b9f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/package-use.html @@ -0,0 +1,193 @@ + + + + + + +Uses of Package pow + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    pow

    +
    + + + + + + + + + + + + + +
    +Packages that use pow
    pow.ivyclient  
    pow.webserver  
    +  +

    + + + + + + + + +
    +Classes in pow used by pow.ivyclient
    AES + +
    +          implements AES encryption and decryption algorithms + see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html + see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption
    +  +

    + + + + + + + + +
    +Classes in pow used by pow.webserver
    AES + +
    +          implements AES encryption and decryption algorithms + see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html + see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AjaxRqst.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AjaxRqst.html new file mode 100755 index 0000000000..c40339441d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AjaxRqst.html @@ -0,0 +1,293 @@ + + + + + + +AjaxRqst + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class AjaxRqst

    +
    +java.lang.Object
    +  extended by javax.servlet.GenericServlet
    +      extended by javax.servlet.http.HttpServlet
    +          extended by pow.webserver.AjaxRqst
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig
    +
    +
    +
    +
    public class AjaxRqst
    extends javax.servlet.http.HttpServlet
    + + +

    +Servlet implementation class ajaxRqst + handles the different request from a web client which wants to give orders to a drone + and it handles administrator queries to manage users' profiles +

    + +

    +

    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    AjaxRqst() + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    + voidinit(javax.servlet.ServletConfig config) + +
    +          init the servlet
    + + + + + + + +
    Methods inherited from class javax.servlet.http.HttpServlet
    service
    + + + + + + + +
    Methods inherited from class javax.servlet.GenericServlet
    destroy, getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +AjaxRqst

    +
    +public AjaxRqst()
    +
    +
    +
    See Also:
    HttpServlet.HttpServlet()
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init(javax.servlet.ServletConfig config)
    +          throws javax.servlet.ServletException
    +
    +
    init the servlet +

    +

    +
    Specified by:
    init in interface javax.servlet.Servlet
    Overrides:
    init in class javax.servlet.GenericServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AlreadyRegisteredUserException.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AlreadyRegisteredUserException.html new file mode 100755 index 0000000000..6738f364d8 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/AlreadyRegisteredUserException.html @@ -0,0 +1,278 @@ + + + + + + +AlreadyRegisteredUserException + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class AlreadyRegisteredUserException

    +
    +java.lang.Object
    +  extended by java.lang.Throwable
    +      extended by java.lang.Exception
    +          extended by pow.webserver.AlreadyRegisteredUserException
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable
    +
    +
    +
    +
    public class AlreadyRegisteredUserException
    extends java.lang.Exception
    + + +

    +exception to inform that a user cannot be created in the users' file + because it exists yet +

    + +

    +

    +
    Author:
    +
    genin
    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    AlreadyRegisteredUserException(User u) + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringtoString() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Throwable
    fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +AlreadyRegisteredUserException

    +
    +public AlreadyRegisteredUserException(User u)
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +toString

    +
    +public java.lang.String toString()
    +
    +
    +
    Overrides:
    toString in class java.lang.Throwable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Conf.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Conf.html new file mode 100755 index 0000000000..bca73ad8f1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Conf.html @@ -0,0 +1,564 @@ + + + + + + +Conf + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Conf

    +
    +java.lang.Object
    +  extended by pow.webserver.Conf
    +
    +
    +
    +
    public class Conf
    extends java.lang.Object
    + + +

    +store useful data about the server configuration + and database connection by + reading a specific file place in the 'conf' folder of + the web application +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Conf(java.lang.String default_folder, + java.lang.String conf_filename) + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringadminLogin() + +
    +           
    + java.lang.StringgetDataBaseName() + +
    +           
    + intgetDataEventTimeoutTime() + +
    +           
    + DbModegetDbMode() + +
    +           
    + java.lang.StringgetDBPassword() + +
    +           
    + java.lang.StringgetDBUserName() + +
    +           
    + intgetDieEventTimeoutTime() + +
    +           
    + intgetOrderResponseTimeout() + +
    +           
    + intgetSocketTimeout() + +
    +           
    + longgetTime2checkDeadBuses() + +
    +           
    + longgetTime2resetFilter() + +
    +           
    + longgetTimeToSendValues() + +
    +           
    + intgetUdpSize() + +
    +           
    + java.lang.StringmailAdmin() + +
    +           
    + intportIvyToWeb() + +
    +           
    + intportWebToIvy() + +
    +           
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Conf

    +
    +public Conf(java.lang.String default_folder,
    +            java.lang.String conf_filename)
    +
    +
    +
    Parameters:
    default_folder - folder of the web application on the server
    conf_filename - name of the configuration file placed in 'conf' folder of the web application
    +
    + + + + + + + + +
    +Method Detail
    + +

    +portIvyToWeb

    +
    +public int portIvyToWeb()
    +
    +
    + +
    Returns:
    the udp port on which the server receive data from ivy buses
    +
    +
    +
    + +

    +portWebToIvy

    +
    +public int portWebToIvy()
    +
    +
    + +
    Returns:
    the udp port on which the server send data to ivy buses
    +
    +
    +
    + +

    +getUdpSize

    +
    +public int getUdpSize()
    +
    +
    + +
    Returns:
    the max size of an udp trame
    +
    +
    +
    + +

    +getDBPassword

    +
    +public java.lang.String getDBPassword()
    +
    +
    + +
    Returns:
    the password to connect to the database
    +
    +
    +
    + +

    +getDBUserName

    +
    +public java.lang.String getDBUserName()
    +
    +
    + +
    Returns:
    the login to connect to the database
    +
    +
    +
    + +

    +getDataBaseName

    +
    +public java.lang.String getDataBaseName()
    +
    +
    + +
    Returns:
    the database name
    +
    +
    +
    + +

    +getSocketTimeout

    +
    +public int getSocketTimeout()
    +
    +
    + +
    Returns:
    a time after what an exception is thrown if no message has been received by server
    +
    +
    +
    + +

    +mailAdmin

    +
    +public java.lang.String mailAdmin()
    +
    +
    + +
    Returns:
    the mail to contact if any problem occurs
    +
    +
    +
    + +

    +adminLogin

    +
    +public java.lang.String adminLogin()
    +
    +
    + +
    Returns:
    the login of the administrator of the site
    +
    +
    +
    + +

    +getTime2resetFilter

    +
    +public long getTime2resetFilter()
    +
    +
    + +
    Returns:
    period of time in millisec to reset the filter of waypoint_moved messages
    +
    +
    +
    + +

    +getTimeToSendValues

    +
    +public long getTimeToSendValues()
    +
    +
    + +
    Returns:
    period of time in millisec to send all the parameter values for a specific drone
    +
    +
    +
    + +

    +getOrderResponseTimeout

    +
    +public int getOrderResponseTimeout()
    +
    +
    + +
    Returns:
    time to wait for the acknowledgement of an order
    +
    +
    +
    + +

    +getDieEventTimeoutTime

    +
    +public int getDieEventTimeoutTime()
    +
    +
    + +
    Returns:
    time to wait after a die event to remove the drone
    +
    +
    +
    + +

    +getDataEventTimeoutTime

    +
    +public int getDataEventTimeoutTime()
    +
    +
    + +
    Returns:
    time to wait after receiving no data for a drone to remove the drone
    +
    +
    +
    + +

    +getTime2checkDeadBuses

    +
    +public long getTime2checkDeadBuses()
    +
    +
    + +
    Returns:
    period of time to check for dead ivy buses in serveur.java
    +
    +
    +
    + +

    +getDbMode

    +
    +public DbMode getDbMode()
    +
    +
    + +
    Returns:
    SILENT or VERBOSE
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbMode.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbMode.html new file mode 100755 index 0000000000..064ea2b667 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbMode.html @@ -0,0 +1,334 @@ + + + + + + +DbMode + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Enum DbMode

    +
    +java.lang.Object
    +  extended by java.lang.Enum<DbMode>
    +      extended by pow.webserver.DbMode
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Comparable<DbMode>
    +
    +
    +
    +
    public enum DbMode
    extends java.lang.Enum<DbMode>
    + + +

    +specify how the database works +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + + + +
    +Enum Constant Summary
    SILENT + +
    +          the database stores only connection activity of ivy client
    VERBOSE + +
    +          the database records all ivy messages the server receives
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static DbModevalueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static DbMode[]values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    + + + + + + + +
    Methods inherited from class java.lang.Enum
    compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
    + + + + + + + +
    Methods inherited from class java.lang.Object
    getClass, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Enum Constant Detail
    + +

    +VERBOSE

    +
    +public static final DbMode VERBOSE
    +
    +
    the database records all ivy messages the server receives +

    +

    +
    +
    +
    + +

    +SILENT

    +
    +public static final DbMode SILENT
    +
    +
    the database stores only connection activity of ivy client +

    +

    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +values

    +
    +public static DbMode[] values()
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
    +for (DbMode c : DbMode.values())
    +    System.out.println(c);
    +
    +

    +

    + +
    Returns:
    an array containing the constants of this enum type, in +the order they are declared
    +
    +
    +
    + +

    +valueOf

    +
    +public static DbMode valueOf(java.lang.String name)
    +
    +
    Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.) +

    +

    +
    Parameters:
    name - the name of the enum constant to be returned. +
    Returns:
    the enum constant with the specified name +
    Throws: +
    java.lang.IllegalArgumentException - if this enum type has no constant +with the specified name +
    java.lang.NullPointerException - if the argument is null
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbOrder.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbOrder.html new file mode 100755 index 0000000000..9723fdca9a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/DbOrder.html @@ -0,0 +1,373 @@ + + + + + + +DbOrder + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Enum DbOrder

    +
    +java.lang.Object
    +  extended by java.lang.Enum<DbOrder>
    +      extended by pow.webserver.DbOrder
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Comparable<DbOrder>
    +
    +
    +
    +
    public enum DbOrder
    extends java.lang.Enum<DbOrder>
    + + +

    +represents 4 kind of message stored in database + CONNECT first connection of an ivy bus --> inform db + DECONNECT ivy bus deconnected --> inform db + ADD add message to db +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + +
    +Enum Constant Summary
    ADD_DATA + +
    +          just store the data in the log table
    ADD_ORDER + +
    +          the message is an order coming from a web user
    CONNECT + +
    +          store the message and create a record in the 'connexion' table
    DECONNECT + +
    +          store the message and complete the end field in the 'connexion' table
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static DbOrdervalueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static DbOrder[]values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    + + + + + + + +
    Methods inherited from class java.lang.Enum
    compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
    + + + + + + + +
    Methods inherited from class java.lang.Object
    getClass, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Enum Constant Detail
    + +

    +CONNECT

    +
    +public static final DbOrder CONNECT
    +
    +
    store the message and create a record in the 'connexion' table +

    +

    +
    +
    +
    + +

    +DECONNECT

    +
    +public static final DbOrder DECONNECT
    +
    +
    store the message and complete the end field in the 'connexion' table +

    +

    +
    +
    +
    + +

    +ADD_DATA

    +
    +public static final DbOrder ADD_DATA
    +
    +
    just store the data in the log table +

    +

    +
    +
    +
    + +

    +ADD_ORDER

    +
    +public static final DbOrder ADD_ORDER
    +
    +
    the message is an order coming from a web user +

    +

    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +values

    +
    +public static DbOrder[] values()
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
    +for (DbOrder c : DbOrder.values())
    +    System.out.println(c);
    +
    +

    +

    + +
    Returns:
    an array containing the constants of this enum type, in +the order they are declared
    +
    +
    +
    + +

    +valueOf

    +
    +public static DbOrder valueOf(java.lang.String name)
    +
    +
    Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.) +

    +

    +
    Parameters:
    name - the name of the enum constant to be returned. +
    Returns:
    the enum constant with the specified name +
    Throws: +
    java.lang.IllegalArgumentException - if this enum type has no constant +with the specified name +
    java.lang.NullPointerException - if the argument is null
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Greeting.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Greeting.html new file mode 100755 index 0000000000..1fd3eed639 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Greeting.html @@ -0,0 +1,289 @@ + + + + + + +Greeting + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Greeting

    +
    +java.lang.Object
    +  extended by javax.servlet.GenericServlet
    +      extended by javax.servlet.http.HttpServlet
    +          extended by pow.webserver.Greeting
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig
    +
    +
    +
    +
    public class Greeting
    extends javax.servlet.http.HttpServlet
    + + +

    +Servlet implementation class Greeting + Handles the connection request from a new web client + check the login's information and rights +

    + +

    +

    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Greeting() + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    + voidinit(javax.servlet.ServletConfig config) + +
    +           
    + + + + + + + +
    Methods inherited from class javax.servlet.http.HttpServlet
    service
    + + + + + + + +
    Methods inherited from class javax.servlet.GenericServlet
    destroy, getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Greeting

    +
    +public Greeting()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init(javax.servlet.ServletConfig config)
    +          throws javax.servlet.ServletException
    +
    +
    +
    Specified by:
    init in interface javax.servlet.Servlet
    Overrides:
    init in class javax.servlet.GenericServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/HeartBeat.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/HeartBeat.html new file mode 100755 index 0000000000..6831e97645 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/HeartBeat.html @@ -0,0 +1,290 @@ + + + + + + +HeartBeat + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class HeartBeat

    +
    +java.lang.Object
    +  extended by pow.webserver.HeartBeat
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable
    +
    +
    +
    +
    public class HeartBeat
    extends java.lang.Object
    implements java.lang.Runnable
    + + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    HeartBeat(javax.servlet.ServletContext s, + int h, + int p) + +
    +           
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    + voidrun() + +
    +          send a periodic heartbeat message to every connected ivy bus
    + voidstop_thread() + +
    +          stop the heartbeat process of the server
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +HeartBeat

    +
    +public HeartBeat(javax.servlet.ServletContext s,
    +                 int h,
    +                 int p)
    +
    +
    +
    Parameters:
    s - the object which stores ivysessions
    h - the period of the heartbeats
    p - the udp port to use to send heartbeat
    +
    + + + + + + + + +
    +Method Detail
    + +

    +run

    +
    +public void run()
    +
    +
    send a periodic heartbeat message to every connected ivy bus +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    +
    + +

    +stop_thread

    +
    +public void stop_thread()
    +
    +
    stop the heartbeat process of the server +

    +

    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Ivy2TomcatHttpServer.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Ivy2TomcatHttpServer.html new file mode 100755 index 0000000000..f772ae0887 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Ivy2TomcatHttpServer.html @@ -0,0 +1,312 @@ + + + + + + +Ivy2TomcatHttpServer + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Ivy2TomcatHttpServer

    +
    +java.lang.Object
    +  extended by javax.servlet.GenericServlet
    +      extended by javax.servlet.http.HttpServlet
    +          extended by pow.webserver.Ivy2TomcatHttpServer
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig
    +
    +
    +
    +
    public class Ivy2TomcatHttpServer
    extends javax.servlet.http.HttpServlet
    + + +

    +Handles the connection request from a new ivy bus + provide a unique id for the ivy bus + provide a unique id for each new drone on a ivy bus + handles the uploading of the configuration files for each new drone on a ivy bus +

    + +

    +

    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Ivy2TomcatHttpServer() + +
    +           
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    + intgetWebId(java.lang.String login) + +
    +          contact database if any to have a new webid
    + voidinit(javax.servlet.ServletConfig config) + +
    +           
    + + + + + + + +
    Methods inherited from class javax.servlet.http.HttpServlet
    service
    + + + + + + + +
    Methods inherited from class javax.servlet.GenericServlet
    destroy, getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Ivy2TomcatHttpServer

    +
    +public Ivy2TomcatHttpServer()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +init

    +
    +public void init(javax.servlet.ServletConfig config)
    +          throws javax.servlet.ServletException
    +
    +
    +
    Specified by:
    init in interface javax.servlet.Servlet
    Overrides:
    init in class javax.servlet.GenericServlet
    +
    +
    + +
    Throws: +
    javax.servlet.ServletException
    +
    +
    +
    + +

    +getWebId

    +
    +public int getWebId(java.lang.String login)
    +
    +
    contact database if any to have a new webid +

    +

    + +
    Returns:
    a webid>0 or -1 if failed
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/IvyMsg.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/IvyMsg.html new file mode 100755 index 0000000000..a99621ba67 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/IvyMsg.html @@ -0,0 +1,404 @@ + + + + + + +IvyMsg + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class IvyMsg

    +
    +java.lang.Object
    +  extended by pow.webserver.IvyMsg
    +
    +
    +
    +
    public class IvyMsg
    extends java.lang.Object
    + + +

    +represents information which are sended by the source event to the database on the queue fifo +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + + + + + + + +
    +Constructor Summary
    IvyMsg(int wId) + +
    +           
    IvyMsg(int wId, + long num, + java.lang.String date, + java.lang.String msg) + +
    +           
    IvyMsg(int wId, + long num, + java.lang.String date, + java.lang.String msg, + DbOrder order) + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.lang.StringgetIvyMsg() + +
    +           
    + longgetNumMsg() + +
    +           
    + DbOrdergetOrder() + +
    +           
    + java.lang.StringgetTimeMsg() + +
    +           
    + intgetWebId() + +
    +           
    + voidsetOrder(DbOrder o) + +
    +          specify how to store the message in database
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +IvyMsg

    +
    +public IvyMsg(int wId,
    +              long num,
    +              java.lang.String date,
    +              java.lang.String msg,
    +              DbOrder order)
    +
    +
    +
    + +

    +IvyMsg

    +
    +public IvyMsg(int wId,
    +              long num,
    +              java.lang.String date,
    +              java.lang.String msg)
    +
    +
    +
    + +

    +IvyMsg

    +
    +public IvyMsg(int wId)
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getWebId

    +
    +public int getWebId()
    +
    +
    + +
    Returns:
    the ivy web ivy which has sent the message
    +
    +
    +
    + +

    +getNumMsg

    +
    +public long getNumMsg()
    +
    +
    + +
    Returns:
    the number of the message
    +
    +
    +
    + +

    +getTimeMsg

    +
    +public java.lang.String getTimeMsg()
    +
    +
    + +
    Returns:
    the time at which the message was sent
    +
    +
    +
    + +

    +getIvyMsg

    +
    +public java.lang.String getIvyMsg()
    +
    +
    + +
    Returns:
    the ivy message
    +
    +
    +
    + +

    +getOrder

    +
    +public DbOrder getOrder()
    +
    +
    + +
    Returns:
    an order on how to store the ivy message in database
    +
    +
    +
    + +

    +setOrder

    +
    +public void setOrder(DbOrder o)
    +
    +
    specify how to store the message in database +

    +

    +
    Parameters:
    o - the way to store the message in database
    See Also:
    DbOrder
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Log.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Log.html new file mode 100755 index 0000000000..aa44e8d019 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Log.html @@ -0,0 +1,268 @@ + + + + + + +Log + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Log

    +
    +java.lang.Object
    +  extended by pow.webserver.Log
    +
    +
    +
    +
    public class Log
    extends java.lang.Object
    + + +

    +Handles the writing of a log in a file +

    + +

    +

    +
    Since:
    +
    V1
    +
    Author:
    +
    from V1
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Log(java.lang.String path) + +
    +          create a log file into the log floder of the web application
    +  + + + + + + + + + + + +
    +Method Summary
    + voidwrite(java.lang.String writing) + +
    +          write a string in log file and on stdout
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Log

    +
    +public Log(java.lang.String path)
    +
    +
    create a log file into the log floder of the web application +

    +

    +
    Parameters:
    path - the complete path of the web application
    +
    + + + + + + + + +
    +Method Detail
    + +

    +write

    +
    +public void write(java.lang.String writing)
    +
    +
    write a string in log file and on stdout +

    +

    +
    Parameters:
    writing - the string to write in the log file
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Md5.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Md5.html new file mode 100755 index 0000000000..258bdff760 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Md5.html @@ -0,0 +1,279 @@ + + + + + + +Md5 + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Md5

    +
    +java.lang.Object
    +  extended by pow.webserver.Md5
    +
    +
    +
    +
    public class Md5
    extends java.lang.Object
    + + +

    +tool class to implemente MD5 encoding + ( found on the web ) +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Md5() + +
    +           
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static java.lang.Stringencode(java.lang.String password) + +
    +           
    +static voidmain(java.lang.String[] args) + +
    +          example
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Md5

    +
    +public Md5()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +encode

    +
    +public static java.lang.String encode(java.lang.String password)
    +
    +
    +
    Parameters:
    password - the string to encode with MD5 algorithm +
    Returns:
    the encoded string with MD5 algorithm
    +
    +
    +
    + +

    +main

    +
    +public static void main(java.lang.String[] args)
    +
    +
    example +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Rights.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Rights.html new file mode 100755 index 0000000000..67989cb50c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Rights.html @@ -0,0 +1,370 @@ + + + + + + +Rights + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Enum Rights

    +
    +java.lang.Object
    +  extended by java.lang.Enum<Rights>
    +      extended by pow.webserver.Rights
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Comparable<Rights>
    +
    +
    +
    +
    public enum Rights
    extends java.lang.Enum<Rights>
    + + +

    +describe the different rights a web user can have +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + +
    +Enum Constant Summary
    ADMIN + +
    +          can pilot all the drones and manage user's account and create others administrators
    IVY + +
    +          specify an ivy user which send data to the server via UDP
    USER + +
    +          can pilot only specific drones which are specified in its user account
    VISITOR + +
    +          can only see the drones
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static RightsvalueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static Rights[]values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    + + + + + + + +
    Methods inherited from class java.lang.Enum
    compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
    + + + + + + + +
    Methods inherited from class java.lang.Object
    getClass, notify, notifyAll, wait, wait, wait
    +  +

    + + + + + + + + +
    +Enum Constant Detail
    + +

    +VISITOR

    +
    +public static final Rights VISITOR
    +
    +
    can only see the drones +

    +

    +
    +
    +
    + +

    +ADMIN

    +
    +public static final Rights ADMIN
    +
    +
    can pilot all the drones and manage user's account and create others administrators +

    +

    +
    +
    +
    + +

    +USER

    +
    +public static final Rights USER
    +
    +
    can pilot only specific drones which are specified in its user account +

    +

    +
    +
    +
    + +

    +IVY

    +
    +public static final Rights IVY
    +
    +
    specify an ivy user which send data to the server via UDP +

    +

    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +values

    +
    +public static Rights[] values()
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
    +for (Rights c : Rights.values())
    +    System.out.println(c);
    +
    +

    +

    + +
    Returns:
    an array containing the constants of this enum type, in +the order they are declared
    +
    +
    +
    + +

    +valueOf

    +
    +public static Rights valueOf(java.lang.String name)
    +
    +
    Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.) +

    +

    +
    Parameters:
    name - the name of the enum constant to be returned. +
    Returns:
    the enum constant with the specified name +
    Throws: +
    java.lang.IllegalArgumentException - if this enum type has no constant +with the specified name +
    java.lang.NullPointerException - if the argument is null
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SGBDfeeder.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SGBDfeeder.html new file mode 100755 index 0000000000..a68f1cb4fe --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SGBDfeeder.html @@ -0,0 +1,330 @@ + + + + + + +SGBDfeeder + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SGBDfeeder

    +
    +java.lang.Object
    +  extended by pow.webserver.SGBDfeeder
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable
    +
    +
    +
    +
    public class SGBDfeeder
    extends java.lang.Object
    implements java.lang.Runnable
    + + +

    +thread which waits for ivy messages sent by event source (serveur.java) + and stores them into a mysql database + the ivy messages are extracted from a blocking queue (fifo) + parameter of the database are extracted from conf file +

    + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SGBDfeeder(java.lang.String dbname, + java.lang.String dbuser, + java.lang.String dbpwd, + DbMode mode) + +
    +          create a thread which fill the database with the message it extracts from the fifo
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.util.concurrent.LinkedBlockingQueue<IvyMsg>getQueueFIFO() + +
    +           
    + voidkill() + +
    +          stop the thread by ending run method + used caused Thread.stop is now deprecated
    + voidrun() + +
    +          listens fifo queue and stores ivy messages in database + if the message has the DECONNECT type it also fills the end field corresponding + to this ivy session into the 'connexion' table
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SGBDfeeder

    +
    +public SGBDfeeder(java.lang.String dbname,
    +                  java.lang.String dbuser,
    +                  java.lang.String dbpwd,
    +                  DbMode mode)
    +
    +
    create a thread which fill the database with the message it extracts from the fifo +

    +

    +
    Parameters:
    dbname - the name of the database
    dbuser - the user login to connect to the database
    dbpwd - the user password to connect to the database
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getQueueFIFO

    +
    +public java.util.concurrent.LinkedBlockingQueue<IvyMsg> getQueueFIFO()
    +
    +
    +
    +
    +
    + +
    Returns:
    the fifo to communicate with the database feeder
    +
    +
    +
    + +

    +kill

    +
    +public void kill()
    +
    +
    stop the thread by ending run method + used caused Thread.stop is now deprecated +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +run

    +
    +public void run()
    +
    +
    listens fifo queue and stores ivy messages in database + if the message has the DECONNECT type it also fills the end field corresponding + to this ivy session into the 'connexion' table +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeHostnameVerifier.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeHostnameVerifier.html new file mode 100755 index 0000000000..873103aef5 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeHostnameVerifier.html @@ -0,0 +1,279 @@ + + + + + + +SSLUtilities.FakeHostnameVerifier + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SSLUtilities.FakeHostnameVerifier

    +
    +java.lang.Object
    +  extended by pow.webserver.SSLUtilities.FakeHostnameVerifier
    +
    +
    +
    All Implemented Interfaces:
    javax.net.ssl.HostnameVerifier
    +
    +
    +
    Enclosing class:
    SSLUtilities
    +
    +
    +
    +
    public static class SSLUtilities.FakeHostnameVerifier
    extends java.lang.Object
    implements javax.net.ssl.HostnameVerifier
    + + +

    +This class implements a fake hostname verificator, trusting any host + name. +

    + +

    +

    +
    Author:
    +
    Francis Labrie
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SSLUtilities.FakeHostnameVerifier() + +
    +           
    +  + + + + + + + + + + + +
    +Method Summary
    + booleanverify(java.lang.String hostname, + javax.net.ssl.SSLSession session) + +
    +          Always return true, indicating that the host name is + an acceptable match with the server's authentication scheme.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SSLUtilities.FakeHostnameVerifier

    +
    +public SSLUtilities.FakeHostnameVerifier()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +verify

    +
    +public boolean verify(java.lang.String hostname,
    +                      javax.net.ssl.SSLSession session)
    +
    +
    Always return true, indicating that the host name is + an acceptable match with the server's authentication scheme. +

    +

    +
    Specified by:
    verify in interface javax.net.ssl.HostnameVerifier
    +
    +
    +
    Parameters:
    hostname - the host name.
    session - the SSL session used on the connection to + host. +
    Returns:
    the true boolean value + indicating the host name is trusted.
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeX509TrustManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeX509TrustManager.html new file mode 100755 index 0000000000..d76b6bd955 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.FakeX509TrustManager.html @@ -0,0 +1,332 @@ + + + + + + +SSLUtilities.FakeX509TrustManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SSLUtilities.FakeX509TrustManager

    +
    +java.lang.Object
    +  extended by pow.webserver.SSLUtilities.FakeX509TrustManager
    +
    +
    +
    All Implemented Interfaces:
    javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager
    +
    +
    +
    Enclosing class:
    SSLUtilities
    +
    +
    +
    +
    public static class SSLUtilities.FakeX509TrustManager
    extends java.lang.Object
    implements javax.net.ssl.X509TrustManager
    + + +

    +This class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates. +

    + +

    +

    +
    Author:
    +
    Francis Labrie
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SSLUtilities.FakeX509TrustManager() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidcheckClientTrusted(java.security.cert.X509Certificate[] chain, + java.lang.String authType) + +
    +          Always trust for client SSL chain peer certificate + chain with any authType authentication types.
    + voidcheckServerTrusted(java.security.cert.X509Certificate[] chain, + java.lang.String authType) + +
    +          Always trust for server SSL chain peer certificate + chain with any authType exchange algorithm types.
    + java.security.cert.X509Certificate[]getAcceptedIssuers() + +
    +          Return an empty array of certificate authority certificates which + are trusted for authenticating peers.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SSLUtilities.FakeX509TrustManager

    +
    +public SSLUtilities.FakeX509TrustManager()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +checkClientTrusted

    +
    +public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
    +                               java.lang.String authType)
    +
    +
    Always trust for client SSL chain peer certificate + chain with any authType authentication types. +

    +

    +
    Specified by:
    checkClientTrusted in interface javax.net.ssl.X509TrustManager
    +
    +
    +
    Parameters:
    chain - the peer certificate chain.
    authType - the authentication type based on the client + certificate.
    +
    +
    +
    + +

    +checkServerTrusted

    +
    +public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
    +                               java.lang.String authType)
    +
    +
    Always trust for server SSL chain peer certificate + chain with any authType exchange algorithm types. +

    +

    +
    Specified by:
    checkServerTrusted in interface javax.net.ssl.X509TrustManager
    +
    +
    +
    Parameters:
    chain - the peer certificate chain.
    authType - the key exchange algorithm used.
    +
    +
    +
    + +

    +getAcceptedIssuers

    +
    +public java.security.cert.X509Certificate[] getAcceptedIssuers()
    +
    +
    Return an empty array of certificate authority certificates which + are trusted for authenticating peers. +

    +

    +
    Specified by:
    getAcceptedIssuers in interface javax.net.ssl.X509TrustManager
    +
    +
    + +
    Returns:
    a empty array of issuer certificates.
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeHostnameVerifier.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeHostnameVerifier.html new file mode 100755 index 0000000000..1774d01874 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeHostnameVerifier.html @@ -0,0 +1,282 @@ + + + + + + +SSLUtilities._FakeHostnameVerifier + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SSLUtilities._FakeHostnameVerifier

    +
    +java.lang.Object
    +  extended by pow.webserver.SSLUtilities._FakeHostnameVerifier
    +
    +
    +
    All Implemented Interfaces:
    com.sun.net.ssl.HostnameVerifier
    +
    +
    +
    Enclosing class:
    SSLUtilities
    +
    +
    +Deprecated. see SSLUtilities.FakeHostnameVerifier. +

    +

    +
    public static class SSLUtilities._FakeHostnameVerifier
    extends java.lang.Object
    implements com.sun.net.ssl.HostnameVerifier
    + + +

    +This class implements a fake hostname verificator, trusting any host + name. This class uses the old deprecated API from the com.sun. + ssl package. +

    + +

    +

    +
    Author:
    +
    Francis Labrie
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SSLUtilities._FakeHostnameVerifier() + +
    +          Deprecated.  
    +  + + + + + + + + + + + +
    +Method Summary
    + booleanverify(java.lang.String hostname, + java.lang.String session) + +
    +          Deprecated. Always return true, indicating that the host name is an + acceptable match with the server's authentication scheme.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SSLUtilities._FakeHostnameVerifier

    +
    +public SSLUtilities._FakeHostnameVerifier()
    +
    +
    Deprecated. 
    + + + + + + + + +
    +Method Detail
    + +

    +verify

    +
    +public boolean verify(java.lang.String hostname,
    +                      java.lang.String session)
    +
    +
    Deprecated. 
    Always return true, indicating that the host name is an + acceptable match with the server's authentication scheme. +

    +

    +
    Specified by:
    verify in interface com.sun.net.ssl.HostnameVerifier
    +
    +
    +
    Parameters:
    hostname - the host name.
    session - the SSL session used on the connection to + host. +
    Returns:
    the true boolean value + indicating the host name is trusted.
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeX509TrustManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeX509TrustManager.html new file mode 100755 index 0000000000..9b1c2f4f9b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities._FakeX509TrustManager.html @@ -0,0 +1,335 @@ + + + + + + +SSLUtilities._FakeX509TrustManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SSLUtilities._FakeX509TrustManager

    +
    +java.lang.Object
    +  extended by pow.webserver.SSLUtilities._FakeX509TrustManager
    +
    +
    +
    All Implemented Interfaces:
    com.sun.net.ssl.TrustManager, com.sun.net.ssl.X509TrustManager
    +
    +
    +
    Enclosing class:
    SSLUtilities
    +
    +
    +Deprecated. see SSLUtilities.FakeX509TrustManager. +

    +

    +
    public static class SSLUtilities._FakeX509TrustManager
    extends java.lang.Object
    implements com.sun.net.ssl.X509TrustManager
    + + +

    +This class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates. This + class uses the old deprecated API from the com.sun.ssl + package. +

    + +

    +

    +
    Author:
    +
    Francis Labrie
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SSLUtilities._FakeX509TrustManager() + +
    +          Deprecated.  
    +  + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.security.cert.X509Certificate[]getAcceptedIssuers() + +
    +          Deprecated. Return an empty array of certificate authority certificates which + are trusted for authenticating peers.
    + booleanisClientTrusted(java.security.cert.X509Certificate[] chain) + +
    +          Deprecated. Always return true, trusting for client SSL + chain peer certificate chain.
    + booleanisServerTrusted(java.security.cert.X509Certificate[] chain) + +
    +          Deprecated. Always return true, trusting for server SSL + chain peer certificate chain.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SSLUtilities._FakeX509TrustManager

    +
    +public SSLUtilities._FakeX509TrustManager()
    +
    +
    Deprecated. 
    + + + + + + + + +
    +Method Detail
    + +

    +isClientTrusted

    +
    +public boolean isClientTrusted(java.security.cert.X509Certificate[] chain)
    +
    +
    Deprecated. 
    Always return true, trusting for client SSL + chain peer certificate chain. +

    +

    +
    Specified by:
    isClientTrusted in interface com.sun.net.ssl.X509TrustManager
    +
    +
    +
    Parameters:
    chain - the peer certificate chain. +
    Returns:
    the true boolean value + indicating the chain is trusted.
    +
    +
    +
    + +

    +isServerTrusted

    +
    +public boolean isServerTrusted(java.security.cert.X509Certificate[] chain)
    +
    +
    Deprecated. 
    Always return true, trusting for server SSL + chain peer certificate chain. +

    +

    +
    Specified by:
    isServerTrusted in interface com.sun.net.ssl.X509TrustManager
    +
    +
    +
    Parameters:
    chain - the peer certificate chain. +
    Returns:
    the true boolean value + indicating the chain is trusted.
    +
    +
    +
    + +

    +getAcceptedIssuers

    +
    +public java.security.cert.X509Certificate[] getAcceptedIssuers()
    +
    +
    Deprecated. 
    Return an empty array of certificate authority certificates which + are trusted for authenticating peers. +

    +

    +
    Specified by:
    getAcceptedIssuers in interface com.sun.net.ssl.X509TrustManager
    +
    +
    + +
    Returns:
    a empty array of issuer certificates.
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.html new file mode 100755 index 0000000000..9d12a1fe97 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SSLUtilities.html @@ -0,0 +1,334 @@ + + + + + + +SSLUtilities + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SSLUtilities

    +
    +java.lang.Object
    +  extended by pow.webserver.SSLUtilities
    +
    +
    +
    +
    public final class SSLUtilities
    extends java.lang.Object
    + + +

    +This class provide various static methods that relax X509 certificate and + hostname verification while using the SSL over the HTTP protocol. + call: + SSLUtilities.trustAllHostnames() to turn off the default hostname verification on HTTPS connection; + SSLUtilities.trustAllHttpsCertificates() to turn off the default certificate validation on HTTPS connection. +

    + +

    +

    +
    Author:
    +
    Francis Labrie
    +
    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + +
    +Nested Class Summary
    +static classSSLUtilities._FakeHostnameVerifier + +
    +          Deprecated. see SSLUtilities.FakeHostnameVerifier.
    +static classSSLUtilities._FakeX509TrustManager + +
    +          Deprecated. see SSLUtilities.FakeX509TrustManager.
    +static classSSLUtilities.FakeHostnameVerifier + +
    +          This class implements a fake hostname verificator, trusting any host + name.
    +static classSSLUtilities.FakeX509TrustManager + +
    +          This class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates.
    +  + + + + + + + + + + +
    +Constructor Summary
    SSLUtilities() + +
    +           
    +  + + + + + + + + + + + + + + + +
    +Method Summary
    +static voidtrustAllHostnames() + +
    +          Set the default Hostname Verifier to an instance of a fake class that + trust all hostnames.
    +static voidtrustAllHttpsCertificates() + +
    +          Set the default X509 Trust Manager to an instance of a fake class that + trust all certificates, even the self-signed ones.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SSLUtilities

    +
    +public SSLUtilities()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +trustAllHostnames

    +
    +public static void trustAllHostnames()
    +
    +
    Set the default Hostname Verifier to an instance of a fake class that + trust all hostnames. +

    +

    +
    +
    +
    +
    + +

    +trustAllHttpsCertificates

    +
    +public static void trustAllHttpsCertificates()
    +
    +
    Set the default X509 Trust Manager to an instance of a fake class that + trust all certificates, even the self-signed ones. +

    +

    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.IvyEventSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.IvyEventSource.html new file mode 100755 index 0000000000..6243259a72 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.IvyEventSource.html @@ -0,0 +1,385 @@ + + + + + + +Serveur.IvyEventSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Serveur.IvyEventSource

    +
    +java.lang.Object
    +  extended by pow.webserver.Serveur.IvyEventSource
    +
    +
    +
    All Implemented Interfaces:
    java.lang.Runnable, nl.justobjects.pushlet.core.EventSource
    +
    +
    +
    Enclosing class:
    Serveur
    +
    +
    +
    +
    public static class Serveur.IvyEventSource
    extends java.lang.Object
    implements nl.justobjects.pushlet.core.EventSource, java.lang.Runnable
    + + +

    +


    + +

    + + + + + + + + + + + +
    +Constructor Summary
    Serveur.IvyEventSource() + +
    +           
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidactivate() + +
    +          Activate the event source.
    + voidpassivate() + +
    +          Desactivate the event source.
    + voidrun() + +
    +          main loop : + listens to the udp channel + deciphers the udp message + checks if the sender is a new bus or not + send the message to database through a fifo + turns the ivy message into a pushlet event + send the event to web users + checks if there are some buses that doesn't send messages anymore + removes drone which belonged to dead buses
    + voidsetServletContext(javax.servlet.ServletContext srvCtxt) + +
    +          method qui renseigne la source sur la servlet qui l'a appelé + modification de la librairie pushlet + Pushlet.java + EventSource.java + EventSourceManager.java
    + voidstop() + +
    +          Desactivate the event source.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Serveur.IvyEventSource

    +
    +public Serveur.IvyEventSource()
    +
    +
    + + + + + + + + +
    +Method Detail
    + +

    +activate

    +
    +public void activate()
    +
    +
    Activate the event source. + load configuration, create log and create link to database MySQL + ! setServletContext method should be called before activating +

    +

    +
    Specified by:
    activate in interface nl.justobjects.pushlet.core.EventSource
    +
    +
    +
    See Also:
    class
    +
    +
    +
    + +

    +passivate

    +
    +public void passivate()
    +
    +
    Desactivate the event source. +

    +

    +
    Specified by:
    passivate in interface nl.justobjects.pushlet.core.EventSource
    +
    +
    +
    +
    +
    +
    + +

    +stop

    +
    +public void stop()
    +
    +
    Desactivate the event source. +

    +

    +
    Specified by:
    stop in interface nl.justobjects.pushlet.core.EventSource
    +
    +
    +
    +
    +
    +
    + +

    +run

    +
    +public void run()
    +
    +
    main loop : + listens to the udp channel + deciphers the udp message + checks if the sender is a new bus or not + send the message to database through a fifo + turns the ivy message into a pushlet event + send the event to web users + checks if there are some buses that doesn't send messages anymore + removes drone which belonged to dead buses +

    +

    +
    Specified by:
    run in interface java.lang.Runnable
    +
    +
    +
    +
    +
    +
    + +

    +setServletContext

    +
    +public void setServletContext(javax.servlet.ServletContext srvCtxt)
    +
    +
    method qui renseigne la source sur la servlet qui l'a appelé + modification de la librairie pushlet + Pushlet.java + EventSource.java + EventSourceManager.java +

    +

    +
    Specified by:
    setServletContext in interface nl.justobjects.pushlet.core.EventSource
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.html new file mode 100755 index 0000000000..87a92ee036 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/Serveur.html @@ -0,0 +1,251 @@ + + + + + + +Serveur + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class Serveur

    +
    +java.lang.Object
    +  extended by pow.webserver.Serveur
    +
    +
    +
    +
    public class Serveur
    extends java.lang.Object
    + + +

    +Class which receive a datagramm from ivy bus via UDP + transforms it into a Pushlet event and send it to the Pushlet server + in order that it will be sent to web clients +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Nested Class Summary
    +static classServeur.IvyEventSource + +
    +           
    +  + + + + + + + + + + +
    +Constructor Summary
    Serveur() + +
    +           
    +  + + + + + + + +
    +Method Summary
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +Serveur

    +
    +public Serveur()
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SessionIvy.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SessionIvy.html new file mode 100755 index 0000000000..ce2bbfbd98 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/SessionIvy.html @@ -0,0 +1,401 @@ + + + + + + +SessionIvy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class SessionIvy

    +
    +java.lang.Object
    +  extended by pow.webserver.SessionIvy
    +
    +
    +
    +
    public class SessionIvy
    extends java.lang.Object
    + + +

    +store information about a specific ivy bus which is connected + to the server +

    + +

    +

    +
    Author:
    +
    genin
    +
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    SessionIvy(java.lang.String l, + int w, + AES c, + java.net.InetAddress IvyAddr) + +
    +          create a session which store information about an ivy bus client connected to the server + main information are its net address to send him orders from web users + and drones which are connected to this ivy bus
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + BusIvy_getBusIvy() + +
    +           
    + AESgetCipher() + +
    +           
    + java.net.InetAddressgetIvyInetAddress() + +
    +           
    + java.lang.StringgetLogin() + +
    +           
    + intgetWebId() + +
    +           
    + voidsetBusIvy(BusIvy_ b) + +
    +          store the information of the ivy bus into the ivy session
    + voidsetIvyInetAddress(java.net.InetAddress addr) + +
    +          set the ip adress of the ivy bus host
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +SessionIvy

    +
    +public SessionIvy(java.lang.String l,
    +                  int w,
    +                  AES c,
    +                  java.net.InetAddress IvyAddr)
    +           throws java.net.UnknownHostException
    +
    +
    create a session which store information about an ivy bus client connected to the server + main information are its net address to send him orders from web users + and drones which are connected to this ivy bus +

    +

    +
    Parameters:
    l - the login of the ivy user
    w - the webid of the ivy bus
    c - the cipher object
    IvyAddr - the IP address of the ivy host machine +
    Throws: +
    java.net.UnknownHostException
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getIvyInetAddress

    +
    +public java.net.InetAddress getIvyInetAddress()
    +
    +
    + +
    Returns:
    the ip adress of the ivy bus
    +
    +
    +
    + +

    +setIvyInetAddress

    +
    +public void setIvyInetAddress(java.net.InetAddress addr)
    +
    +
    set the ip adress of the ivy bus host +

    +

    +
    +
    +
    +
    + +

    +getCipher

    +
    +public AES getCipher()
    +
    +
    + +
    Returns:
    the AES object which allows to encrypt and decrypt a message with
    +
    +
    +
    + +

    +getBusIvy

    +
    +public BusIvy_ getBusIvy()
    +
    +
    + +
    Returns:
    the object storing data about drones on the bus
    +
    +
    +
    + +

    +setBusIvy

    +
    +public void setBusIvy(BusIvy_ b)
    +
    +
    store the information of the ivy bus into the ivy session +

    +

    +
    Parameters:
    b - the ivy bus object
    +
    +
    +
    + +

    +getWebId

    +
    +public int getWebId()
    +
    +
    + +
    Returns:
    the ivy bus identifier
    +
    +
    +
    + +

    +getLogin

    +
    +public java.lang.String getLogin()
    +
    +
    + +
    Returns:
    the login of the user who is connected via this ivy bus
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/StrictSSLProtocolSocketFactory.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/StrictSSLProtocolSocketFactory.html new file mode 100755 index 0000000000..2dad9ff236 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/StrictSSLProtocolSocketFactory.html @@ -0,0 +1,537 @@ + + + + + + +StrictSSLProtocolSocketFactory + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class StrictSSLProtocolSocketFactory

    +
    +java.lang.Object
    +  extended by pow.webserver.StrictSSLProtocolSocketFactory
    +
    +
    +
    All Implemented Interfaces:
    org.apache.commons.httpclient.protocol.ProtocolSocketFactory, org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
    +
    +
    +
    +
    public class StrictSSLProtocolSocketFactory
    extends java.lang.Object
    implements org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
    + + +

    +A SecureProtocolSocketFactory that uses JSSE to create + SSL sockets. It will also support host name verification to help preventing + man-in-the-middle attacks. Host name verification is turned on by + default but one will be able to turn it off, which might be a useful feature + during development. Host name verification will make sure the SSL sessions + server host name matches with the the host name returned in the + server certificates "Common Name" field of the "SubjectDN" entry. +

    + +

    +

    +
    Author:
    +
    Sebastian Hauer +

    + DISCLAIMER: HttpClient developers DO NOT actively support this component. + The component is provided as a reference material, which may be inappropriate + for use without additional customization. +

    +
    +
    + +

    + + + + + + + + + + + + + + +
    +Constructor Summary
    StrictSSLProtocolSocketFactory() + +
    +          Constructor for StrictSSLProtocolSocketFactory.
    StrictSSLProtocolSocketFactory(boolean verifyHostname) + +
    +          Constructor for StrictSSLProtocolSocketFactory.
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + java.net.SocketcreateSocket(java.net.Socket socket, + java.lang.String host, + int port, + boolean autoClose) + +
    +           
    + java.net.SocketcreateSocket(java.lang.String host, + int port) + +
    +           
    + java.net.SocketcreateSocket(java.lang.String host, + int port, + java.net.InetAddress clientHost, + int clientPort) + +
    +           
    + java.net.SocketcreateSocket(java.lang.String host, + int port, + java.net.InetAddress localAddress, + int localPort, + org.apache.commons.httpclient.params.HttpConnectionParams params) + +
    +          Attempts to get a new socket connection to the given host within the given time limit.
    + booleanequals(java.lang.Object obj) + +
    +           
    + booleangetHostnameVerification() + +
    +          Gets the status of the host name verification flag.
    + inthashCode() + +
    +           
    + voidsetHostnameVerification(boolean verifyHostname) + +
    +          Set the host name verification flag.
    + + + + + + + +
    Methods inherited from class java.lang.Object
    getClass, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +StrictSSLProtocolSocketFactory

    +
    +public StrictSSLProtocolSocketFactory(boolean verifyHostname)
    +
    +
    Constructor for StrictSSLProtocolSocketFactory. +

    +

    +
    Parameters:
    verifyHostname - The host name verification flag. If set to + true the SSL sessions server host name will be compared + to the host name returned in the server certificates "Common Name" + field of the "SubjectDN" entry. If these names do not match a + Exception is thrown to indicate this. Enabling host name verification + will help to prevent from man-in-the-middle attacks. If set to + false host name verification is turned off. + + Code sample: + +
    + Protocol stricthttps = new Protocol( + "https", new StrictSSLProtocolSocketFactory(true), 443); + + HttpClient client = new HttpClient(); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); +
    +
    +
    + +

    +StrictSSLProtocolSocketFactory

    +
    +public StrictSSLProtocolSocketFactory()
    +
    +
    Constructor for StrictSSLProtocolSocketFactory. + Host name verification will be enabled by default. +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +setHostnameVerification

    +
    +public void setHostnameVerification(boolean verifyHostname)
    +
    +
    Set the host name verification flag. +

    +

    +
    +
    +
    +
    Parameters:
    verifyHostname - The host name verification flag. If set to + true the SSL sessions server host name will be compared + to the host name returned in the server certificates "Common Name" + field of the "SubjectDN" entry. If these names do not match a + Exception is thrown to indicate this. Enabling host name verification + will help to prevent from man-in-the-middle attacks. If set to + false host name verification is turned off.
    +
    +
    +
    + +

    +getHostnameVerification

    +
    +public boolean getHostnameVerification()
    +
    +
    Gets the status of the host name verification flag. +

    +

    +
    +
    +
    + +
    Returns:
    Host name verification flag. Either true if host + name verification is turned on, or false if host name + verification is turned off.
    +
    +
    +
    + +

    +createSocket

    +
    +public java.net.Socket createSocket(java.lang.String host,
    +                                    int port,
    +                                    java.net.InetAddress clientHost,
    +                                    int clientPort)
    +                             throws java.io.IOException,
    +                                    java.net.UnknownHostException
    +
    +
    +
    Specified by:
    createSocket in interface org.apache.commons.httpclient.protocol.ProtocolSocketFactory
    +
    +
    + +
    Throws: +
    java.io.IOException +
    java.net.UnknownHostException
    See Also:
    ProtocolSocketFactory.createSocket(java.lang.String,int,java.net.InetAddress,int)
    +
    +
    +
    + +

    +createSocket

    +
    +public java.net.Socket createSocket(java.lang.String host,
    +                                    int port,
    +                                    java.net.InetAddress localAddress,
    +                                    int localPort,
    +                                    org.apache.commons.httpclient.params.HttpConnectionParams params)
    +                             throws java.io.IOException,
    +                                    java.net.UnknownHostException,
    +                                    org.apache.commons.httpclient.ConnectTimeoutException
    +
    +
    Attempts to get a new socket connection to the given host within the given time limit. +

    + This method employs several techniques to circumvent the limitations of older JREs that + do not support connect timeout. When running in JRE 1.4 or above reflection is used to + call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older + JREs a controller thread is executed. The controller thread attempts to create a new socket + within the given limit of time. If socket constructor does not return until the timeout + expires, the controller terminates and throws an ConnectTimeoutException +

    +

    +

    +
    Specified by:
    createSocket in interface org.apache.commons.httpclient.protocol.ProtocolSocketFactory
    +
    +
    +
    Parameters:
    host - the host name/IP
    port - the port on the host
    params - Http connection parameters +
    Returns:
    Socket a new socket +
    Throws: +
    java.io.IOException - if an I/O error occurs while creating the socket +
    java.net.UnknownHostException - if the IP address of the host cannot be + determined +
    org.apache.commons.httpclient.ConnectTimeoutException
    +
    +
    +
    + +

    +createSocket

    +
    +public java.net.Socket createSocket(java.lang.String host,
    +                                    int port)
    +                             throws java.io.IOException,
    +                                    java.net.UnknownHostException
    +
    +
    +
    Specified by:
    createSocket in interface org.apache.commons.httpclient.protocol.ProtocolSocketFactory
    +
    +
    + +
    Throws: +
    java.io.IOException +
    java.net.UnknownHostException
    See Also:
    ProtocolSocketFactory.createSocket(java.lang.String,int)
    +
    +
    +
    + +

    +createSocket

    +
    +public java.net.Socket createSocket(java.net.Socket socket,
    +                                    java.lang.String host,
    +                                    int port,
    +                                    boolean autoClose)
    +                             throws java.io.IOException,
    +                                    java.net.UnknownHostException
    +
    +
    +
    Specified by:
    createSocket in interface org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
    +
    +
    + +
    Throws: +
    java.io.IOException +
    java.net.UnknownHostException
    See Also:
    SecureProtocolSocketFactory.createSocket(java.net.Socket,java.lang.String,int,boolean)
    +
    +
    +
    + +

    +equals

    +
    +public boolean equals(java.lang.Object obj)
    +
    +
    +
    Overrides:
    equals in class java.lang.Object
    +
    +
    +
    +
    +
    +
    + +

    +hashCode

    +
    +public int hashCode()
    +
    +
    +
    Overrides:
    hashCode in class java.lang.Object
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/User.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/User.html new file mode 100755 index 0000000000..db97accfe4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/User.html @@ -0,0 +1,543 @@ + + + + + + +User + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class User

    +
    +java.lang.Object
    +  extended by pow.webserver.User
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable
    +
    +
    +
    +
    public class User
    extends java.lang.Object
    implements java.io.Serializable
    + + +

    +represents a ivy or a web user account + for the web user the account nest also the list of drones that the user can control + the list contains the ivy name of the drone (MJ5, TJ1...). + In Paparazzi a drone is not identified in a unique identifier, that means that if a user + can pilot a drone MJ5, he can pilot all 'MJ5' drone +

    + +

    +

    +
    Author:
    +
    genin
    +
    See Also:
    Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    User(java.lang.String log, + java.lang.String pwd, + Rights rght) + +
    +          create a user account
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + voidaddDrone(java.lang.String d) + +
    +          add a drone name to the list of drones that the user can control
    + booleancanControl(java.lang.String droneName) + +
    +          inform whether the user can pilot a drone or not
    + voidclearListDrone() + +
    +          reset the list of drone that the web user can control
    + java.lang.StringgetListDrone() + +
    +          the list of drone that the web user can control
    + java.lang.StringgetLogin() + +
    +           
    + java.lang.StringgetPassword() + +
    +           
    + RightsgetRights() + +
    +           
    + java.util.Iterator<java.lang.String>getSetItr() + +
    +           
    + booleanIsPwdTrue(java.lang.String pwd) + +
    +          check if the password given in argument corresponds to the password user
    + voidsetNom(java.lang.String log) + +
    +          specify the login of the user
    + voidsetPwd(java.lang.String pwd) + +
    +          specify the user password, it's not stored in clear (md5 hash)
    + voidsetRights(Rights r) + +
    +          specify the type of right granted to the user
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +User

    +
    +public User(java.lang.String log,
    +            java.lang.String pwd,
    +            Rights rght)
    +
    +
    create a user account +

    +

    +
    Parameters:
    log - the login of the user
    pwd - the password of the user
    rght - the type of the user
    +
    + + + + + + + + +
    +Method Detail
    + +

    +getSetItr

    +
    +public java.util.Iterator<java.lang.String> getSetItr()
    +
    +
    +
    +
    +
    + +
    Returns:
    an iterator containing the list of all drone that the user can control
    +
    +
    +
    + +

    +clearListDrone

    +
    +public void clearListDrone()
    +
    +
    reset the list of drone that the web user can control +

    +

    +
    +
    +
    +
    +
    +
    +
    + +

    +getListDrone

    +
    +public java.lang.String getListDrone()
    +
    +
    the list of drone that the web user can control +

    +

    +
    +
    +
    + +
    Returns:
    a formatted string containing all the drone that the user can control separated by commas
    +
    +
    +
    + +

    +addDrone

    +
    +public void addDrone(java.lang.String d)
    +
    +
    add a drone name to the list of drones that the user can control +

    +

    +
    +
    +
    +
    Parameters:
    d -
    +
    +
    +
    + +

    +canControl

    +
    +public boolean canControl(java.lang.String droneName)
    +
    +
    inform whether the user can pilot a drone or not +

    +

    +
    +
    +
    +
    Parameters:
    droneName - the name of the drone +
    Returns:
    true if the user can pilot the drones with this name
    +
    +
    +
    + +

    +getRights

    +
    +public Rights getRights()
    +
    +
    +
    +
    +
    + +
    Returns:
    the type of right granted to the user
    +
    +
    +
    + +

    +setRights

    +
    +public void setRights(Rights r)
    +
    +
    specify the type of right granted to the user +

    +

    +
    +
    +
    +
    Parameters:
    r - the right granted to the user
    +
    +
    +
    + +

    +getLogin

    +
    +public java.lang.String getLogin()
    +
    +
    +
    +
    +
    + +
    Returns:
    the login of the user
    +
    +
    +
    + +

    +setNom

    +
    +public void setNom(java.lang.String log)
    +
    +
    specify the login of the user +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user
    +
    +
    +
    + +

    +getPassword

    +
    +public java.lang.String getPassword()
    +
    +
    +
    +
    +
    + +
    Returns:
    the password of the user encoded with md5 algorithm
    +
    +
    +
    + +

    +setPwd

    +
    +public void setPwd(java.lang.String pwd)
    +
    +
    specify the user password, it's not stored in clear (md5 hash) +

    +

    +
    +
    +
    +
    Parameters:
    pwd - the user password in clear
    +
    +
    +
    + +

    +IsPwdTrue

    +
    +public boolean IsPwdTrue(java.lang.String pwd)
    +
    +
    check if the password given in argument corresponds to the password user +

    +

    +
    +
    +
    +
    Parameters:
    pwd - the password to check +
    Returns:
    true if the password is correct
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/UserTab.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/UserTab.html new file mode 100755 index 0000000000..8f2ce66f24 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/UserTab.html @@ -0,0 +1,472 @@ + + + + + + +UserTab + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +

    + +pow.webserver +
    +Class UserTab

    +
    +java.lang.Object
    +  extended by pow.webserver.UserTab
    +
    +
    +
    All Implemented Interfaces:
    java.io.Serializable
    +
    +
    +
    +
    public class UserTab
    extends java.lang.Object
    implements java.io.Serializable
    + + +

    +User objects are stored in a UserTab object which can be serialized in a file on the server disk +

    + +

    +

    +
    Author:
    +
    genin
    +
    See Also:
    User, +Serialized Form
    +
    + +

    + + + + + + + + + + + +
    +Constructor Summary
    UserTab() + +
    +          create a empty list of users
    +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Method Summary
    + booleancheckUser(java.lang.String log, + java.lang.String pwd) + +
    +          Check if the password of the user having the specified login is correct
    + java.util.Iterator<java.lang.String>getItrUsr(java.lang.String log) + +
    +          return the list of all drone which may be controlled by the user
    + java.util.Iterator<java.lang.String>getLoginIterator() + +
    +           
    + voidinsert(User u) + +
    +          insert a user in the list
    + booleanisInside(java.lang.String log) + +
    +          check if an user with this logging exists yet
    + voidremove(java.lang.String log) + +
    +          remove the user with the spefied login
    + Userseek(java.lang.String log) + +
    +          return the user corresponding to the given login
    + voidserialize(java.lang.String nomfichier) + +
    +          Save the object in a file
    +static UserTabunserialize(java.lang.String nomfichier) + +
    +          load the object from a file
    + + + + + + + +
    Methods inherited from class java.lang.Object
    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    +  +

    + + + + + + + + +
    +Constructor Detail
    + +

    +UserTab

    +
    +public UserTab()
    +
    +
    create a empty list of users +

    +

    + + + + + + + + +
    +Method Detail
    + +

    +insert

    +
    +public void insert(User u)
    +            throws AlreadyRegisteredUserException
    +
    +
    insert a user in the list +

    +

    +
    +
    +
    +
    Parameters:
    u - a user object to insert +
    Throws: +
    AlreadyRegisteredUserException
    +
    +
    +
    + +

    +remove

    +
    +public void remove(java.lang.String log)
    +
    +
    remove the user with the spefied login +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user to remove
    +
    +
    +
    + +

    +seek

    +
    +public User seek(java.lang.String log)
    +
    +
    return the user corresponding to the given login +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user to seek +
    Returns:
    the user object corresponding to the login or null if it is not present
    +
    +
    +
    + +

    +isInside

    +
    +public boolean isInside(java.lang.String log)
    +
    +
    check if an user with this logging exists yet +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user to check +
    Returns:
    true if the user having the login exists
    +
    +
    +
    + +

    +checkUser

    +
    +public boolean checkUser(java.lang.String log,
    +                         java.lang.String pwd)
    +
    +
    Check if the password of the user having the specified login is correct +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user
    pwd - the password +
    Returns:
    true if there is a user with this login and this password
    +
    +
    +
    + +

    +getItrUsr

    +
    +public java.util.Iterator<java.lang.String> getItrUsr(java.lang.String log)
    +
    +
    return the list of all drone which may be controlled by the user +

    +

    +
    +
    +
    +
    Parameters:
    log - the login of the user +
    Returns:
    an iterator containing the list of drone or null is the user does not exist
    +
    +
    +
    + +

    +getLoginIterator

    +
    +public java.util.Iterator<java.lang.String> getLoginIterator()
    +
    +
    +
    +
    +
    + +
    Returns:
    an iterator on all login in the list
    +
    +
    +
    + +

    +serialize

    +
    +public void serialize(java.lang.String nomfichier)
    +
    +
    Save the object in a file +

    +

    +
    +
    +
    +
    Parameters:
    nomfichier - the file where the user's accounts will be stored
    +
    +
    +
    + +

    +unserialize

    +
    +public static UserTab unserialize(java.lang.String nomfichier)
    +
    +
    load the object from a file +

    +

    +
    +
    +
    +
    Parameters:
    nomfichier - the file where the user's accounts are stored +
    Returns:
    an object containing the users list or null if the pathname is not correct
    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AjaxRqst.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AjaxRqst.html new file mode 100755 index 0000000000..35be99bf24 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AjaxRqst.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.AjaxRqst + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.AjaxRqst

    +
    +No usage of pow.webserver.AjaxRqst +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AlreadyRegisteredUserException.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AlreadyRegisteredUserException.html new file mode 100755 index 0000000000..dc697a84bf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/AlreadyRegisteredUserException.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class pow.webserver.AlreadyRegisteredUserException + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.AlreadyRegisteredUserException

    +
    + + + + + + + + + +
    +Packages that use AlreadyRegisteredUserException
    pow.webserver  
    +  +

    + + + + + +
    +Uses of AlreadyRegisteredUserException in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that throw AlreadyRegisteredUserException
    + voidUserTab.insert(User u) + +
    +          insert a user in the list
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Conf.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Conf.html new file mode 100755 index 0000000000..4d5a6ea5eb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Conf.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Conf + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Conf

    +
    +No usage of pow.webserver.Conf +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbMode.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbMode.html new file mode 100755 index 0000000000..bfb5b3ac95 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbMode.html @@ -0,0 +1,214 @@ + + + + + + +Uses of Class pow.webserver.DbMode + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.DbMode

    +
    + + + + + + + + + +
    +Packages that use DbMode
    pow.webserver  
    +  +

    + + + + + +
    +Uses of DbMode in pow.webserver
    +  +

    + + + + + + + + + + + + + + + + + +
    Methods in pow.webserver that return DbMode
    + DbModeConf.getDbMode() + +
    +           
    +static DbModeDbMode.valueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static DbMode[]DbMode.values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    +  +

    + + + + + + + + +
    Constructors in pow.webserver with parameters of type DbMode
    SGBDfeeder(java.lang.String dbname, + java.lang.String dbuser, + java.lang.String dbpwd, + DbMode mode) + +
    +          create a thread which fill the database with the message it extracts from the fifo
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbOrder.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbOrder.html new file mode 100755 index 0000000000..90566e8ae3 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/DbOrder.html @@ -0,0 +1,231 @@ + + + + + + +Uses of Class pow.webserver.DbOrder + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.DbOrder

    +
    + + + + + + + + + +
    +Packages that use DbOrder
    pow.webserver  
    +  +

    + + + + + +
    +Uses of DbOrder in pow.webserver
    +  +

    + + + + + + + + + + + + + + + + + +
    Methods in pow.webserver that return DbOrder
    + DbOrderIvyMsg.getOrder() + +
    +           
    +static DbOrderDbOrder.valueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static DbOrder[]DbOrder.values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    +  +

    + + + + + + + + + +
    Methods in pow.webserver with parameters of type DbOrder
    + voidIvyMsg.setOrder(DbOrder o) + +
    +          specify how to store the message in database
    +  +

    + + + + + + + + +
    Constructors in pow.webserver with parameters of type DbOrder
    IvyMsg(int wId, + long num, + java.lang.String date, + java.lang.String msg, + DbOrder order) + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Greeting.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Greeting.html new file mode 100755 index 0000000000..05f566b054 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Greeting.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Greeting + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Greeting

    +
    +No usage of pow.webserver.Greeting +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/HeartBeat.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/HeartBeat.html new file mode 100755 index 0000000000..2e2e360276 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/HeartBeat.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.HeartBeat + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.HeartBeat

    +
    +No usage of pow.webserver.HeartBeat +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Ivy2TomcatHttpServer.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Ivy2TomcatHttpServer.html new file mode 100755 index 0000000000..e80454938e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Ivy2TomcatHttpServer.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Ivy2TomcatHttpServer + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Ivy2TomcatHttpServer

    +
    +No usage of pow.webserver.Ivy2TomcatHttpServer +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/IvyMsg.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/IvyMsg.html new file mode 100755 index 0000000000..dac7ad7c6a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/IvyMsg.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class pow.webserver.IvyMsg + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.IvyMsg

    +
    + + + + + + + + + +
    +Packages that use IvyMsg
    pow.webserver  
    +  +

    + + + + + +
    +Uses of IvyMsg in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that return types with arguments of type IvyMsg
    + java.util.concurrent.LinkedBlockingQueue<IvyMsg>SGBDfeeder.getQueueFIFO() + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Log.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Log.html new file mode 100755 index 0000000000..75aaa030fe --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Log.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Log + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Log

    +
    +No usage of pow.webserver.Log +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Md5.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Md5.html new file mode 100755 index 0000000000..a14e32624c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Md5.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Md5 + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Md5

    +
    +No usage of pow.webserver.Md5 +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Rights.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Rights.html new file mode 100755 index 0000000000..18fe48e970 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Rights.html @@ -0,0 +1,229 @@ + + + + + + +Uses of Class pow.webserver.Rights + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Rights

    +
    + + + + + + + + + +
    +Packages that use Rights
    pow.webserver  
    +  +

    + + + + + +
    +Uses of Rights in pow.webserver
    +  +

    + + + + + + + + + + + + + + + + + +
    Methods in pow.webserver that return Rights
    + RightsUser.getRights() + +
    +           
    +static RightsRights.valueOf(java.lang.String name) + +
    +          Returns the enum constant of this type with the specified name.
    +static Rights[]Rights.values() + +
    +          Returns an array containing the constants of this enum type, in +the order they are declared.
    +  +

    + + + + + + + + + +
    Methods in pow.webserver with parameters of type Rights
    + voidUser.setRights(Rights r) + +
    +          specify the type of right granted to the user
    +  +

    + + + + + + + + +
    Constructors in pow.webserver with parameters of type Rights
    User(java.lang.String log, + java.lang.String pwd, + Rights rght) + +
    +          create a user account
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SGBDfeeder.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SGBDfeeder.html new file mode 100755 index 0000000000..2fb130cc19 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SGBDfeeder.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SGBDfeeder + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SGBDfeeder

    +
    +No usage of pow.webserver.SGBDfeeder +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeHostnameVerifier.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeHostnameVerifier.html new file mode 100755 index 0000000000..c742aebeb1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeHostnameVerifier.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SSLUtilities.FakeHostnameVerifier + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SSLUtilities.FakeHostnameVerifier

    +
    +No usage of pow.webserver.SSLUtilities.FakeHostnameVerifier +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeX509TrustManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeX509TrustManager.html new file mode 100755 index 0000000000..f5de159940 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.FakeX509TrustManager.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SSLUtilities.FakeX509TrustManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SSLUtilities.FakeX509TrustManager

    +
    +No usage of pow.webserver.SSLUtilities.FakeX509TrustManager +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeHostnameVerifier.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeHostnameVerifier.html new file mode 100755 index 0000000000..3295523544 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeHostnameVerifier.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SSLUtilities._FakeHostnameVerifier + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SSLUtilities._FakeHostnameVerifier

    +
    +No usage of pow.webserver.SSLUtilities._FakeHostnameVerifier +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeX509TrustManager.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeX509TrustManager.html new file mode 100755 index 0000000000..bc7ea4646b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities._FakeX509TrustManager.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SSLUtilities._FakeX509TrustManager + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SSLUtilities._FakeX509TrustManager

    +
    +No usage of pow.webserver.SSLUtilities._FakeX509TrustManager +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.html new file mode 100755 index 0000000000..15b204fe4d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SSLUtilities.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SSLUtilities + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SSLUtilities

    +
    +No usage of pow.webserver.SSLUtilities +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.IvyEventSource.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.IvyEventSource.html new file mode 100755 index 0000000000..171ee8f695 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.IvyEventSource.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Serveur.IvyEventSource + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Serveur.IvyEventSource

    +
    +No usage of pow.webserver.Serveur.IvyEventSource +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.html new file mode 100755 index 0000000000..9bfae12605 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/Serveur.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.Serveur + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.Serveur

    +
    +No usage of pow.webserver.Serveur +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SessionIvy.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SessionIvy.html new file mode 100755 index 0000000000..a20be41ac4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/SessionIvy.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.SessionIvy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.SessionIvy

    +
    +No usage of pow.webserver.SessionIvy +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/StrictSSLProtocolSocketFactory.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/StrictSSLProtocolSocketFactory.html new file mode 100755 index 0000000000..83bfbc3749 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/StrictSSLProtocolSocketFactory.html @@ -0,0 +1,144 @@ + + + + + + +Uses of Class pow.webserver.StrictSSLProtocolSocketFactory + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.StrictSSLProtocolSocketFactory

    +
    +No usage of pow.webserver.StrictSSLProtocolSocketFactory +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/User.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/User.html new file mode 100755 index 0000000000..158d303aac --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/User.html @@ -0,0 +1,210 @@ + + + + + + +Uses of Class pow.webserver.User + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.User

    +
    + + + + + + + + + +
    +Packages that use User
    pow.webserver  
    +  +

    + + + + + +
    +Uses of User in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that return User
    + UserUserTab.seek(java.lang.String log) + +
    +          return the user corresponding to the given login
    +  +

    + + + + + + + + + +
    Methods in pow.webserver with parameters of type User
    + voidUserTab.insert(User u) + +
    +          insert a user in the list
    +  +

    + + + + + + + + +
    Constructors in pow.webserver with parameters of type User
    AlreadyRegisteredUserException(User u) + +
    +           
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/UserTab.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/UserTab.html new file mode 100755 index 0000000000..09ef6d77e7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/class-use/UserTab.html @@ -0,0 +1,180 @@ + + + + + + +Uses of Class pow.webserver.UserTab + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Class
    pow.webserver.UserTab

    +
    + + + + + + + + + +
    +Packages that use UserTab
    pow.webserver  
    +  +

    + + + + + +
    +Uses of UserTab in pow.webserver
    +  +

    + + + + + + + + + +
    Methods in pow.webserver that return UserTab
    +static UserTabUserTab.unserialize(java.lang.String nomfichier) + +
    +          load the object from a file
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-frame.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-frame.html new file mode 100755 index 0000000000..59e87a47b4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-frame.html @@ -0,0 +1,96 @@ + + + + + + +pow.webserver + + + + + + + + + + + +pow.webserver + + + + +
    +Classes  + +
    +AjaxRqst +
    +Conf +
    +Greeting +
    +HeartBeat +
    +Ivy2TomcatHttpServer +
    +IvyMsg +
    +Log +
    +Md5 +
    +Serveur +
    +Serveur.IvyEventSource +
    +SessionIvy +
    +SGBDfeeder +
    +SSLUtilities +
    +SSLUtilities._FakeHostnameVerifier +
    +SSLUtilities._FakeX509TrustManager +
    +SSLUtilities.FakeHostnameVerifier +
    +SSLUtilities.FakeX509TrustManager +
    +StrictSSLProtocolSocketFactory +
    +User +
    +UserTab
    + + + + + + +
    +Enums  + +
    +DbMode +
    +DbOrder +
    +Rights
    + + + + + + +
    +Exceptions  + +
    +AlreadyRegisteredUserException
    + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-summary.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-summary.html new file mode 100755 index 0000000000..5e2b700de1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-summary.html @@ -0,0 +1,296 @@ + + + + + + +pow.webserver + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +

    +Package pow.webserver +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Class Summary
    AjaxRqstServlet implementation class ajaxRqst + handles the different request from a web client which wants to give orders to a drone + and it handles administrator queries to manage users' profiles
    Confstore useful data about the server configuration + and database connection by + reading a specific file place in the 'conf' folder of + the web application
    GreetingServlet implementation class Greeting + Handles the connection request from a new web client + check the login's information and rights
    HeartBeat 
    Ivy2TomcatHttpServerHandles the connection request from a new ivy bus + provide a unique id for the ivy bus + provide a unique id for each new drone on a ivy bus + handles the uploading of the configuration files for each new drone on a ivy bus
    IvyMsgrepresents information which are sended by the source event to the database on the queue fifo
    LogHandles the writing of a log in a file
    Md5tool class to implemente MD5 encoding + ( found on the web )
    ServeurClass which receive a datagramm from ivy bus via UDP + transforms it into a Pushlet event and send it to the Pushlet server + in order that it will be sent to web clients
    Serveur.IvyEventSource 
    SessionIvystore information about a specific ivy bus which is connected + to the server
    SGBDfeederthread which waits for ivy messages sent by event source (serveur.java) + and stores them into a mysql database + the ivy messages are extracted from a blocking queue (fifo) + parameter of the database are extracted from conf file
    SSLUtilitiesThis class provide various static methods that relax X509 certificate and + hostname verification while using the SSL over the HTTP protocol.
    SSLUtilities._FakeHostnameVerifierDeprecated. see SSLUtilities.FakeHostnameVerifier.
    SSLUtilities._FakeX509TrustManagerDeprecated. see SSLUtilities.FakeX509TrustManager.
    SSLUtilities.FakeHostnameVerifierThis class implements a fake hostname verificator, trusting any host + name.
    SSLUtilities.FakeX509TrustManagerThis class allow any X509 certificates to be used to authenticate the + remote side of a secure socket, including self-signed certificates.
    StrictSSLProtocolSocketFactoryA SecureProtocolSocketFactory that uses JSSE to create + SSL sockets.
    Userrepresents a ivy or a web user account + for the web user the account nest also the list of drones that the user can control + the list contains the ivy name of the drone (MJ5, TJ1...).
    UserTabUser objects are stored in a UserTab object which can be serialized in a file on the server disk
    +  + +

    + + + + + + + + + + + + + + + + + +
    +Enum Summary
    DbModespecify how the database works
    DbOrderrepresents 4 kind of message stored in database + CONNECT first connection of an ivy bus --> inform db + DECONNECT ivy bus deconnected --> inform db + ADD add message to db
    Rightsdescribe the different rights a web user can have
    +  + +

    + + + + + + + + + +
    +Exception Summary
    AlreadyRegisteredUserExceptionexception to inform that a user cannot be created in the users' file + because it exists yet
    +  + +

    +

    +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-tree.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-tree.html new file mode 100755 index 0000000000..c848877f62 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-tree.html @@ -0,0 +1,184 @@ + + + + + + +pow.webserver Class Hierarchy + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Hierarchy For Package pow.webserver +

    +
    +
    +
    Package Hierarchies:
    All Packages
    +
    +

    +Class Hierarchy +

    + +

    +Enum Hierarchy +

    +
      +
    • java.lang.Object
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      +
    +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-use.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-use.html new file mode 100755 index 0000000000..762260c019 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/pow/webserver/package-use.html @@ -0,0 +1,212 @@ + + + + + + +Uses of Package pow.webserver + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Uses of Package
    pow.webserver

    +
    + + + + + + + + + +
    +Packages that use pow.webserver
    pow.webserver  
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +Classes in pow.webserver used by pow.webserver
    AlreadyRegisteredUserException + +
    +          exception to inform that a user cannot be created in the users' file + because it exists yet
    DbMode + +
    +          specify how the database works
    DbOrder + +
    +          represents 4 kind of message stored in database + CONNECT first connection of an ivy bus --> inform db + DECONNECT ivy bus deconnected --> inform db + ADD add message to db
    IvyMsg + +
    +          represents information which are sended by the source event to the database on the queue fifo
    Rights + +
    +          describe the different rights a web user can have
    User + +
    +          represents a ivy or a web user account + for the web user the account nest also the list of drones that the user can control + the list contains the ivy name of the drone (MJ5, TJ1...).
    UserTab + +
    +          User objects are stored in a UserTab object which can be serialized in a file on the server disk
    +  +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/resources/inherit.gif b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/resources/inherit.gif new file mode 100755 index 0000000000..c814867a13 Binary files /dev/null and b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/resources/inherit.gif differ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/serialized-form.html b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/serialized-form.html new file mode 100755 index 0000000000..9a0ee8f735 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/serialized-form.html @@ -0,0 +1,442 @@ + + + + + + +Serialized Form + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    +

    +Serialized Form

    +
    +
    + + + + + +
    +Package pow.ivyclient
    + +

    + + + + + +
    +Class pow.ivyclient.IvyConnectionExeption extends java.lang.Exception implements Serializable
    + +

    +serialVersionUID: 1805159521752564076L + +

    + + + + + +
    +Serialized Fields
    + +

    +reason

    +
    +java.lang.String reason
    +
    +
    +
    +
    +
    + + + + + +
    +Package pow.webserver
    + +

    + + + + + +
    +Class pow.webserver.AjaxRqst extends javax.servlet.http.HttpServlet implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +default_folder

    +
    +java.lang.String default_folder
    +
    +
    +
    +
    +
    +

    +srvCtxt

    +
    +javax.servlet.ServletContext srvCtxt
    +
    +
    +
    +
    +
    +

    +myConf

    +
    +Conf myConf
    +
    +
    +
    +
    + +

    + + + + + +
    +Class pow.webserver.AlreadyRegisteredUserException extends java.lang.Exception implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +usr

    +
    +User usr
    +
    +
    +
    +
    + +

    + + + + + +
    +Class pow.webserver.Greeting extends javax.servlet.http.HttpServlet implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +default_folder

    +
    +java.lang.String default_folder
    +
    +
    +
    +
    + +

    + + + + + +
    +Class pow.webserver.Ivy2TomcatHttpServer extends javax.servlet.http.HttpServlet implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +srvCtxt

    +
    +javax.servlet.ServletContext srvCtxt
    +
    +
    +
    +
    +
    +

    +default_folder

    +
    +java.lang.String default_folder
    +
    +
    +
    +
    +
    +

    +tableIvySession

    +
    +java.util.HashMap<K,V> tableIvySession
    +
    +
    +
    +
    +
    +

    +myConf

    +
    +Conf myConf
    +
    +
    +
    +
    + +

    + + + + + +
    +Class pow.webserver.User extends java.lang.Object implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +login

    +
    +java.lang.String login
    +
    +
    +
    +
    +
    +

    +password

    +
    +java.lang.String password
    +
    +
    +
    +
    +
    +

    +dronesNamePermitted

    +
    +java.util.HashSet<E> dronesNamePermitted
    +
    +
    +
    +
    +
    +

    +right

    +
    +Rights right
    +
    +
    +
    +
    + +

    + + + + + +
    +Class pow.webserver.UserTab extends java.lang.Object implements Serializable
    + +

    +serialVersionUID: 1L + +

    + + + + + +
    +Serialized Fields
    + +

    +tabUser

    +
    +java.util.HashMap<K,V> tabUser
    +
    +
    +
    +
    + +

    +


    + + + + + + + + + + + + + + + +
    + +
    + + + +
    + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/stylesheet.css b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/stylesheet.css new file mode 100755 index 0000000000..6ea9e51616 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/doc/stylesheet.css @@ -0,0 +1,29 @@ +/* Javadoc style sheet */ + +/* Define colors, fonts and other style attributes here to override the defaults */ + +/* Page background color */ +body { background-color: #FFFFFF; color:#000000 } + +/* Headings */ +h1 { font-size: 145% } + +/* Table colors */ +.TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */ +.TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */ +.TableRowColor { background: #FFFFFF; color:#000000 } /* White */ + +/* Font used in left-hand frame lists */ +.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } + +/* Navigation bar fonts and colors */ +.NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */ +.NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */ +.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} +.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} + +.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} +.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/Version.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/Version.java new file mode 100755 index 0000000000..a2563f7192 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/Version.java @@ -0,0 +1,37 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet; + +/** + * Version info class. + * + *

    Purpose

    + * Extract version info from jar manifest file. + * + * @author Just van den Broecke + * @version $Id: Version.java,v 1.4 2006/05/06 00:10:11 justb Exp $ + */ + +public class Version { + /** Version info extracted from the .jar manifest file (see build.xml and build.properties). */ + public static final String SOFTWARE_VERSION = Version.class.getPackage().getSpecificationVersion(); + public static final String BUILD_DATE = Version.class.getPackage().getImplementationVersion(); +} + +/* + * $Log: Version.java,v $ + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2004/02/08 16:07:55 justb + * *** empty log message *** + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/11 21:29:48 justb + * first checkin + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java new file mode 100755 index 0000000000..f2dc390f26 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java @@ -0,0 +1,699 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventParser; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.OutputStream; +import java.net.*; +import java.util.Map; + +/** + * Client API for Java HTTP client applets or apps. + *

    + * Use this class within Java client applications or applets. + * Implement a PushletClientListener to receive callbacks for + * data-related Event objects pushed by the server. + *

    + * This class may also be used as a base class and be extended + * for custom clients, hence the presence of many proteced methods. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: PushletClient.java,v 1.19 2009/06/04 12:46:35 justb Exp $ + * @see PushletClientListener + * @see nl.justobjects.pushlet.test.PushletApplet + * @see nl.justobjects.pushlet.test.PushletPingApplication + */ +public class PushletClient implements Protocol { + /** + * Pushlet URL. + */ + private String pushletURL; + + /** + * Debug flag for verbose output. + */ + private boolean debug; + + /** + * Id gotten on join ack + */ + private String id; + + /** + * Internal listener for data events pushed by server. + */ + protected DataEventListener dataEventListener; + + /** + * Constructor with full pushlet URL. + */ + public PushletClient(String aPushletURL) { + pushletURL = aPushletURL; + } + + /** + * Constructor with host and port using default URI. + */ + public PushletClient(String aHost, int aPort) { + this("http://" + aHost + ":" + aPort + DEFAULT_SERVLET_URI); + } + + /** + * Set proxy options and optional proxy authentication. + *

    + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + *

    + * Usage: + * PushletClient pushletClient = new PushletClient("http:://www.domain.com/pushlet"); + * pushletClient.setProxyOptions("proxy.bla.com", "8080", ....); + *

    + * use pushletClient further as normal + */ + public void setProxyOptions(String aProxyHost, + String aProxyPort, String theNonProxyHosts, + String aUserName, String aPassword, String anNTLMDomain) { + + // Enable proxying + System.setProperty("http.proxySet", "true"); + System.setProperty("http.proxyHost", aProxyHost); + System.setProperty("http.proxyPort", aProxyPort); + + // Set optional non-proxy hosts + if (theNonProxyHosts != null) { + System.setProperty("http.nonProxyHosts", theNonProxyHosts); + } + + // If user name specified configure proxy authentication + if (aUserName != null) { + System.setProperty("http.proxyUser", aUserName); + System.setProperty("http.proxyPassword", aPassword); + + // See inner class below + Authenticator.setDefault(new HTTPAuthenticateProxy(aUserName, aPassword)); + + // Optional NT domain + if (anNTLMDomain != null) { + System.setProperty("http.auth.ntlm.domain", anNTLMDomain); + } + } + } + + /** + * Join server, starts session. + */ + public void join() throws PushletException { + Event event = new Event(E_JOIN); + event.setField(P_FORMAT, FORMAT_XML); + Event response = doControl(event); + throwOnNack(response); + + // Join Ack received + id = response.getField(P_ID); + } + + /** + * Leave server, stops session. + */ + public void leave() throws PushletException { + stopListen(); + throwOnInvalidSession(); + Event event = new Event(E_LEAVE); + event.setField(P_ID, id); + Event response = doControl(event); + + throwOnNack(response); + id = null; + } + + /** + * Open data channel. + */ + public void listen(PushletClientListener aListener) throws PushletException { + listen(aListener, MODE_STREAM); + } + + /** + * Open data channel in stream or push mode. + */ + public void listen(PushletClientListener aListener, String aMode) throws PushletException { + listen(aListener, aMode, null); + } + + /** + * Open data channel in stream or push mode with a subject. + */ + public void listen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + throwOnInvalidSession(); + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_LISTEN + + "&" + P_ID + "=" + id + + "&" + P_MODE + "=" + aMode; + if (aSubject != null) { + listenURL = listenURL + "&" + P_SUBJECT + "=" + aSubject; + } + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Immediate listener: joins/subscribes and listens in one action. + */ + public void joinListen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_JOIN_LISTEN + + "&" + P_FORMAT + "=" + FORMAT_XML + + "&" + P_MODE + "=" + aMode + + "&" + P_SUBJECT + "=" + aSubject; + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Publish an event through server. + */ + public void publish(String aSubject, Map theAttributes) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_PUBLISH, theAttributes); + event.setField(P_SUBJECT, aSubject); + event.setField(P_ID, id); + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject, String aLabel) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_SUBSCRIBE); + event.setField(P_ID, id); + event.setField(P_SUBJECT, aSubject); + + // Optional label, is returned in data events + if (aLabel != null) { + event.setField(P_SUBSCRIPTION_LABEL, aLabel); + } + + // Send request + Event response = doControl(event); + throwOnNack(response); + + return response.getField(P_SUBSCRIPTION_ID); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject) throws PushletException { + return subscribe(aSubject, null); + } + + /** + * Unsubscribes with subscription id. + */ + public void unsubscribe(String aSubscriptionId) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_UNSUBSCRIBE); + event.setField(P_ID, id); + + // Optional subscription id + if (aSubscriptionId != null) { + event.setField(P_SUBSCRIPTION_ID, aSubscriptionId); + } + + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Unsubscribes from all subjects. + */ + public void unsubscribe() throws PushletException { + unsubscribe(null); + } + + /** + * Stop the listener. + */ + public void stopListen() throws PushletException { + if (dataEventListener != null) { + unsubscribe(); + dataEventListener.stop(); + dataEventListener = null; + } + } + + public void setDebug(boolean b) { + debug = b; + } + + /** + * Starts default DataEventListener and waits for its thread to start. + */ + protected void startDataEventListener(PushletClientListener aListener, String aListenURL) { + // Suggestion by Jeff Nowakowski 29.oct.2006 + dataEventListener = new DataEventListener(aListener, aListenURL); + + synchronized (dataEventListener) { + dataEventListener.start(); + try { + // Wait for data event listener (thread) to start + dataEventListener.wait(); + } catch (InterruptedException e) { + } + } + } + + protected void throwOnNack(Event anEvent) throws PushletException { + if (anEvent.getEventType().equals(E_NACK)) { + throw new PushletException("Negative response: reason=" + anEvent.getField(P_REASON)); + } + } + + protected void throwOnInvalidSession() throws PushletException { + if (id == null) { + throw new PushletException("Invalid pushlet session"); + } + } + + protected Reader openURL(String aURL) throws PushletException { + // Open URL connection with server + try { + p("Connecting to " + aURL); + URL url = new URL(aURL); + URLConnection urlConnection = url.openConnection(); + + // Disable any kind of caching. + urlConnection.setUseCaches(false); + urlConnection.setDefaultUseCaches(false); + + // TODO: later version may use POST + // Enable HTTP POST + // urlConnection.setDoOutput(true); + + // Do the POST with Event in XML in body + // OutputStream os = urlConnection.getOutputStream(); + // os.write(anEvent.toXML().getBytes()); + // os.flush(); + // os.close(); + + // Get the stream from the server. + // reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + // Note: somehow the client does not work with some JVMs when using + // BufferedInputStream... So do unbuffered input. + // p("Opening urlConnection inputstream"); + return new InputStreamReader(urlConnection.getInputStream()); + + } catch (Throwable t) { + warn("openURL() could not open " + aURL, t); + throw new PushletException(" could not open " + aURL, t); + } + } + + + /** + * Send control events to server and return response. + */ + protected Event doControl(Event aControlEvent) throws PushletException { + String controlURL = pushletURL + "?" + aControlEvent.toQueryString(); + + p("doControl to " + controlURL); + + // Open URL connection with server + Reader reader = openURL(controlURL); + + // Get Pushlet event from stream + Event event = null; + try { + p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + return event; + } catch (Throwable t) { + // Stop and report error. + warn("doControl() exception", t); + throw new PushletException(" error parsing response from" + controlURL, t); + } + } + + /** + * Util: print. + */ + protected void p(String s) { + if (debug) { + System.out.println("[PushletClient] " + s); + } + } + + /** + * Util: warn. + */ + protected void warn(String s) { + warn(s, null); + } + + /** + * Util: warn with exception. + */ + protected void warn(String s, Throwable t) { + System.err.println("[PushletClient] - WARN - " + s + " ex=" + t); + + if (t != null) { + t.printStackTrace(); + } + } + + /** + * Internal (default) listener for the Pushlet data channel. + */ + protected class DataEventListener implements Runnable { + /** + * Client's listener that gets called back on events. + */ + private PushletClientListener listener; + + /** + * Receiver receiveThread. + */ + private Thread receiveThread = null; + private Reader reader; + private String refreshURL; + private String listenURL; + + public DataEventListener(PushletClientListener aListener, String aListenURL) { + listener = aListener; + listenURL = aListenURL; + } + + public void start() { + // All ok: start a receiver receiveThread + receiveThread = new Thread(this); + receiveThread.start(); + + } + + /** + * Stop listening; may restart later with start(). + */ + public void stop() { + p("In stop()"); + bailout(); + } + + /** + * Receive event objects from server and callback listener. + */ + public void run() { + p("Start run()"); + try { + while (receiveThread != null && receiveThread.isAlive()) { + // Connect to server + reader = openURL(listenURL); + + synchronized (this) { + // Inform the calling thread we're ready to receive events. + // Suggestion by Jeff Nowakowski 29.oct.2006 + this.notify(); + } + + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; + try { + // p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + } catch (Throwable t) { + + // Stop and report error. + // warn("Stop run() on exception", t); + if (listener != null) { + listener.onError("exception during receive: " + t); + } + + break; + } + + // Handle event by calling listener + if (event != null && listener != null) { + // p("received: " + event.toXML()); + String eventType = event.getEventType(); + if (eventType.equals(E_HEARTBEAT)) { + listener.onHeartbeat(event); + } else if (eventType.equals(E_DATA)) { + listener.onData(event); + } else if (eventType.equals(E_JOIN_LISTEN_ACK)) { + id = event.getField(P_ID); + } else if (eventType.equals(E_LISTEN_ACK)) { + p("Listen ack ok"); + } else if (eventType.equals(E_REFRESH_ACK)) { + // ignore + } else if (eventType.equals(E_ABORT)) { + listener.onAbort(event); + listener = null; + break; + } else if (eventType.equals(E_REFRESH)) { + refresh(event); + } else { + handleUnknownEventType(eventType, event, listener); + } + } + } + } + } catch (Throwable t) { + warn("Exception in run() ", t); + // bailout(); + } + } + + protected void disconnect() { + p("start disconnect()"); + if (reader != null) { + try { + // this blocks, find another way + // reader.close(); + p("Closed reader ok"); + } catch (Exception ignore) { + } finally { + reader = null; + } + } + p("end disconnect()"); + } + + /** + * Stop receiver receiveThread. + */ + public void stopThread() { + p("In stopThread()"); + + // Keep a reference such that we can kill it from here. + Thread targetThread = receiveThread; + + receiveThread = null; + + // This should stop the main loop for this receiveThread. + // Killing a receiveThread on a blcing read is tricky. + // See also http://gee.cs.oswego.edu/dl/cpj/cancel.html + if ((targetThread != null) && targetThread.isAlive()) { + + targetThread.interrupt(); + + try { + + // Wait for it to die + targetThread.join(500); + } catch (InterruptedException ignore) { + } + + // If current receiveThread refuses to die, + // take more rigorous methods. + if (targetThread.isAlive()) { + + // Not preferred but may be needed + // to stop during a blocking read. + targetThread.stop(); + + // Wait for it to die + try { + targetThread.join(500); + } catch (Throwable ignore) { + } + } + + p("Stopped receiveThread alive=" + targetThread.isAlive()); + + } + } + + /** + * Stop listening on stream from server. + */ + public void bailout() { + p("In bailout()"); + stopThread(); + disconnect(); + } + + /** + * Handle refresh, by pausing. + */ + protected void refresh(Event aRefreshEvent) throws PushletException { + try { + // Wait for specified time. + Thread.sleep(Long.parseLong(aRefreshEvent.getField(P_WAIT))); + } catch (Throwable t) { + warn("abort while refresing"); + refreshURL = null; + return; + } + + // If stopped during sleep, don't proceed + if (receiveThread == null) { + return; + } + + // Create url to refresh + refreshURL = pushletURL + + "?" + P_ID + "=" + id + + "&" + P_EVENT + "=" + E_REFRESH + ; + + if (reader != null) { + try { + reader.close(); + + } catch (IOException ignore) { + + } + reader = null; + } + + reader = openURL(refreshURL); + } + + /** + * Handle unknown Event (default behaviour). + */ + protected void handleUnknownEventType(String eventType, Event event, PushletClientListener listener) { + warn("unsupported event type received: " + eventType); + } + } + + /** + * Authenticator + */ + private static class HTTPAuthenticateProxy extends Authenticator { + + /** + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + */ + + private String thePassword = ""; + private String theUser = ""; + + public HTTPAuthenticateProxy(String username, String password) { + + thePassword = password; + theUser = username; + } + + protected PasswordAuthentication getPasswordAuthentication() { + // System.out.println("[HttpAuthenticateProxy] Username = " + theUser); + // System.out.println("[HttpAuthenticateProxy] Password = " + thePassword); + + return new PasswordAuthentication(theUser, thePassword.toCharArray()); + } + + } + +} + +/* + * $Log: PushletClient.java,v $ + * Revision 1.19 2009/06/04 12:46:35 justb + * PushletClient: add more hooks for extension (feat ID: 2799694 Craig M) + * + * Revision 1.18 2007/11/10 13:52:47 justb + * make startDataEventListener method protected to allow overriding + * + * Revision 1.17 2006/10/29 16:47:57 justb + * included patch from Jeff Nowakowski: wait until listener thread runs + * + * Revision 1.16 2005/05/06 20:08:20 justb + * client enhancements + * + * Revision 1.15 2005/03/27 17:42:27 justb + * enhancements + * + * Revision 1.14 2005/03/25 23:54:04 justb + * *** empty log message *** + * + * Revision 1.13 2005/02/28 16:59:40 justb + * fixes for leave and disconnect + * + * Revision 1.12 2005/02/28 15:57:54 justb + * added SimpleListener example + * + * Revision 1.11 2005/02/21 12:31:44 justb + * added proxy contribution from Dele Olajide + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/02/18 09:54:12 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.7 2005/02/15 15:46:30 justb + * client API improves + * + * Revision 1.6 2005/02/15 13:28:56 justb + * first quick rewrite adapt for v2 protocol + * + * Revision 1.5 2004/10/25 21:23:44 justb + * *** empty log message *** + * + * Revision 1.4 2004/10/24 13:52:51 justb + * small fixes in client lib + * + * Revision 1.3 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 20:14:17 justb + * renamed all *JavaPushletClient* to *PushletClient* + * + * Revision 1.10 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.9 2003/08/17 20:30:20 justb + * cosmetic changes + * + * Revision 1.8 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java.patch b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java.patch new file mode 100755 index 0000000000..63d660354d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClient.java.patch @@ -0,0 +1,29 @@ +--- PushletClient.java 6 May 2005 20:08:20 -0000 1.16 ++++ PushletClient.java 28 Oct 2006 23:19:12 -0000 +@@ -142,7 +142,13 @@ + } + + dataEventListener = new DataEventListener(aListener, listenURL); +- dataEventListener.start(); ++ synchronized (dataEventListener) { ++ dataEventListener.start(); ++ try { ++ dataEventListener.wait(); ++ } catch (InterruptedException e) { ++ } ++ } + } + + /** Immediate listener. */ +@@ -354,6 +360,11 @@ + // Connect to server + reader = openURL(listenURL); + ++ synchronized (this) { ++ // Inform the calling thread we're ready to receive events. ++ this.notify(); ++ } ++ + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClientListener.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClientListener.java new file mode 100755 index 0000000000..74cee7b2b2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/client/PushletClientListener.java @@ -0,0 +1,50 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; + +/** + * Interface for listener of the PushletClient object. + * + * @version $Id: PushletClientListener.java,v 1.5 2005/02/21 11:50:37 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public interface PushletClientListener extends Protocol { + /** Abort event from server. */ + public void onAbort(Event theEvent); + + /** Data event from server. */ + public void onData(Event theEvent); + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent); + + /** Error occurred. */ + public void onError(String message); +} + +/* +* $Log: PushletClientListener.java,v $ +* Revision 1.5 2005/02/21 11:50:37 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.4 2005/02/15 15:46:31 justb +* client API improves +* +* Revision 1.3 2004/10/24 12:58:18 justb +* revised client and test classes for new protocol +* +* Revision 1.2 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.1 2004/03/10 20:14:17 justb +* renamed all *JavaPushletClient* to *PushletClient* +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/BrowserAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/BrowserAdapter.java new file mode 100755 index 0000000000..8aa226b659 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/BrowserAdapter.java @@ -0,0 +1,203 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Iterator; + +/** + * Generic implementation of ClientAdapter for browser clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: BrowserAdapter.java,v 1.6 2007/11/09 13:15:35 justb Exp $ + */ +public class BrowserAdapter implements ClientAdapter, Protocol { + + public static final String START_DOCUMENT = + "" + + "" + + "\n"; + public static final String END_DOCUMENT = ""; + + private PrintWriter servletOut; + private HttpServletResponse servletRsp; + private int bytesSent; + + /** + * Constructor. + */ + public BrowserAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + /** + * Generic init. + */ + public void start() throws IOException { + // Keep servlet request/response objects until page ends in stop() + // Content type as HTML + servletRsp.setStatus(HttpServletResponse.SC_OK); + servletRsp.setContentType("text/html;charset=UTF-8"); + + // http://www.junlu.com/msg/45902.html + // Log.debug("bufsize=" + aRsp.getBufferSize()); + servletOut = servletRsp.getWriter(); + send(START_DOCUMENT); + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + Log.debug("BCA event=" + anEvent.toXML()); + + // Check if we should refresh + if (anEvent.getEventType().equals(Protocol.E_REFRESH)) { + // Append refresh and tail of HTML document + // Construct the JS callback line to be sent as last line of doc. + // This will refresh the request using the unique id to determine + // the subscriber instance on the server. The client will wait for + // a number of milliseconds. + long refreshWaitMillis = Long.parseLong(anEvent.getField(P_WAIT)); + + // Create servlet request for requesting next events (refresh) + String url = anEvent.getField(P_URL); + String jsRefreshTrigger = "\n"; + + + send(jsRefreshTrigger + END_DOCUMENT); + } else { + send(event2JavaScript(anEvent)); + } + } + + /** + * End HTML page in client browser. + */ + public void stop() { + // To be garbage collected if adapter remains active + servletOut = null; + } + + /** + * Send any string to browser. + */ + protected void send(String s) throws IOException { + // Send string to browser. + // Log.debug("Adapter: sending: " + s); + if (servletOut == null) { + throw new IOException("Client adapter was stopped"); + } + + servletOut.print(s); + + servletOut.flush(); + + // Note: this doesn't seem to have effect + // in Tomcat 4/5 if the client already disconnected. + servletRsp.flushBuffer(); + + bytesSent += s.length(); + Log.debug("bytesSent= " + bytesSent); + // Log.debug("BCA sent event: " + s); + } + + /** + * Converts the Java Event to a JavaScript function call in browser page. + */ + protected String event2JavaScript(Event event) throws IOException { + + // Convert the event to a comma-separated string. + String jsArgs = ""; + for (Iterator iter = event.getFieldNames(); iter.hasNext();) { + String name = (String) iter.next(); + String value = event.getField(name); + String nextArgument = (jsArgs.equals("") ? "" : ",") + "'" + name + "'" + ", \"" + value + "\""; + jsArgs += nextArgument; + } + + // Construct and return the function call */ + return ""; + } + +} + +/* + * $Log: BrowserAdapter.java,v $ + * Revision 1.6 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.5 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:44 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.12 2005/02/15 13:30:23 justb + * changes for Tomcat buffering (now working in tc4 and 5.0) + * + * Revision 1.11 2005/01/24 22:45:58 justb + * getting safari to work + * + * Revision 1.10 2005/01/18 16:46:27 justb + * buffer size setting ignored by tomcat workings + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:07 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:02 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/10/30 14:15:47 just + * no message + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ClientAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ClientAdapter.java new file mode 100755 index 0000000000..c7ea141fee --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ClientAdapter.java @@ -0,0 +1,72 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.IOException; + +/** + * Adapter interface for encapsulation of specific HTTP clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ClientAdapter.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public interface ClientAdapter { + + /** + * Start event push. + */ + public void start() throws IOException; + + /** + * Push single Event to client. + */ + public void push(Event anEvent) throws IOException; + + /** + * Stop event push. + */ + public void stop() throws IOException; +} + +/* + * $Log: ClientAdapter.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/21 11:50:45 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Command.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Command.java new file mode 100755 index 0000000000..dbba4fae76 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Command.java @@ -0,0 +1,158 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Servlets; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Wraps pushlet request/response data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Command.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +public class Command implements Protocol { + + /** + * Pushlet request event. + */ + public final Event reqEvent; + + /** + * Pushlet response event. + */ + private Event rspEvent; + + /** + * HTTP Servlet GET/POST request. + */ + public final HttpServletRequest httpReq; + + /** + * HTTP Servlet GET/POST response. + */ + public final HttpServletResponse httpRsp; + + /** + * Pushlet session. + */ + public final Session session; + + /** + * Per-response client adapter. + */ + private ClientAdapter clientAdapter; + + /** + * Constructor. + */ + private Command(Session aSession, Event aRequestEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + session = aSession; + reqEvent = aRequestEvent; + httpReq = aHTTPReq; + httpRsp = aHTTPRsp; + } + + /** + * Create new Command object. + */ + public static Command create(Session aSession, Event aReqEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + return new Command(aSession, aReqEvent, aHTTPReq, aHTTPRsp); + } + + /** + * Set pushlet response event. + */ + public void setResponseEvent(Event aResponseEvent) { + rspEvent = aResponseEvent; + } + + /** + * Get pushlet response event. + */ + public Event getResponseEvent() { + return rspEvent; + } + + /** + * Get client adapter for request. + */ + public ClientAdapter getClientAdapter() throws PushletException { + if (clientAdapter == null) { + // Create and initialize client-specific adapter. + clientAdapter = createClientAdapter(); + } + return clientAdapter; + } + + /** + * Create client notifier based on "format" parameter passed in request. + */ + protected ClientAdapter createClientAdapter() throws PushletException { + + // Assumed to be set by parent. + String outputFormat = session.getFormat(); + + // Determine client adapter to create. + if (outputFormat.equals(FORMAT_JAVASCRIPT)) { + // Client expects to receive Events as JavaScript dispatch calls.. + return new BrowserAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_SERIALIZED_JAVA_OBJECT)) { + // Client expects to receive Events as Serialized Java Objects. + return new SerializedAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML)) { + // Client expects to receive Events as stream of XML docs. + return new XMLAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML_STRICT)) { + // Client expects to receive Events embedded in single XML doc. + return new XMLAdapter(httpRsp, true); + } else { + throw new PushletException("Null or invalid output format: " + outputFormat); + } + } + + /** + * Sends HTTP response headers. + */ + protected void sendResponseHeaders() { + // Just to try to prevent caching in any form. + Servlets.setNoCacheHeaders(httpRsp); + + // Close connection for Java enabled browsers + if (session.getUserAgent().indexOf("java") > 0) { + // The connection should be closed after this request + // NB: this allows sending a "long response". Some clients + // in particular java.net.URL in VMs > 1.1 that use HTTP/1.1 + // will block if + // - the content length is not sent + // - if Connection: close HTTP header is not sent. + // + // Since we don't know the content length we will assume + // the underlying servlet engine will use chunked encoding. + httpRsp.setHeader("Connection", "close"); + } + } + + +} + +/* + * $Log: Command.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.2 2005/02/28 17:25:15 justb + * commented + * + * Revision 1.1 2005/02/28 12:45:59 justb + * introduced Command class + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Config.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Config.java new file mode 100755 index 0000000000..c598e033d7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Config.java @@ -0,0 +1,152 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Sys; + +import java.io.File; +import java.util.Properties; + +/** + * Loads and maintains overall configuration. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Config.java,v 1.5 2007/11/23 21:10:17 justb Exp $ + */ +public class Config implements ConfigDefs { + private static final String PROPERTIES_FILE = "pushlet.properties"; + private static Properties properties; + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return an instance of class denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Object createObject(String aClassNameProp, String aDefault) throws PushletException { + Class clazz = getClass(aClassNameProp, aDefault); + try { + return clazz.newInstance(); + } catch (Throwable t) { + // Usually a misconfiguration + throw new PushletException("Cannot instantiate class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return a Class object denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Class getClass(String aClassNameProp, String aDefault) throws PushletException { + // Singleton + factory pattern: create object instance + // from configured class name + String clazz = (aDefault == null ? getProperty(aClassNameProp) : getProperty(aClassNameProp, aDefault)); + + try { + return Class.forName(clazz); + } catch (ClassNotFoundException t) { + // Usually a misconfiguration + throw new PushletException("Cannot find class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Initialize event sources from properties file. + */ + public static void load(String aDirPath) { + // Load Event sources using properties file. + try { + // Try loading through classpath first (e.g. in WEB-INF/classes or from .jar) + Log.info("Config: loading " + PROPERTIES_FILE + " from classpath"); + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("Config: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("Config: cannot load properties file from " + filePath, t); + + // Give up + return; + } + } + + Log.info("Config: loaded values=" + properties); + } + + public static String getProperty(String aName, String aDefault) { + return properties.getProperty(aName, aDefault); + } + + public static String getProperty(String aName) { + String value = properties.getProperty(aName); + if (value == null) { + throw new IllegalArgumentException("Unknown property: " + aName); + } + return value; + } + + public static boolean getBoolProperty(String aName) { + String value = getProperty(aName); + try { + return value.equals("true"); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static int getIntProperty(String aName) { + String value = getProperty(aName); + try { + return Integer.parseInt(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static long getLongProperty(String aName) { + String value = getProperty(aName); + try { + return Long.parseLong(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static boolean hasProperty(String aName) { + return properties.containsKey(aName); + } + + +} + +/* + * $Log: Config.java,v $ + * Revision 1.5 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ConfigDefs.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ConfigDefs.java new file mode 100755 index 0000000000..df00d41beb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/ConfigDefs.java @@ -0,0 +1,104 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Definition of config property strings. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ConfigDefs.java,v 1.9 2007/12/07 12:57:40 justb Exp $ + */ +public interface ConfigDefs { + /** + * Class factory definitions, used to insert your custom classes. + */ + public static final String CONTROLLER_CLASS = "controller.class"; + public static final String DISPATCHER_CLASS = "dispatcher.class"; + public static final String LOGGER_CLASS = "logger.class"; + public static final String SESSION_MANAGER_CLASS = "sessionmanager.class"; + public static final String SESSION_CLASS = "session.class"; + public static final String SUBSCRIBER_CLASS = "subscriber.class"; + public static final String SUBSCRIPTION_CLASS = "subscription.class"; + + /** + * Session management. + */ + public static final String SESSION_ID_SIZE = "session.id.size"; + public static final String SESSION_ID_GENERATION = "session.id.generation"; + public static final String SESSION_ID_GENERATION_UUID = "uuid"; + public static final String SESSION_ID_GENERATION_RANDOMSTRING = "randomstring"; + public static final String SESSION_TIMEOUT_MINS = "session.timeout.mins"; + + public static final String SOURCES_ACTIVATE = "sources.activate"; + + /** + * Logging + */ + public static final String LOG_LEVEL = "log.level"; + public static final int LOG_LEVEL_FATAL = 1; + public static final int LOG_LEVEL_ERROR = 2; + public static final int LOG_LEVEL_WARN = 3; + public static final int LOG_LEVEL_INFO = 4; + public static final int LOG_LEVEL_DEBUG = 5; + public static final int LOG_LEVEL_TRACE = 6; + + /** + * Queues + */ + public static final String QUEUE_SIZE = "queue.size"; + public static final String QUEUE_READ_TIMEOUT_MILLIS = "queue.read.timeout.millis"; + public static final String QUEUE_WRITE_TIMEOUT_MILLIS = "queue.write.timeout.millis"; + + /** + * Listening modes. + */ + public static final String LISTEN_FORCE_PULL_ALL = "listen.force.pull.all"; + public static final String LISTEN_FORCE_PULL_AGENTS = "listen.force.pull.agents"; + + + public static final String PULL_REFRESH_TIMEOUT_MILLIS = "pull.refresh.timeout.millis"; + public static final String PULL_REFRESH_WAIT_MIN_MILLIS = "pull.refresh.wait.min.millis"; + public static final String PULL_REFRESH_WAIT_MAX_MILLIS = "pull.refresh.wait.max.millis"; + + + public static final String POLL_REFRESH_TIMEOUT_MILLIS = "poll.refresh.timeout.millis"; + public static final String POLL_REFRESH_WAIT_MIN_MILLIS = "poll.refresh.wait.min.millis"; + public static final String POLL_REFRESH_WAIT_MAX_MILLIS = "poll.refresh.wait.max.millis"; + +} + +/* + * $Log: ConfigDefs.java,v $ + * Revision 1.9 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.8 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2007/11/10 14:48:35 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/21 16:59:00 justb + * SessionManager and session lease introduced + * + * Revision 1.3 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.2 2005/02/21 11:16:44 justb + * add log level config prop + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Controller.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Controller.java new file mode 100755 index 0000000000..ca90b1539e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Controller.java @@ -0,0 +1,502 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; + +/** + * Handles servlet requests from client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Controller.java,v 1.9 2007/11/23 14:33:07 justb Exp $ + */ +public class Controller implements Protocol, ConfigDefs { + + private Session session; + + /** + * Protected constructor as we create through factory method. + */ + protected Controller() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Controller object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Controller create(Session aSession) throws PushletException { + Controller controller; + try { + controller = (Controller) Config.getClass(CONTROLLER_CLASS, "nl.justobjects.pushlet.core.Controller").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Controller from config", t); + } + controller.session = aSession; + return controller; + } + + /** + * Handle command. + */ + public void doCommand(Command aCommand) { + try { + // Update lease time to live + session.kick(); + + // Set remote IP address of client + session.setAddress(aCommand.httpReq.getRemoteAddr()); + + debug("doCommand() event=" + aCommand.reqEvent); + + // Get event type + String eventType = aCommand.reqEvent.getEventType(); + + // Determine action based on event type + if (eventType.equals(Protocol.E_REFRESH)) { + // Pull/poll mode clients that refresh + doRefresh(aCommand); + } else if (eventType.equals(Protocol.E_SUBSCRIBE)) { + // Subscribe + doSubscribe(aCommand); + } else if (eventType.equals(Protocol.E_UNSUBSCRIBE)) { + // Unsubscribe + doUnsubscribe(aCommand); + } else if (eventType.equals(Protocol.E_JOIN)) { + // Join + doJoin(aCommand); + } else if (eventType.equals(Protocol.E_JOIN_LISTEN)) { + // Join and listen (for simple and e.g. REST apps) + doJoinListen(aCommand); + } else if (eventType.equals(Protocol.E_LEAVE)) { + // Leave + doLeave(aCommand); + } else if (eventType.equals(Protocol.E_HEARTBEAT)) { + // Heartbeat mainly to do away with browser "busy" cursor + doHeartbeat(aCommand); + } else if (eventType.equals(Protocol.E_PUBLISH)) { + // Publish event + doPublish(aCommand); + } else if (eventType.equals(Protocol.E_LISTEN)) { + // Listen to pushed events + doListen(aCommand); + } + + // Handle response back to client + if (eventType.endsWith(Protocol.E_LISTEN) || + eventType.equals(Protocol.E_REFRESH)) { + // Data channel events + // Loops until refresh or connection closed + getSubscriber().fetchEvents(aCommand); + + } else { + // Send response for control commands + sendControlResponse(aCommand); + } + + } catch (Throwable t) { + warn("Exception in doCommand(): " + t); + t.printStackTrace(); + } + } + + public String toString() { + return session.toString(); + } + + /** + * Handle heartbeat event. + */ + protected void doHeartbeat(Command aCommand) { + + // Set heartbeat acknowledgement to client + aCommand.setResponseEvent(new Event(E_HEARTBEAT_ACK)); + } + + /** + * Handle Join request. + */ + protected void doJoin(Command aCommand) throws PushletException { + + Event responseEvent = null; + + try { + + session.start(); + + // Determine format for encoding Events to client. + // Default assume a userAgent window on the other end. + String format = aCommand.reqEvent.getField(P_FORMAT, FORMAT_JAVASCRIPT); + + session.setFormat(format); + responseEvent = new Event(E_JOIN_ACK); + + // Set unique subscriber id and encoding format + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_FORMAT, format); + info("joined"); + } catch (Throwable t) { + session.stop(); + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doJoin() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle JoinListen request. + */ + protected void doJoinListen(Command aCommand) throws PushletException { + + // Basically bundles a join and a listen + // This request is handly for simple apps that + // need to do a single request to get events immediately + // For example in RESTful apps. + + // First do regular join + doJoin(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If successful do the listen + doListen(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If still ok do the listen ack + aCommand.getResponseEvent().setField(P_EVENT, E_JOIN_LISTEN_ACK); + } + } + } + + /** + * Handle Leave request. + */ + protected void doLeave(Command aCommand) throws IOException { + + Event responseEvent = null; + + try { + // Also removes all subscriptions + session.stop(); + + // Prepare acknowledgement + responseEvent = new Event(E_LEAVE_ACK); + + // Set unique subscriber id + responseEvent.setField(P_ID, session.getId()); + info("left"); + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doLeave() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle Listen request. + */ + protected void doListen(Command aCommand) throws PushletException { + + + String mode = MODE_STREAM; + // Should we always force "pull" mode ? + if (Config.getBoolProperty(LISTEN_FORCE_PULL_ALL)) { + mode = MODE_PULL; + } else { + // Determine optimal mode determined by parameter and/or user agent + // Mode param determines how events are transfered to the client + + // In "stream" mode, a stream of events is sent, i.e. the document + // is neverending. In "pull" or "poll" mode a complete document is returned + // ending with a request to refresh. + mode = aCommand.reqEvent.getField(P_MODE, MODE_STREAM); + + String userAgent = aCommand.httpReq.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + for (int i = 0; i < session.FORCED_PULL_AGENTS.length; i++) { + if ((userAgent.indexOf(session.FORCED_PULL_AGENTS[i]) != -1)) { + info("Forcing pull mode for agent=" + userAgent); + mode = MODE_PULL; + break; + } + } + } else { + userAgent = "unknown"; + } + } + + getSubscriber().setMode(mode); + + // Prepare acknowledgement + Event listenAckEvent = new Event(E_LISTEN_ACK); + + // Add subscription(s) if subject(s) specified + String subject = aCommand.reqEvent.getField(P_SUBJECT); + if (subject != null) { + // Optional label for subscription + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + + // Add a subscription + Subscription subscription = getSubscriber().addSubscription(subject, label); + + // Add subscription id and optional label to listen-ack event + listenAckEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + listenAckEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + } + + // Set unique subscriber id, push mode and encoding format + listenAckEvent.setField(P_ID, session.getId()); + listenAckEvent.setField(P_MODE, mode); + listenAckEvent.setField(P_FORMAT, session.getFormat()); + + // Activate the subscriber + getSubscriber().start(); + + // Enqueue listen ack event on data channel + aCommand.setResponseEvent(listenAckEvent); + + info("Listening mode=" + mode + " userAgent=" + session.getUserAgent()); + + } + + /** + * Handle Publish request. + */ + protected void doPublish(Command aCommand) { + Event responseEvent = null; + + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + aCommand.reqEvent.setField(P_FROM, session.getId()); + aCommand.reqEvent.setField(P_EVENT, E_DATA); + + // Event may be targeted to specific user (p_to field) + String to = aCommand.reqEvent.getField(P_TO); + if (to != null) { + Dispatcher.getInstance().unicast(aCommand.reqEvent, to); + } else { + // No to: multicast + debug("doPublish() event=" + aCommand.reqEvent); + Dispatcher.getInstance().multicast(aCommand.reqEvent); + } + + // Acknowledge + responseEvent = new Event(E_PUBLISH_ACK); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doPublish() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle refresh event. + */ + protected void doRefresh(Command aCommand) { + // Set ack + aCommand.setResponseEvent(new Event(E_REFRESH_ACK)); + } + + /** + * Handle Subscribe request. + */ + protected void doSubscribe(Command aCommand) throws IOException { + + Event responseEvent = null; + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + Subscription subscription = null; + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + subscription = getSubscriber().addSubscription(subject, label); + + // Acknowledge + responseEvent = new Event(E_SUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBJECT, subject); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + info("subscribed to " + subject + " sid=" + subscription.getId()); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doSubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle Unsubscribe request. + */ + protected void doUnsubscribe(Command aCommand) throws IOException { + + + Event responseEvent = null; + try { + String subscriptionId = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_ID); + if (subscriptionId == null) { + // Unsuscbribe all + getSubscriber().removeSubscriptions(); + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + info("unsubscribed all"); + } else { + // Subscription id provided: remove Subscription + Subscription subscription = getSubscriber().removeSubscription(subscriptionId); + if (subscription == null) { + // Unknown subscription id: return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subscription for sid=" + subscriptionId); + warn("unsubscribe: no subscription for sid=" + subscriptionId); + } else { + // OK return ack + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + responseEvent.setField(P_SUBJECT, subscription.getSubject()); + if (subscription.getLabel() != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + info("unsubscribed sid= " + subscriptionId); + } + } + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doUnsubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + public Subscriber getSubscriber() { + return session.getSubscriber(); + } + + /** + * Send response on the control channel. + */ + protected void sendControlResponse(Command aCommand) { + try { + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + aCommand.getClientAdapter().start(); + + // Push to client through client adapter + aCommand.getClientAdapter().push(aCommand.getResponseEvent()); + + // One shot response + aCommand.getClientAdapter().stop(); + } catch (Throwable t) { + session.stop(); + } + } + + + /** + * Info. + */ + protected void info(String s) { + session.info("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Controller] " + s); + } + + +} + +/* + * $Log: Controller.java,v $ + * Revision 1.9 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.8 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.7 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:00 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Dispatcher.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Dispatcher.java new file mode 100755 index 0000000000..5cd739d5bd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Dispatcher.java @@ -0,0 +1,265 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Routes Events to Subscribers. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Dispatcher.java,v 1.9 2007/12/04 13:55:53 justb Exp $ + */ +public class Dispatcher implements Protocol, ConfigDefs { + /** + * Singleton pattern: single instance. + */ + private static Dispatcher instance; + protected SessionManagerVisitor sessionManagerVisitor; + + static { + try { + instance = (Dispatcher) Config.getClass(DISPATCHER_CLASS, "nl.justobjects.pushlet.core.Dispatcher").newInstance(); + Log.info("Dispatcher created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate Dispatcher from config", t); + } + } + + /** + * Singleton pattern with factory method: protected constructor. + */ + protected Dispatcher() { + + } + + /** + * Singleton pattern: get single instance. + */ + public static Dispatcher getInstance() { + return instance; + } + + /** + * Send event to all subscribers. + */ + public synchronized void broadcast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Object[] args = new Object[2]; + args[1] = anEvent; + Method method = sessionManagerVisitor.getMethod("visitBroadcast"); + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + /** + * Send event to subscribers matching Event subject. + */ + public synchronized void multicast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Method method = sessionManagerVisitor.getMethod("visitMulticast"); + Object[] args = new Object[2]; + args[1] = anEvent; + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + + /** + * Send event to specific subscriber. + */ + public synchronized void unicast(Event event, String aSessionId) { + // Get subscriber to send event to + Session session = SessionManager.getInstance().getSession(aSessionId); + if (session == null) { + Log.warn("unicast: session with id=" + aSessionId + " does not exist"); + return; + } + + // Send Event to subscriber. + session.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Start Dispatcher. + */ + public void start() throws PushletException { + Log.info("Dispatcher started"); + + // Create callback for SessionManager visits. + sessionManagerVisitor = new SessionManagerVisitor(); + } + + /** + * Stop Dispatcher. + */ + public void stop() { + // Send abort control event to all subscribers. + Log.info("Dispatcher stopped: broadcast abort to all subscribers"); + broadcast(new Event(E_ABORT)); + } + + /** + * Supplies Visitor methods for callbacks from SessionManager. + */ + private class SessionManagerVisitor { + private final Map visitorMethods = new HashMap(2); + + SessionManagerVisitor() throws PushletException { + + try { + // Setup Visitor Methods for callback from SessionManager + // This is a slight opitmization over creating Method objects + // on each invokation. + Class[] argsClasses = {Session.class, Event.class}; + visitorMethods.put("visitMulticast", this.getClass().getMethod("visitMulticast", argsClasses)); + visitorMethods.put("visitBroadcast", this.getClass().getMethod("visitBroadcast", argsClasses)); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup SessionManagerVisitor", e); + } + } + + /** + * Return Visitor Method by name. + */ + public Method getMethod(String aName) { + return (Method) visitorMethods.get(aName); + + } + + /** + * Visitor method called by SessionManager. + */ + public void visitBroadcast(Session aSession, Event event) { + aSession.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Visitor method called by SessionManager. + */ + public void visitMulticast(Session aSession, Event event) { + Subscriber subscriber = aSession.getSubscriber(); + Event clonedEvent; + Subscription subscription; + + // Send only if the subscriber's criteria + // match the event. + if ((subscription = subscriber.match(event)) != null) { + // Personalize event + clonedEvent = (Event) event.clone(); + + // Set subscription id and optional label + clonedEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (subscription.getLabel() != null) { + event.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + + subscriber.onEvent(clonedEvent); + } + } + } +} + +/* + * $Log: Dispatcher.java,v $ + * Revision 1.9 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.5 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.4 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.3 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.2 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.1 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.14 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.13 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.12 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.11 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.10 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.9 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.8 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.7 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.6 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.5 2004/03/10 13:59:28 justb + * rewrite using Collection classes and finer synchronization + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 08:54:40 justb + * added getSubscriberCount() and use Log + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Event.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Event.java new file mode 100755 index 0000000000..e9a0aaa48b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Event.java @@ -0,0 +1,184 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Sys; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Represents the event data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Event.java,v 1.13 2007/11/23 14:33:07 justb Exp $ + */ +public class Event implements Protocol, Serializable { + + protected Map attributes = new HashMap(3); + + public Event(String anEventType) { + this(anEventType, null); + } + + public Event(String anEventType, Map theAttributes) { + + if (theAttributes != null) { + setAttrs(theAttributes); + } + + // Set required field event type + setField(P_EVENT, anEventType); + + // Set time in seconds since 1970 + setField(P_TIME, System.currentTimeMillis() / 1000); + } + + public Event(Map theAttributes) { + if (!theAttributes.containsKey(P_EVENT)) { + throw new IllegalArgumentException(P_EVENT + " not found in attributes"); + } + setAttrs(theAttributes); + } + + public static Event createDataEvent(String aSubject) { + return createDataEvent(aSubject, null); + } + + public static Event createDataEvent(String aSubject, Map theAttributes) { + Event dataEvent = new Event(E_DATA, theAttributes); + dataEvent.setField(P_SUBJECT, aSubject); + return dataEvent; + } + + public String getEventType() { + return getField(P_EVENT); + } + + public String getSubject() { + return getField(P_SUBJECT); + } + + public void setField(String name, String value) { + attributes.put(name, value); + } + + public void setField(String name, int value) { + attributes.put(name, value + ""); + } + + public void setField(String name, long value) { + attributes.put(name, value + ""); + } + + public String getField(String name) { + return (String) attributes.get(name); + } + + /** + * Return field; if null return default. + */ + public String getField(String name, String aDefault) { + String result = getField(name); + return result == null ? aDefault : result; + } + + public Iterator getFieldNames() { + return attributes.keySet().iterator(); + } + + public String toString() { + return attributes.toString(); + } + + /** + * Convert to HTTP query string. + */ + public String toQueryString() { + String queryString = ""; + String amp = ""; + for (Iterator iter = getFieldNames(); iter.hasNext();) { + String nextAttrName = (String) iter.next(); + String nextAttrValue = getField(nextAttrName); + queryString = queryString + amp + nextAttrName + "=" + nextAttrValue; + // After first add "&". + amp = "&"; + } + + return queryString; + } + + public String toXML(boolean strict) { + String xmlString = " +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.*; +import java.util.HashMap; + +/** + * Parses XML into Event objects. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventParser.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventParser { + + + private EventParser() { + } + + /** + * Parse Event from a File. + */ + public static Event parse(File aFile) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(aFile)); + return parse(br); + } + + /** + * Parse Event from input Reader. + */ + public static Event parse(Reader aReader) throws IOException { + StringBuffer preparsedString = new StringBuffer(24); + + // First find the opening tag ('<') + char nextChar; + while ((nextChar = (char) aReader.read()) != '<') ; + + // Append '<' + preparsedString.append(nextChar); + + // Then find end-tag ('>'), appending all chars to preparsed string. + do { + nextChar = (char) aReader.read(); + preparsedString.append(nextChar); + } while (nextChar != '>'); + + return parse(preparsedString.toString()); + } + + /** + * Parse Event from a String. + */ + public static Event parse(String aString) throws IOException { + aString = aString.trim(); + + if (!aString.startsWith("<") || !aString.endsWith("/>")) { + throw new IOException("No start or end tag found while parsing event [" + aString + "]"); + } + + // Create the attributes object. + HashMap properties = new HashMap(3); + + // Remove the start and end (< ... />) from the string + aString = aString.substring(1, aString.length() - 2).trim(); + + int index = 0; + + // Parse the tag + while (!Character.isWhitespace(aString.charAt(index)) + && (index < aString.length())) { + index++; + } + + // We don't use the tag: remove from string + aString = aString.substring(index).trim(); + index = 0; + + String attrName; + String attrValue; + + while (index < aString.length()) { + + // Parse attribute name + while ((aString.charAt(index) != '=') + && (index < aString.length())) { + index++; + } + + // Create attr name string + attrName = aString.substring(0, index).trim(); + + // remove the attributeName and the '=' from the string + aString = aString.substring(index + 1).trim(); + index = 1; // read past the first wrapping "\"" + + // Parse attribute value + while ((aString.charAt(index) != '\"') + && (index < aString.length())) { + + // bypass the special characters '\' and '"' inside the + // attributevalue itself which are deliniated with a preceding + // '\' + if (aString.charAt(index) == '\\') { + aString = aString.substring(0, index) + + aString.substring(index + 1); // remove the '\' + } + + index++; + } + + // create the attribute value; exclude the wrapping quote-characters + attrValue = aString.substring(1, index); + + // Set the attribute N/V + properties.put(attrName, attrValue); + + aString = aString.substring(index + 1).trim(); + index = 0; + } + + return new Event(properties); + } + + /** + * Test method: use files to test. + */ + public static void main(String[] args) { + try { + Event event = parse(new File(args[0])); + System.out.println("OK parsed Event file " + args[0]); + System.out.println(event.toXML()); + + event = parse(event.toXML()); + System.out.println("OK parsed Event string"); + System.out.println(event.toXML()); + } catch (Throwable t) { + System.out.println("Error parsing event file: " + args[0]); + t.printStackTrace(); + } + } +} + +/* + * $Log: EventParser.java,v $ + * Revision 1.3 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.3 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/05/18 16:12:27 justb + * adding support for XML encoded Events + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventPullSource.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventPullSource.java new file mode 100755 index 0000000000..cf63d98389 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventPullSource.java @@ -0,0 +1,185 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventPullSource.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * ABC for specifc EventPullSources. + */ +abstract public class EventPullSource implements EventSource, Runnable { + private volatile boolean alive = false; + private volatile boolean active = false; + private static int threadNum = 0; + private Thread thread; + + public EventPullSource() { + } + + abstract protected long getSleepTime(); + + abstract protected Event pullEvent(); + + public void start() { + thread = new Thread(this, "EventPullSource-" + (++threadNum)); + thread.setDaemon(true); + thread.start(); + } + + public boolean isAlive() { + return alive; + } + + /** + * Stop the event generator thread. + */ + public void stop() { + alive = false; + + if (thread != null) { + thread.interrupt(); + thread = null; + } + + } + + /** + * Activate the event generator thread. + */ + synchronized public void activate() { + if (active) { + return; + } + active = true; + if (!alive) { + start(); + return; + } + Log.debug(getClass().getName() + ": notifying..."); + notifyAll(); + } + + /** + * Deactivate the event generator thread. + */ + public void passivate() { + if (!active) { + return; + } + active = false; + } + + /** + * Main loop: sleep, generate event and publish. + */ + public void run() { + Log.debug(getClass().getName() + ": starting..."); + alive = true; + while (alive) { + try { + + Thread.sleep(getSleepTime()); + + // Stopped during sleep: end loop. + if (!alive) { + break; + } + + // If passivated wait until we get + // get notify()-ied. If there are no subscribers + // it wasts CPU to remain producing events... + synchronized (this) { + while (!active) { + Log.debug(getClass().getName() + ": waiting..."); + wait(); + } + } + + } catch (InterruptedException e) { + break; + } + + try { + // Derived class should produce an event. + Event event = pullEvent(); + + // Let the publisher push it to subscribers. + Dispatcher.getInstance().multicast(event); + } catch (Throwable t) { + Log.warn("EventPullSource exception while multicasting ", t); + t.printStackTrace(); + } + } + Log.debug(getClass().getName() + ": stopped"); + } +} + +/* + * $Log: EventPullSource.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.13 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.12 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventQueue.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventQueue.java new file mode 100755 index 0000000000..85c730e2d7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventQueue.java @@ -0,0 +1,269 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +/** + * FIFO queue with guarded suspension. + * Purpose
    + *

    + * Implementation
    + * FIFO queue class implemented with circular array. The enQueue() and + * deQueue() methods use guarded suspension according to a readers/writers + * pattern, implemented with java.lang.Object.wait()/notify(). + *

    + * Examples
    + *

    + *
    + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventQueue.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventQueue { + /** + * Defines maximum queue size + */ + private int capacity = 8; + private Event[] queue = null; + private int front, rear; + + /** + * Construct queue with default (8) capacity. + */ + public EventQueue() { + this(8); + } + + /** + * Construct queue with specified capacity. + */ + public EventQueue(int capacity) { + this.capacity = capacity; + queue = new Event[capacity]; + front = rear = 0; + } + + /** + * Put item in queue; waits() indefinitely if queue is full. + */ + public synchronized boolean enQueue(Event item) throws InterruptedException { + return enQueue(item, -1); + } + + /** + * Put item in queue; if full wait maxtime. + */ + public synchronized boolean enQueue(Event item, long maxWaitTime) throws InterruptedException { + + // Wait (optional maxtime) as long as the queue is full + while (isFull()) { + if (maxWaitTime > 0) { + // Wait at most maximum time + wait(maxWaitTime); + + // Timed out or woken; if still full we + // had bad luck and return failure. + if (isFull()) { + return false; + } + } else { + wait(); + } + } + + // Put item in queue + queue[rear] = item; + rear = next(rear); + + // Wake up waiters; NOTE: first waiter will eat item + notifyAll(); + return true; + } + + /** + * Get head; if empty wait until something in queue. + */ + public synchronized Event deQueue() throws InterruptedException { + return deQueue(-1); + } + + /** + * Get head; if empty wait for specified time at max. + */ + public synchronized Event deQueue(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue item + Event result = fetchNext(); + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return result; + } + + /** + * Get all queued Events. + */ + public synchronized Event[] deQueueAll(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue all items item + Event[] events = new Event[getSize()]; + for (int i = 0; i < events.length; i++) { + events[i] = fetchNext(); + } + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return events; + } + + public synchronized int getSize() { + return (rear >= front) ? (rear - front) : (capacity - front + rear); + } + + /** + * Is the queue empty ? + */ + public synchronized boolean isEmpty() { + return front == rear; + } + + /** + * Is the queue full ? + */ + public synchronized boolean isFull() { + return (next(rear) == front); + } + + /** + * Circular counter. + */ + private int next(int index) { + return (index + 1 < capacity ? index + 1 : 0); + } + + /** + * Circular counter. + */ + private Event fetchNext() { + Event temp = queue[front]; + queue[front] = null; + front = next(front); + return temp; + } + + public static void p(String s) { + System.out.println(s); + } + + public static void main(String[] args) { + EventQueue q = new EventQueue(8); + Event event = new Event("t"); + try { + q.enQueue(event); + p("(1) size = " + q.getSize()); + q.enQueue(event); + p("(2) size = " + q.getSize()); + q.deQueue(); + p("(1) size = " + q.getSize()); + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(3) size = " + q.getSize()); + q.deQueue(); + p("(2) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + p("(7) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + p("(4) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(1) size = " + q.getSize()); + } catch (InterruptedException ie) { + } + } +} + +/* +* $Log: EventQueue.java,v $ +* Revision 1.3 2007/11/23 14:33:07 justb +* core classes now configurable through factory +* +* Revision 1.2 2005/02/21 11:50:46 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.6 2005/02/16 12:16:16 justb +* added support for "poll" mode +* +* Revision 1.5 2005/01/13 14:47:15 justb +* control evt: send response on same (control) connection +* +* Revision 1.4 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSource.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSource.java new file mode 100755 index 0000000000..1de0c4a985 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSource.java @@ -0,0 +1,79 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import javax.servlet.ServletContext; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventSource.java,v 1.7 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * Interface for specifc Event(Pull/Push)Sources. + */ +public interface EventSource { + /** + * Activate the event source. + */ + public void activate(); + + /** + * Deactivate the event source. + */ + public void passivate(); + + /** + * Halt the event source. + */ + public void stop(); + + /** + * @author thomas genin + * gives access to the servlet context of pushlet to the source class + */ + public void setServletContext(ServletContext srvCtxt); + +} + +/* + * $Log: EventSource.java,v $ + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSourceManager.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSourceManager.java new file mode 100755 index 0000000000..472b4290cc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/EventSourceManager.java @@ -0,0 +1,175 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; +import java.io.File; + +import javax.servlet.ServletContext; + +/** + * Maintains lifecycle of event sources. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventSourceManager.java,v 1.14 2007/11/10 13:44:02 justb Exp $ + */ +public class EventSourceManager { + private static Vector eventSources = new Vector(0); + private static final String PROPERTIES_FILE = "sources.properties"; + + /** + * Initialize event sources from properties file. + */ + public static void start(String aDirPath,ServletContext srvCtxt) { + // Load Event sources using properties file. + Log.info("EventSourceManager: start"); + + Properties properties = null; + + try { + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("EventSourceManager: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("EventSourceManager: cannot load properties file from " + filePath, t); + + // Give up + Log.warn("EventSourceManager: not starting local event sources (maybe that is what you want)"); + return; + } + } + + // Create event source collection + eventSources = new Vector(properties.size()); + + // Add the configured sources + for (Enumeration e = properties.keys(); e.hasMoreElements();) { + String nextKey = (String) e.nextElement(); + String nextClass = properties.getProperty(nextKey); + EventSource nextEventSource = null; + try { + nextEventSource = (EventSource) Class.forName(nextClass).newInstance(); + //rajout thomas genin + nextEventSource.setServletContext(srvCtxt); + ////////////////////// + Log.info("created EventSource: key=" + nextKey + " class=" + nextClass); + eventSources.addElement(nextEventSource); + + } catch (Exception ex) { + Log.warn("Cannot create EventSource: class=" + nextClass, ex); + } + } + + activate(); + } + + /** + * Activate all event sources. + */ + public static void activate() { + Log.info("Activating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).activate(); + } + Log.info("EventSources activated"); + } + + /** + * Deactivate all event sources. + */ + public static void passivate() { + Log.info("Passivating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).passivate(); + } + Log.info("EventSources passivated"); + } + + /** + * Halt event sources. + */ + public static void stop() { + Log.info("Stopping " + eventSources.size() + " EventSources..."); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).stop(); + } + Log.info("EventSources stopped"); + } + +} + +/* + * $Log: EventSourceManager.java,v $ + * Revision 1.14 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.13 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.12 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/15 13:29:49 justb + * use Sys.loadPropertiesResource() + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:41:35 justb + * replace static initalizer with explicit init() + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/10/30 14:15:47 just + * no message + * + * Revision 1.3 2000/08/31 08:26:54 just + * Changed classloader that loads eventsources.properties to use EventSourceManager's classloader + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Protocol.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Protocol.java new file mode 100755 index 0000000000..79c265f62f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Protocol.java @@ -0,0 +1,294 @@ +// Copyright (c) 2004 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Constants for Pushlet protocols. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Protocol.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + */ +public interface Protocol { + /** + * Default URI . + */ + public static final String DEFAULT_SERVLET_URI = "/pushlet/pushlet.srv"; + + // + // Common protocol header/parameter names + // + + /** + * Event type (join, leave, data, subscribe etc) . + */ + public static final String P_EVENT = "p_event"; + + /** + * Time in seconds since 1970 + */ + public static final String P_TIME = "p_time"; + + /** + * Event sequence number, numbers per-client. + */ + public static final String P_SEQ = "p_seq"; + + /** + * Subject (topic) of data event. + */ + public static final String P_SUBJECT = "p_subject"; + + /** + * Originator of Event. + */ + public static final String P_FROM = "p_from"; + + /** + * Addressee of Event, subject or client p_id. + */ + public static final String P_TO = "p_to"; + + /** + * Identifier for client instance within server. + */ + public static final String P_ID = "p_id"; + + /** + * Subscription id, identifies single subscription. + */ + public static final String P_SUBSCRIPTION_ID = "p_sid"; + + /** + * Format to receive events + */ + public static final String P_FORMAT = "p_format"; + + /** + * Protocol mode. + */ + public static final String P_MODE = "p_mode"; + + /** + * Reason for errors. + */ + public static final String P_REASON = "p_reason"; + + /** + * URL attribute. + */ + public static final String P_URL = "p_url"; + + /** + * Wait attribute. + */ + public static final String P_WAIT = "p_wait"; + + /** + * Subscription label, may be used to return user-specific + * token with a data event, e.g. the name of a function for a callback. + */ + public static final String P_SUBSCRIPTION_LABEL = "p_label"; + + // + // Event values with direction for P_EVENT (C=client, S=server) + // + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN = "join"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_ACK = "join-ack"; + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN_LISTEN = "join-listen"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_LISTEN_ACK = "join-listen-ack"; + + /** + * C-->S Client starts listening. + */ + public static final String E_LISTEN = "listen"; + + /** + * S-->C Ack of listen. + */ + public static final String E_LISTEN_ACK = "listen-ack"; + + /** + * C-->S Client leaves server. + */ + public static final String E_LEAVE = "leave"; + + /** + * S-->C Ack of leave. + */ + public static final String E_LEAVE_ACK = "leave-ack"; + + /** + * C-->S Publish to subject. + */ + public static final String E_PUBLISH = "publish"; + + /** + * S-->C Publish to subject acknowledge. + */ + public static final String E_PUBLISH_ACK = "publish-ack"; + + /** + * C-->S Subscribe to subject request. + */ + public static final String E_SUBSCRIBE = "subscribe"; + + /** + * S-->C Subscribe to subject acknowledge. + */ + public static final String E_SUBSCRIBE_ACK = "subscribe-ack"; + + /** + * C-->S Unsubscribe from subject request. + */ + public static final String E_UNSUBSCRIBE = "unsubscribe"; + + /** + * S--C Unsubscribe from subject acknowledge. + */ + public static final String E_UNSUBSCRIBE_ACK = "unsubscribe-ack"; + + /** + * S-->C Client error response, transitional error. + */ + public static final String E_NACK = "nack"; + + /** + * S-->C Client should abort, permanent error. + */ + public static final String E_ABORT = "abort"; + + /** + * S-->C Data. + */ + public static final String E_DATA = "data"; + + /** + * S-->C or C-->S Heartbeat. + */ + public static final String E_HEARTBEAT = "hb"; + + /** + * S-->C S-->C or C-->S Heartbeat confirmed. + */ + public static final String E_HEARTBEAT_ACK = "hb-ack"; + + /** + * S-->C or C-->S client refresh of data channel. + */ + public static final String E_REFRESH = "refresh"; + + /** + * S-->C client should refresh data channel. + */ + public static final String E_REFRESH_ACK = "refresh-ack"; + + // + // Values for P_FORMAT parameter + // + + /** + * JavaScript callback. + */ + public static String FORMAT_JAVASCRIPT = "js"; + + /** + * Java serialized object. + */ + public static String FORMAT_SERIALIZED_JAVA_OBJECT = "ser"; + + /** + * Stream of XML documents. + */ + public static String FORMAT_XML = "xml"; + + /** + * Single XML document containing zero or more events. + */ + public static String FORMAT_XML_STRICT = "xml-strict"; + + // + // Values for P_MODE parameter + // + public static final String MODE_STREAM = "stream"; + public static final String MODE_PULL = "pull"; + public static final String MODE_POLL = "poll"; + + // + // Values for special/reserved subjects + // TODO: use these to publish events when clients do these actions + // TODO: Dispatcher may intercept these subjects to send cached events + // + public static final String SUBJECT_META = "/meta"; + public static final String SUBJECT_META_SUBS = SUBJECT_META + "/subs"; + public static final String SUBJECT_META_JOINS = SUBJECT_META + "/joins"; + + +} + +/* + * $Log: Protocol.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.13 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.12 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.11 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.10 2005/02/16 12:16:17 justb + * added support for "poll" mode + * + * Revision 1.9 2005/01/24 22:46:02 justb + * getting safari to work + * + * Revision 1.8 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.7 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.6 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.5 2004/10/24 13:52:52 justb + * small fixes in client lib + * + * Revision 1.4 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.3 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/09/03 21:02:20 justb + * make more formalized protocol + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SerializedAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SerializedAdapter.java new file mode 100755 index 0000000000..462a4dd5c2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SerializedAdapter.java @@ -0,0 +1,99 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.ObjectOutputStream; + +/** + * Implementation of ClientAdapter that sends Events as serialized objects. + *

    + * NOTE: You are discouraged to use this adapter, since it is Java-only + * and may have JVM-specific problems. Far better choice is to use XML + * and the XMLAdapter. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SerializedAdapter.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +class SerializedAdapter implements ClientAdapter { + private ObjectOutputStream out = null; + public static final String CONTENT_TYPE = "application/x-java-serialized-object"; + private HttpServletResponse servletRsp; + + /** + * Initialize. + */ + public SerializedAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + public void start() throws IOException { + + servletRsp.setContentType(CONTENT_TYPE); + + // Use a serialized object output stream + out = new ObjectOutputStream(servletRsp.getOutputStream()); + + // Don't need this further + servletRsp = null; + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + out.writeObject(anEvent); + + out.flush(); + } + + + public void stop() throws IOException { + } +} + +/* + * $Log: SerializedAdapter.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:13:48 justb + * fixed blocking for java.net.URL with HTTP/1.1 (JVMs > 1.1) + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Session.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Session.java new file mode 100755 index 0000000000..8adf9ba6f4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Session.java @@ -0,0 +1,205 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +/** + * Represents client pushlet session state. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Session.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public class Session implements Protocol, ConfigDefs { + private Controller controller; + private Subscriber subscriber; + + private String userAgent; + private long LEASE_TIME_MILLIS = Config.getLongProperty(SESSION_TIMEOUT_MINS) * 60 * 1000; + private volatile long timeToLive = LEASE_TIME_MILLIS; + + public static String[] FORCED_PULL_AGENTS = Config.getProperty(LISTEN_FORCE_PULL_AGENTS).split(","); + + private String address = "unknown"; + private String format = FORMAT_XML; + + private String id; + + /** + * Protected constructor as we create through factory method. + */ + protected Session() { + } + + /** + * Create instance through factory method. + * + * @param anId a session id + * @return a Session object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Session create(String anId) throws PushletException { + Session session; + try { + session = (Session) Config.getClass(SESSION_CLASS, "nl.justobjects.pushlet.core.Session").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Session from config", t); + } + + // Init session + session.id = anId; + session.controller = Controller.create(session); + session.subscriber = Subscriber.create(session); + return session; + } + + /** + * Return (remote) Subscriber client's IP address. + */ + public String getAddress() { + return address; + } + + /** + * Return command controller. + */ + public Controller getController() { + return controller; + } + + /** + * Return Event format to send to client. + */ + public String getFormat() { + return format; + } + + /** + * Return (remote) Subscriber client's unique id. + */ + public String getId() { + return id; + } + + /** + * Return subscriber. + */ + public Subscriber getSubscriber() { + return subscriber; + } + + /** + * Return remote HTTP User-Agent. + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Set address. + */ + protected void setAddress(String anAddress) { + address = anAddress; + } + + /** + * Set event format to encode. + */ + protected void setFormat(String aFormat) { + format = aFormat; + } + + /** + * Set client HTTP UserAgent. + */ + public void setUserAgent(String aUserAgent) { + userAgent = aUserAgent; + } + + /** + * Decrease time to live. + */ + public void age(long aDeltaMillis) { + timeToLive -= aDeltaMillis; + } + + /** + * Has session timed out? + */ + public boolean isExpired() { + return timeToLive <= 0; + } + + /** + * Keep alive by resetting TTL. + */ + public void kick() { + timeToLive = LEASE_TIME_MILLIS; + } + + public void start() { + SessionManager.getInstance().addSession(this); + } + + public void stop() { + subscriber.stop(); + SessionManager.getInstance().removeSession(this); + } + + /** + * Info. + */ + public void info(String s) { + Log.info("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void warn(String s) { + Log.warn("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void debug(String s) { + Log.debug("S-" + this + ": " + s); + } + + public String toString() { + return getAddress() + "[" + getId() + "]"; + } +} + +/* + * $Log: Session.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SessionManager.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SessionManager.java new file mode 100755 index 0000000000..7d3441dc7b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/SessionManager.java @@ -0,0 +1,386 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.rmi.server.UID; +import java.util.*; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * Manages lifecycle of Sessions. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SessionManager.java,v 1.12 2007/12/04 13:55:53 justb Exp $ + */ +public class SessionManager implements ConfigDefs { + + /** + * Singleton pattern: single instance. + */ + private static SessionManager instance; + + static { + // Singleton + factory pattern: create single instance + // from configured class name + try { + instance = (SessionManager) Config.getClass(SESSION_MANAGER_CLASS, "nl.justobjects.pushlet.core.SessionManager").newInstance(); + Log.info("SessionManager created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate SessionManager from config", t); + } + } + + /** + * Timer to schedule session leasing TimerTasks. + */ + private Timer timer; + private final long TIMER_INTERVAL_MILLIS = 60000; + + /** + * Map of active sessions, keyed by their id, all access is through mutex. + */ + private Map sessions = new HashMap(13); + + /** + * Cache of Sessions for iteration and to allow concurrent modification. + */ + private Session[] sessionCache = new Session[0]; + + /** + * State of SessionCache, becomes true whenever sessionCache out of sync with sessions Map. + */ + private boolean sessionCacheDirty = false; + + /** + * Lock for any operation on Sessions (Session Map and/or -cache). + */ + private final Object mutex = new Object(); + + /** + * Singleton pattern: protected constructor needed for derived classes. + */ + protected SessionManager() { + } + + /** + * Visitor pattern implementation for Session iteration. + *

    + * This method can be used to iterate over all Sessions in a threadsafe way. + * See Dispatcher.multicast and broadcast methods for examples. + * + * @param visitor the object that should implement method parm + * @param method the method to be called from visitor + * @param args arguments to be passed in visit method, args[0] will always be Session object + */ + public void apply(Object visitor, Method method, Object[] args) { + + synchronized (mutex) { + + // Refresh Session cache if required + // We use a cache for two reasons: + // 1. to prevent concurrent modification from within visitor method + // 2. some optimization (vs setting up Iterator for each apply() + if (sessionCacheDirty) { + // Clear out existing cache + for (int i = 0; i < sessionCache.length; i++) { + sessionCache[i] = null; + } + + // Refill cache and update state + sessionCache = (Session[]) sessions.values().toArray(sessionCache); + sessionCacheDirty = false; + } + + // Valid session cache: loop and call supplied Visitor method + Session nextSession; + for (int i = 0; i < sessionCache.length; i++) { + nextSession = sessionCache[i]; + + // Session cache may not be entirely filled + if (nextSession == null) { + break; + } + + try { + // First argument is always a Session object + args[0] = nextSession; + + // Use Java reflection to call the method passed by the Visitor + method.invoke(visitor, args); + } catch (IllegalAccessException e) { + Log.warn("apply: illegal method access: ", e); + } catch (InvocationTargetException e) { + Log.warn("apply: method invoke: ", e); + } + } + } + } + + /** + * Create new Session (but add later). + */ + public Session createSession(Event anEvent) throws PushletException { + // Trivial + return Session.create(createSessionId()); + } + + + /** + * Singleton pattern: get single instance. + */ + public static SessionManager getInstance() { + return instance; + } + + /** + * Get Session by session id. + */ + public Session getSession(String anId) { + synchronized (mutex) { + return (Session) sessions.get(anId); + } + } + + /** + * Get copy of listening Sessions. + */ + public Session[] getSessions() { + synchronized (mutex) { + return (Session[]) sessions.values().toArray(new Session[0]); + } + } + + /** + * Get number of listening Sessions. + */ + public int getSessionCount() { + synchronized (mutex) { + return sessions.size(); + } + } + + /** + * Get status info. + */ + public String getStatus() { + Session[] sessions = getSessions(); + StringBuffer statusBuffer = new StringBuffer(); + statusBuffer.append("SessionMgr: " + sessions.length + " sessions \\n"); + for (int i = 0; i < sessions.length; i++) { + statusBuffer.append(sessions[i] + "\\n"); + } + return statusBuffer.toString(); + } + + /** + * Is Session present?. + */ + public boolean hasSession(String anId) { + synchronized (mutex) { + return sessions.containsKey(anId); + } + } + + /** + * Add session. + */ + public void addSession(Session session) { + synchronized (mutex) { + sessions.put(session.getId(), session); + sessionCacheDirty = true; + } + // log(session.getId() + " at " + session.getAddress() + " adding "); + info(session.getId() + " at " + session.getAddress() + " added "); + } + + /** + * Register session for removal. + */ + public Session removeSession(Session aSession) { + synchronized (mutex) { + Session session = (Session) sessions.remove(aSession.getId()); + if (session != null) { + info(session.getId() + " at " + session.getAddress() + " removed "); + } + sessionCacheDirty = true; + return session; + } + } + + + /** + * Starts us. + */ + public void start() throws PushletException { + if (timer != null) { + stop(); + } + timer = new Timer(false); + timer.schedule(new AgingTimerTask(), TIMER_INTERVAL_MILLIS, TIMER_INTERVAL_MILLIS); + info("started; interval=" + TIMER_INTERVAL_MILLIS + "ms"); + } + + /** + * Stopis us. + */ + public void stop() { + if (timer != null) { + timer.cancel(); + timer = null; + } + synchronized (mutex) { + sessions.clear(); + } + info("stopped"); + } + + /** + * Create unique Session id. + */ + protected String createSessionId() { + // Use UUID if specified in config (thanks Uli Romahn) + if (Config.hasProperty(SESSION_ID_GENERATION) && Config.getProperty(SESSION_ID_GENERATION).equals(SESSION_ID_GENERATION_UUID)) { + // We want to be Java 1.4 compatible so use UID class (1.5+ we may use java.util.UUID). + return new UID().toString(); + } + + // Other cases use random name + + // Create a unique session id + // In 99.9999 % of the cases this should be generated at once + // We need the mutext to prevent the chance of creating + // same-valued ids (thanks Uli Romahn) + synchronized (mutex) { + String id; + while (true) { + id = Rand.randomName(Config.getIntProperty(SESSION_ID_SIZE)); + if (!hasSession(id)) { + // Created unique session id + break; + } + } + return id; + } + } + + /** + * Util: stdout printing. + */ + protected void info(String s) { + Log.info("SessionManager: " + new Date() + " " + s); + } + + /** + * Util: stdout printing. + */ + protected void warn(String s) { + Log.warn("SessionManager: " + s); + } + + /** + * Util: stdout printing. + */ + protected void debug(String s) { + Log.debug("SessionManager: " + s); + } + + /** + * Manages Session timeouts. + */ + private class AgingTimerTask extends TimerTask { + private long lastRun = Sys.now(); + private long delta; + private Method visitMethod; + + public AgingTimerTask() throws PushletException { + try { + // Setup Visitor Methods for callback from SessionManager + Class[] argsClasses = {Session.class}; + visitMethod = this.getClass().getMethod("visit", argsClasses); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup AgingTimerTask", e); + } + } + + /** + * Clock tick callback from Timer. + */ + public void run() { + long now = Sys.now(); + delta = now - lastRun; + lastRun = now; + debug("AgingTimerTask: tick"); + + // Use Visitor pattern to loop through Session objects (see visit() below) + getInstance().apply(this, visitMethod, new Object[1]); + } + + /** + * Callback from SessionManager during apply() + */ + public void visit(Session aSession) { + try { + // Age the lease + aSession.age(delta); + debug("AgingTimerTask: visit: " + aSession); + + // Stop session if lease expired + if (aSession.isExpired()) { + info("AgingTimerTask: Session expired: " + aSession); + aSession.stop(); + } + } catch (Throwable t) { + warn("AgingTimerTask: Error in timer task : " + t); + } + } + } +} + +/* + * $Log: SessionManager.java,v $ + * Revision 1.12 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.11 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.10 2007/11/10 14:47:45 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.9 2007/11/10 14:17:18 justb + * minor cosmetic changes just commit now + * + * Revision 1.8 2007/07/02 08:12:16 justb + * redo to original version of session cache (with break, but nullify array first) + * + * Revision 1.7 2007/07/02 07:33:02 justb + * small fix in sessionmgr for holes in sessioncache array (continue i.s.o. break) + * + * Revision 1.6 2006/11/18 12:13:47 justb + * made SessionManager constructor protected to allow constructing derived classes + * + * Revision 1.5 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.4 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.3 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.2 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.1 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscriber.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscriber.java new file mode 100755 index 0000000000..39f5ba0198 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscriber.java @@ -0,0 +1,469 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.net.URLEncoder; + +/** + * Handles data channel between dispatcher and client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscriber.java,v 1.26 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscriber implements Protocol, ConfigDefs { + private Session session; + + /** + * Blocking queue. + */ + private EventQueue eventQueue = new EventQueue(Config.getIntProperty(QUEUE_SIZE)); + + /** + * URL to be used in refresh requests in pull/poll modes. + */ + private long queueReadTimeoutMillis = Config.getLongProperty(QUEUE_READ_TIMEOUT_MILLIS); + private long queueWriteTimeoutMillis = Config.getLongProperty(QUEUE_WRITE_TIMEOUT_MILLIS); + private long refreshTimeoutMillis = Config.getLongProperty(PULL_REFRESH_TIMEOUT_MILLIS); + volatile long lastAlive = Sys.now(); + + /** + * Map of active subscriptions, keyed by their subscription id. + */ + private Map subscriptions = Collections.synchronizedMap(new HashMap(3)); + + /** + * Are we able to accept/send events ?. + */ + private volatile boolean active; + + /** + * Transfer mode (stream, pull, poll). + */ + private String mode; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscriber() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Subscriber object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Subscriber create(Session aSession) throws PushletException { + Subscriber subscriber; + try { + subscriber = (Subscriber) Config.getClass(SUBSCRIBER_CLASS, "nl.justobjects.pushlet.core.Subscriber").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + subscriber.session = aSession; + return subscriber; + } + + public void start() { + active = true; + } + + public void stop() { + removeSubscriptions(); + active = false; + } + + public void bailout() { + session.stop(); + } + + /** + * Are we still active to handle events. + */ + public boolean isActive() { + return active; + } + + /** + * Return client session. + */ + public Session getSession() { + return session; + } + + /** + * Get (session) id. + */ + public String getId() { + return session.getId(); + } + + /** + * Return subscriptions. + */ + public Subscription[] getSubscriptions() { + // todo: Optimize + return (Subscription[]) subscriptions.values().toArray(new Subscription[0]); + } + + /** + * Add a subscription. + */ + public Subscription addSubscription(String aSubject, String aLabel) throws PushletException { + Subscription subscription = Subscription.create(aSubject, aLabel); + subscriptions.put(subscription.getId(), subscription); + info("Subscription added subject=" + aSubject + " sid=" + subscription.getId() + " label=" + aLabel); + return subscription; + } + + /** + * Remove a subscription. + */ + public Subscription removeSubscription(String aSubscriptionId) { + Subscription subscription = (Subscription) subscriptions.remove(aSubscriptionId); + if (subscription == null) { + warn("No subscription found sid=" + aSubscriptionId); + return null; + } + info("Subscription removed subject=" + subscription.getSubject() + " sid=" + subscription.getId() + " label=" + subscription.getLabel()); + return subscription; + } + + /** + * Remove all subscriptions. + */ + public void removeSubscriptions() { + subscriptions.clear(); + } + + public String getMode() { + return mode; + } + + public void setMode(String aMode) { + mode = aMode; + } + + public long getRefreshTimeMillis() { + String minWaitProperty = PULL_REFRESH_WAIT_MIN_MILLIS; + String maxWaitProperty = PULL_REFRESH_WAIT_MAX_MILLIS; + if (mode.equals((MODE_POLL))) { + minWaitProperty = POLL_REFRESH_WAIT_MIN_MILLIS; + maxWaitProperty = POLL_REFRESH_WAIT_MAX_MILLIS; + + } + return Rand.randomLong(Config.getLongProperty(minWaitProperty), + Config.getLongProperty(maxWaitProperty)); + } + + /** + * Get events from queue and push to client. + */ + public void fetchEvents(Command aCommand) throws PushletException { + + String refreshURL = aCommand.httpReq.getRequestURI() + "?" + P_ID + "=" + session.getId() + "&" + P_EVENT + "=" + E_REFRESH; + + // This is the only thing required to support "poll" mode + if (mode.equals(MODE_POLL)) { + queueReadTimeoutMillis = 0; + refreshTimeoutMillis = Config.getLongProperty(POLL_REFRESH_TIMEOUT_MILLIS); + } + + // Required for fast bailout (tomcat) + aCommand.httpRsp.setBufferSize(128); + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + ClientAdapter clientAdapter = aCommand.getClientAdapter(); + Event responseEvent = aCommand.getResponseEvent(); + try { + clientAdapter.start(); + + // Send first event (usually hb-ack or listen-ack) + clientAdapter.push(responseEvent); + + // In pull/poll mode and when response is listen-ack or join-listen-ack, + // return and force refresh immediately + // such that the client recieves response immediately over this channel. + // This is usually when loading the browser app for the first time + if ((mode.equals(MODE_POLL) || mode.equals(MODE_PULL)) + && responseEvent.getEventType().endsWith(Protocol.E_LISTEN_ACK)) { + sendRefresh(clientAdapter, refreshURL); + + // We should come back later with refresh event... + return; + } + } catch (Throwable t) { + bailout(); + return; + } + + + Event[] events = null; + + // Main loop: as long as connected, get events and push to client + long eventSeqNr = 1; + while (isActive()) { + // Indicate we are still alive + lastAlive = Sys.now(); + + // Update session time to live + session.kick(); + + // Get next events; blocks until timeout or entire contents + // of event queue is returned. Note that "poll" mode + // will return immediately when queue is empty. + try { + // Put heartbeat in queue when starting to listen in stream mode + // This speeds up the return of *_LISTEN_ACK + if (mode.equals(MODE_STREAM) && eventSeqNr == 1) { + eventQueue.enQueue(new Event(E_HEARTBEAT)); + } + + events = eventQueue.deQueueAll(queueReadTimeoutMillis); + } catch (InterruptedException ie) { + warn("interrupted"); + bailout(); + } + + // Send heartbeat when no events received + if (events == null) { + events = new Event[1]; + events[0] = new Event(E_HEARTBEAT); + } + + // ASSERT: one or more events available + + // Send events to client using adapter + // debug("received event count=" + events.length); + for (int i = 0; i < events.length; i++) { + // Check for abort event + if (events[i].getEventType().equals(E_ABORT)) { + warn("Aborting Subscriber"); + bailout(); + } + + // Push next Event to client + try { + // Set sequence number + events[i].setField(P_SEQ, eventSeqNr++); + + // Push to client through client adapter + clientAdapter.push(events[i]); + } catch (Throwable t) { + bailout(); + return; + } + } + + // Force client refresh request in pull or poll modes + if (mode.equals(MODE_PULL) || mode.equals(MODE_POLL)) { + sendRefresh(clientAdapter, refreshURL); + + // Always leave loop in pull/poll mode + break; + } + } + } + + /** + * Determine if we should receive event. + */ + public Subscription match(Event event) { + Subscription[] subscriptions = getSubscriptions(); + for (int i = 0; i < subscriptions.length; i++) { + if (subscriptions[i].match(event)) { + return subscriptions[i]; + } + } + return null; + } + + /** + * Event from Dispatcher: enqueue it. + */ + public void onEvent(Event theEvent) { + if (!isActive()) { + return; + } + + // p("send: queue event: "+theEvent.getSubject()); + + // Check if we had any active continuation for at + // least 'timeOut' millisecs. If the client has left this + // instance there would be no way of knowing otherwise. + long now = Sys.now(); + if (now - lastAlive > refreshTimeoutMillis) { + warn("not alive for at least: " + refreshTimeoutMillis + "ms, leaving..."); + bailout(); + return; + } + + // Put event in queue; leave if queue full + try { + if (!eventQueue.enQueue(theEvent, queueWriteTimeoutMillis)) { + warn("queue full, bailing out..."); + bailout(); + } + + // ASSERTION : Event in queue. + // see fetchEvents() where Events are dequeued and pushed to the client. + } catch (InterruptedException ie) { + bailout(); + } + + } + + /** + * Send refresh command to pull/poll clients. + */ + protected void sendRefresh(ClientAdapter aClientAdapter, String aRefreshURL) { + Event refreshEvent = new Event(E_REFRESH); + + // Set wait time and url for refresh + refreshEvent.setField(P_WAIT, "" + getRefreshTimeMillis()); + refreshEvent.setField(P_URL, aRefreshURL); + + try { + // Push to client through client adapter + aClientAdapter.push(refreshEvent); + + // Stop this round until refresh event + aClientAdapter.stop(); + } catch (Throwable t) { + // Leave on any exception + bailout(); + } + } + + /** + * Info. + */ + protected void info(String s) { + session.info("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Subscriber] " + s); + } + + + public String toString() { + return session.toString(); + } +} + +/* + * $Log: Subscriber.java,v $ + * Revision 1.26 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.25 2007/11/10 15:53:15 justb + * put heartbeat in queue when start fetching events in stream-mode + * + * Revision 1.24 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.22 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.21 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.20 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + * Revision 1.19 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.18 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.17 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.16 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.15 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.14 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.13 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.12 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.11 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.10 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.7 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.6 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscription.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscription.java new file mode 100755 index 0000000000..c6f88bd597 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/Subscription.java @@ -0,0 +1,133 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.PushletException; + + +/** + * Represents single subject subscription + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscription.java,v 1.5 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscription implements ConfigDefs { + public static final int ID_SIZE = 5; + public static final String SUBJECT_SEPARATOR = ","; + private String id = Rand.randomName(ID_SIZE); + private String subject; + private String[] subjects; + + /** + * Optional label, a user supplied token. + */ + private String label; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscription() { + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject) throws PushletException { + return create(aSubject, null); + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @param aLabel the subject label (optional). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject, String aLabel) throws PushletException { + if (aSubject == null || aSubject.length() == 0) { + throw new IllegalArgumentException("Null or emtpy subject"); + } + + Subscription subscription; + try { + subscription = (Subscription) Config.getClass(SUBSCRIPTION_CLASS, "nl.justobjects.pushlet.core.Subscription").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + // Init + subscription.subject = aSubject; + + // We may subscribe to multiple subjects by separating + // them with SUBJECT_SEPARATOR, e.g. "/stocks/aex,/system/memory,.."). + subscription.subjects = aSubject.split(SUBJECT_SEPARATOR); + + subscription.label = aLabel; + return subscription; + } + + + public String getId() { + return id; + } + + public String getLabel() { + return label; + } + + public String getSubject() { + return subject; + } + + /** + * Determine if Event matches subscription. + */ + public boolean match(Event event) { + String eventSubject = event.getSubject(); + + // Silly case but check anyway + if (eventSubject == null || eventSubject.length() == 0) { + return false; + } + + // Test if one of the subjects matches + for (int i = 0; i < subjects.length; i++) { + if (eventSubject.startsWith(subjects[i])) { + return true; + } + } + + // No match + return false; + } +} + +/* + * $Log: Subscription.java,v $ + * Revision 1.5 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/16 15:23:10 justb + * multiple subject (, separated) support + * + * Revision 1.2 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.1 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/XMLAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/XMLAdapter.java new file mode 100755 index 0000000000..15d7096e59 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/core/XMLAdapter.java @@ -0,0 +1,137 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * ClientAdapter that sends Events as XML. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: XMLAdapter.java,v 1.7 2007/11/09 13:15:35 justb Exp $ + */ +class XMLAdapter implements ClientAdapter { + /** + * Header for strict XML + */ + // public static final String XML_HEAD = "\n"; + private String contentType = "text/plain;charset=UTF-8"; + private ServletOutputStream out = null; + private HttpServletResponse servletRsp; + private boolean strictXML; + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse) { + this(aServletResponse, false); + } + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse, boolean useStrictXML) { + servletRsp = aServletResponse; + + // Strict XML implies returning a complete XML document + strictXML = useStrictXML; + if (strictXML) { + contentType = "text/xml;charset=UTF-8"; + } + } + + public void start() throws IOException { + + // If content type is plain text + // then this is not a complete XML document, but rather + // a stream of XML documents where each document is + // an Event. In strict XML mode a complete document is returned. + servletRsp.setContentType(contentType); + + out = servletRsp.getOutputStream(); + + // Don't need this further + servletRsp = null; + + // Start XML document if strict XML mode + if (strictXML) { + out.print(""); + } + } + + /** + * Force client to refresh the request. + */ + public void push(Event anEvent) throws IOException { + debug("event=" + anEvent); + + // Send the event as XML to the client and flush. + out.print(anEvent.toXML(strictXML)); + out.flush(); + } + + /** + * No action. + */ + public void stop() throws IOException { + // Close XML document if strict XML mode + if (strictXML) { + out.print(""); + out.flush(); + } + } + + private void debug(String s) { + Log.debug("[XMLAdapter]" + s); + } +} + +/* + * $Log: XMLAdapter.java,v $ + * Revision 1.7 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.6 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.5 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.4 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.5 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.4 2003/08/13 14:00:00 justb + * some testing for applets; no real change + * + * Revision 1.3 2003/08/12 09:57:06 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/19 21:56:29 justb + * various fixes for applet clients + * + * Revision 1.1 2003/05/18 16:12:28 justb + * adding support for XML encoded Events + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/servlet/Pushlet.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/servlet/Pushlet.java new file mode 100755 index 0000000000..333fbe8302 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/servlet/Pushlet.java @@ -0,0 +1,294 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.servlet; + +import nl.justobjects.pushlet.core.*; +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Servlets; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.Version; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Enumeration; + +/** + * Servlet runs a Subscriber per request. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Pushlet.java,v 1.23 2007/12/04 13:55:53 justb Exp $ + */ +public class Pushlet extends HttpServlet implements Protocol { + + public void init() throws ServletException { + try { + System.out.println("initiating pushlet servlet..."); + // Load configuration (from classpath or WEB-INF root path) + String webInfPath = getServletContext().getRealPath("/") + "/WEB-INF"; + Config.load(webInfPath); + + Log.init(); + + // Start + Log.info("init() Pushlet Webapp - version=" + Version.SOFTWARE_VERSION + " built=" + Version.BUILD_DATE); + + // Start session manager + SessionManager.getInstance().start(); + + // Start event Dispatcher + Dispatcher.getInstance().start(); + + System.out.println("pushlet initiates event sources..."); + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + EventSourceManager.start(webInfPath,getServletContext());// changed by thomas genin + } else { + Log.info("Not starting local event sources"); + } + } catch (Throwable t) { + throw new ServletException("Failed to initialize Pushlet framework " + t, t); + } + } + + public void destroy() { + Log.info("destroy(): Exit Pushlet webapp"); + + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + // Stop local event sources + EventSourceManager.stop(); + } else { + Log.info("No local event sources to stop"); + } + + // Should abort all subscribers + Dispatcher.getInstance().stop(); + + // Should stop all sessions + SessionManager.getInstance().stop(); + } + + /** + * Servlet GET request: handles event requests. + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + + try { + // Event parm identifies event type from the client + String eventType = Servlets.getParameter(request, P_EVENT); + + // Always must have an event type + if (eventType == null) { + Log.warn("Pushlet.doGet(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + // Create Event and set attributes from parameters + event = new Event(eventType); + for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) { + String nextAttribute = (String) e.nextElement(); + event.setField(nextAttribute, request.getParameter(nextAttribute)); + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doGet(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Servlet POST request: extracts event data from body. + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + try { + // Create Event by parsing XML from input stream. + event = EventParser.parse(new InputStreamReader(request.getInputStream())); + + // Always must have an event type + if (event.getEventType() == null) { + Log.warn("Pushlet.doPost(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doPost(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Generic request handler (GET+POST). + */ + protected void doRequest(Event anEvent, HttpServletRequest request, HttpServletResponse response) { + // Must have valid event type. + String eventType = anEvent.getEventType(); + try { + + // Get Session: either by creating (on Join eventType) + // or by id (any other eventType, since client is supposed to have joined). + Session session = null; + if (eventType.startsWith(Protocol.E_JOIN)) { + // Join request: create new subscriber + session = SessionManager.getInstance().createSession(anEvent); + + String userAgent = request.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + } else { + userAgent = "unknown"; + } + session.setUserAgent(userAgent); + + } else { + // Must be a request for existing Session + + // Get id + String id = anEvent.getField(P_ID); + + // We must have an id value + if (id == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No id specified"); + Log.warn("Pushlet: bad request, no id specified event=" + eventType); + return; + } + + // We have an id: get the session object + session = SessionManager.getInstance().getSession(id); + + // Check for invalid id + if (session == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid or expired id: " + id); + Log.warn("Pushlet: bad request, no session found id=" + id + " event=" + eventType); + return; + } + } + + // ASSERTION: we have a valid Session + + // Let Controller handle request further + // including exceptions + Command command = Command.create(session, anEvent, request, response); + session.getController().doCommand(command); + } catch (Throwable t) { + // Hmm we should never ever get here + Log.warn("Pushlet: Exception in doRequest() event=" + eventType, t); + t.printStackTrace(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + } +} + +/* + * $Log: Pushlet.java,v $ + * Revision 1.23 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.22 2007/11/24 10:29:36 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.21 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.20 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.19 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.18 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.17 2005/02/28 13:06:01 justb + * introduced join-listen protocol service + * + * Revision 1.16 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.15 2005/02/28 09:14:56 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.14 2005/02/25 15:13:04 justb + * session id generation more robust + * + * Revision 1.13 2005/02/21 17:19:21 justb + * move init()/destroy() to Pushlet servlet + * + * Revision 1.12 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.11 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.7 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.6 2004/09/26 21:39:44 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.5 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2004/08/13 23:36:06 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/13 13:26:57 justb + * moved all servlets to servlet package + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/DefaultLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/DefaultLogger.java new file mode 100755 index 0000000000..bec2d94f34 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/DefaultLogger.java @@ -0,0 +1,164 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Default logger. + *

    + * Logs to stdout. Override this class by setting "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: DefaultLogger.java,v 1.2 2007/12/07 12:57:40 justb Exp $ + */ +public class DefaultLogger implements PushletLogger { + + + /** + * Level intialized with default. + */ + private int level = LOG_LEVEL_INFO; + + public DefaultLogger() { + } + + public void init() { + + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage) { + if (level < LOG_LEVEL_TRACE) { + return; + } + print("TRACE", aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage) { + if (level < LOG_LEVEL_DEBUG) { + return; + } + print("DEBUG", aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage) { + if (level < LOG_LEVEL_INFO) { + return; + } + print("INFO", aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage) { + if (level < LOG_LEVEL_WARN) { + return; + } + print("WARN", aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable) { + warn(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage) { + if (level < LOG_LEVEL_ERROR) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable) { + error(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage) { + if (level < LOG_LEVEL_FATAL) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable) { + fatal(aMessage + " exception=" + aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + public void setLevel(int aLevel) { + level = aLevel; + } + + /** + * Print message. + * + * @param aTag the log type + * @param aMessage the message to be logged + */ + private void print(String aTag, String aMessage) { + // SImple std out e.g. to catalina.out in Tomcat + System.out.println("Pushlet[" + aTag + "] " + aMessage); + } + +} + +/* +* $Log: DefaultLogger.java,v $ +* Revision 1.2 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.1 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log.java new file mode 100755 index 0000000000..3ce40153e7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log.java @@ -0,0 +1,178 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.Config; +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logging wrapper. + *

    + * Provides a hook to direct logging to your own logging library. Override the DefaultLogger class by setting + * "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: Log.java,v 1.5 2007/12/07 12:57:40 justb Exp $ + */ +public class Log implements ConfigDefs { + /** + * Init with default to have at least some logging. + */ + private static PushletLogger logger = new DefaultLogger(); + + /** + * General purpose initialization. + */ + static public void init() { + try { + logger = (PushletLogger) Config.getClass(LOGGER_CLASS, "nl.justobjects.pushlet.util.DefaultLogger").newInstance(); + } catch (Throwable t) { + // Hmmm cannot log this since we don't have a log... + System.out.println("Cannot instantiate Logger from config ex=" + t); + return; + } + + logger.init(); + + // Set log level + logger.setLevel(Config.getIntProperty(Config.LOG_LEVEL)); + + logger.info("Logging intialized logger class=" + logger.getClass()); + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + static public void trace(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + static public void debug(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + static public void info(String aMessage) { + logger.info(aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + static public void warn(String aMessage) { + logger.warn(aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + static public void error(String aMessage) { + logger.error(aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + static public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + static public void setLevel(int aLevel) { + logger.setLevel(aLevel); + } +} + +/* +* $Log: Log.java,v $ +* Revision 1.5 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.4 2007/11/23 21:29:43 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.3 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.2 2005/02/21 11:15:59 justb +* support log levels +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.7 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.6 2004/08/12 13:16:08 justb +* make debug flag false +* +* Revision 1.5 2004/03/10 14:01:55 justb +* formatting and *Subscriber refactoring +* +* Revision 1.4 2003/08/15 09:54:46 justb +* fix javadoc warnings +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* Revision 1.2 2003/08/12 09:42:47 justb +* enhancements +* +* Revision 1.1 2003/08/12 08:46:00 justb +* cvs comment tags added +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log4jLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log4jLogger.java new file mode 100755 index 0000000000..d7ee1df832 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Log4jLogger.java @@ -0,0 +1,134 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +/** + * Logger to use Log4j for logging. + *

    + * Logs using Log4j. + * This class will require a log4j library in the classpath of the Pushlet. + * + * @author Uli Romahn + * @version $Id: Log4jLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public class Log4jLogger implements PushletLogger { + + /** + * Level intialized with default. + */ + private Logger logger = LogManager.getLogger("pushlet"); + + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#init() + */ + public void init() { + setLevel(LOG_LEVEL_INFO); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#debug(java.lang.String) + */ + public void debug(String aMessage) { + if (!logger.isDebugEnabled()) { + return; + } + logger.debug(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String) + */ + public void error(String aMessage) { + logger.error(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String, java.lang.Throwable) + */ + public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String) + */ + public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String, java.lang.Throwable) + */ + public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#info(java.lang.String) + */ + public void info(String aMessage) { + if (!logger.isInfoEnabled()) { + return; + } + logger.info(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#trace(java.lang.String) + */ + public void trace(String aMessage) { + logger.trace(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String) + */ + public void warn(String aMessage) { + logger.warn(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String, java.lang.Throwable) + */ + public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#setLevel(int) + */ + public void setLevel(int aLevel) { + if (aLevel < LOG_LEVEL_FATAL) { + logger.setLevel(Level.OFF); + } else { + switch (aLevel) { + case LOG_LEVEL_FATAL: + logger.setLevel(Level.FATAL); + break; + case LOG_LEVEL_ERROR: + logger.setLevel(Level.ERROR); + break; + case LOG_LEVEL_WARN: + logger.setLevel(Level.WARN); + break; + case LOG_LEVEL_INFO: + logger.setLevel(Level.INFO); + break; + case LOG_LEVEL_DEBUG: + logger.setLevel(Level.DEBUG); + break; + case LOG_LEVEL_TRACE: + logger.setLevel(Level.TRACE); + break; + default: + logger.setLevel(Level.INFO); + } + } + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletException.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletException.java new file mode 100755 index 0000000000..09ecd3176c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletException.java @@ -0,0 +1,41 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Generic exception wrapper. + * + * @author Just van den Broecke + * @version $Id: PushletException.java,v 1.1 2005/02/15 15:14:34 justb Exp $ + */ +public class PushletException extends Exception { + + private PushletException() { + } + + public PushletException(String aMessage, Throwable t) { + super(aMessage + "\n embedded exception=" + t.toString()); + } + + public PushletException(String aMessage) { + super(aMessage); + } + + public PushletException(Throwable t) { + this("PushletException: ", t); + } + + public String toString() { + return "PushletException: " + getMessage(); + } +} + +/* + * $Log: PushletException.java,v $ + * Revision 1.1 2005/02/15 15:14:34 justb + * *** empty log message *** + * + + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletLogger.java new file mode 100755 index 0000000000..c3853369ba --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/PushletLogger.java @@ -0,0 +1,94 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logger interface to allow different logging providers. + *

    + * + * @author Ulrich Romahn + * @version $Id: PushletLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public interface PushletLogger extends ConfigDefs { + + /** + * Method allowing to initialize our logger + */ + public void init(); + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage); + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage); + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage); + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage); + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable); + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage); + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable); + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage); + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable); + + /** + * Set log level + * + * @param aLevel a valid Level from ConfigDefs + */ + public void setLevel(int aLevel); +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Rand.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Rand.java new file mode 100755 index 0000000000..041970941f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Rand.java @@ -0,0 +1,147 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. +package nl.justobjects.pushlet.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.Random; + +/** + * Randomizing routines. + * + * @author Just van den Broecke + * @version $Id: Rand.java,v 1.4 2007/12/07 12:57:40 justb Exp $ + */ +public class Rand { + private static char CHARS[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'v', 'w', 'y', 'z'}; + private static char NON_VOWELS[] = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'z'}; + private static char VOWELS[] = {'a', 'e', 'i', 'o', 'u', 'y'}; + private static Random random = new Random(); + + public static char randomChar() { + return CHARS[randomInt(0, CHARS.length - 1)]; + } + + public static char randomVowel() { + return VOWELS[randomInt(0, VOWELS.length - 1)]; + } + + public static char randomNonVowel() { + return NON_VOWELS[randomInt(0, NON_VOWELS.length - 1)]; + } + + public static File randomTempDir() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oasetest" + File.separator + randomString(12)); + file.mkdirs(); + file.deleteOnExit(); + return file; + } + + public static File randomTempFile() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oase-" + randomString(6)); + file.createNewFile(); + file.deleteOnExit(); + return file; + } + + public static File randomBinaryFile(int aSize) throws Exception { + File file = randomTempFile(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(randomBytes(aSize)); + fos.close(); + return file; + } + + public static File randomTextFile(int aSize) throws Exception { + File file = randomTempFile(); + PrintWriter pw = new PrintWriter(new FileOutputStream(file)); + pw.write(randomString(aSize)); + pw.close(); + return file; + } + + public static byte[] randomBytes(int aSize) { + return randomBlob(aSize); + } + + public static byte[] randomBlob(int aSize) { + byte[] retval = new byte[aSize]; + for (int i = 0; i < retval.length; i++) { + retval[i] = randomByte(); + } + return retval; + } + + public static byte randomByte() { + return (byte) random.nextInt(); + } + + public static double randomDouble() { + return random.nextLong(); + } + + + public static int randomInt() { + return random.nextInt(); + } + + public static int randomInt(int min, int max) { + return (int) ((Math.random() * (double) (max + 1 - min)) + min); + } + + public static long randomLong() { + return random.nextLong(); + } + + public static long randomLong(long min, long max) { + return (long) ((Math.random() * (double) (max + 1L - min)) + min); + } + + public static String randomName(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(i % 2 == 0 ? randomNonVowel() : randomVowel()); + } + return sb.toString(); + } + + public static void randomSleep(long min, long max) { + try { + Thread.sleep(randomLong(min, max)); + } catch (InterruptedException ie) { + + } + } + + public static String randomString(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(randomChar()); + } + return sb.toString(); + } + + public static String randomString() { + return "" + randomLong(); + } + + +} + +/* + * $Log: Rand.java,v $ + * Revision 1.4 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.3 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.2 2004/09/03 22:35:38 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 12:21:27 justb + * *** empty log message *** + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Servlets.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Servlets.java new file mode 100755 index 0000000000..3b0f20c89f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Servlets.java @@ -0,0 +1,67 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Servlet utilities. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Servlets.java,v 1.2 2007/11/23 21:10:17 justb Exp $ + */ +public class Servlets { + + /** + * Get parameter; if not set or empty return null. + */ + public static String getParameter(HttpServletRequest aRequest, String aName) { + return getParameter(aRequest, aName, null); + } + + /** + * Get parameter; if not set or empty return specified default value. + */ + public static String getParameter(HttpServletRequest aRequest, String aName, String aDefault) { + String value = aRequest.getParameter(aName); + if (value == null || value.length() == 0) { + value = aDefault; + } + return value; + } + + /** + * Set HTTP headers to prevent caching. + */ + public static void setNoCacheHeaders(HttpServletResponse aResponse) { + // Set to expire far in the past. + aResponse.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); + + // Set standard HTTP/1.1 no-cache headers. + aResponse.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + + // Set IE extended HTTP/1.1 no-cache headers (use addHeader). + aResponse.addHeader("Cache-Control", "post-check=0, pre-check=0"); + + // Set standard HTTP/1.0 no-cache header. + aResponse.setHeader("Pragma", "no-cache"); + + } + +} + +/* + * $Log: Servlets.java,v $ + * Revision 1.2 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.1 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * + */ + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Sys.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Sys.java new file mode 100755 index 0000000000..2b72ab55e1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/nl/justobjects/pushlet/util/Sys.java @@ -0,0 +1,113 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + + +import java.io.FileInputStream; +import java.io.IOException; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Properties; + +/** + * Utilities that interact with the underlying OS/JVM. + * + * @author Just van den Broecke + * @version $Id: Sys.java,v 1.4 2007/11/10 14:17:18 justb Exp $ + */ +public class Sys { + + /** + * Replace characters having special meaning inside HTML tags + * with their escaped equivalents, using character entities such as '&'. + *

    + *

    The escaped characters are : + *

      + *
    • < + *
    • > + *
    • " + *
    • ' + *
    • \ + *
    • & + *
    + *

    + *

    This method ensures that arbitrary text appearing inside a tag does not "confuse" + * the tag. For example, HREF='Blah.do?Page=1&Sort=ASC' + * does not comply with strict HTML because of the ampersand, and should be changed to + * HREF='Blah.do?Page=1&Sort=ASC'. This is commonly seen in building + * query strings. (In JSTL, the c:url tag performs this task automatically.) + */ + static public String forHTMLTag(String aTagFragment) { + final StringBuffer result = new StringBuffer(); + + final StringCharacterIterator iterator = new StringCharacterIterator(aTagFragment); + char character = iterator.current(); + while (character != CharacterIterator.DONE) { + if (character == '<') { + result.append("<"); + } else if (character == '>') { + result.append(">"); + } else if (character == '\"') { + result.append("""); + } else if (character == '\'') { + result.append("'"); + } else if (character == '\\') { + result.append("\"); + } else if (character == '&') { + result.append("&"); + } else { + //the char is not a special one + //add it to the result as is + result.append(character); + } + character = iterator.next(); + } + return result.toString(); + } + + /** + * Load properties file from classpath. + */ + static public Properties loadPropertiesResource(String aResourcePath) throws IOException { + try { + // Use the class loader that loaded our class. + // This is required where for reasons like security + // multiple class loaders exist, e.g. BEA WebLogic. + // Thanks to Lutz Lennemann 29-aug-2000. + ClassLoader classLoader = Sys.class.getClassLoader(); + + Properties properties = new Properties(); + + // Try loading it. + properties.load(classLoader.getResourceAsStream(aResourcePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties resource from " + aResourcePath); + } + } + + /** + * Load properties file from file path. + */ + static public Properties loadPropertiesFile(String aFilePath) throws IOException { + try { + + Properties properties = new Properties(); + + // Try loading it. + properties.load(new FileInputStream(aFilePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties file from " + aFilePath); + } + } + + /** + * Shorthand for current time. + */ + static public long now() { + return System.currentTimeMillis(); + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/AES.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/AES.java new file mode 100755 index 0000000000..e7bde1e0a7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/AES.java @@ -0,0 +1,190 @@ +package pow; + +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.KeySpec; +//import java.security.spec.KeySpec; + +import javax.crypto.*; +import javax.crypto.spec.*; + +//import org.apache.commons.codec.binary.Hex; + +import java.io.*; + +/** +* implements AES encryption and decryption algorithms +* see @link http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html +* see @link http://stackoverflow.com/questions/992019/java-256bit-aes-encryption +*/ + +public class AES { + + private byte[] key; + private SecretKeySpec skeySpec; + private Cipher cipher_encrypt; + private Cipher cipher_decrypt; + // + /** + * construct a cipher with a generated 128 bits key + * @throws InvalidParameterSpecException + * @throws InvalidAlgorithmParameterException + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + */ + public AES() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, InvalidAlgorithmParameterException { + // Get the KeyGenerator + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + kgen.init(128); // 192 and 256 bits may not be available + // Generate the secret key specs. + SecretKey skey = kgen.generateKey(); + key = skey.getEncoded(); + skeySpec = new SecretKeySpec(key, "AES"); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec); + byte[] iv = cipher_encrypt.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + } + /** + * construct a cipher from an user specified key + * @param password a string representing the user key + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + * @throws InvalidKeyException + * @throws InvalidParameterSpecException + * @throws InvalidAlgorithmParameterException + * @throws InvalidKeySpecException + */ + public AES(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeySpecException { + // autre facon de generer la cle + SecureRandom random = new SecureRandom(); + byte salt[] = new byte[8]; + random.nextBytes(salt); + + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256); + SecretKey tmp = factory.generateSecret(spec); + SecretKey skey = new SecretKeySpec(tmp.getEncoded(), "AES"); + // + key = skey.getEncoded(); + skeySpec = new SecretKeySpec(key, "AES"); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec); + byte[] iv = cipher_encrypt.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + } + /** + * construct a cipher from a key and a parameter array + * usefull to create a remote decryption cypher + * @param key the key in array byte format + * @param iv parameter of the cipher + * @throws InvalidKeyException + * @throws InvalidAlgorithmParameterException + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + */ + public AES(byte[] key,byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException{ + skeySpec = new SecretKeySpec(key, "AES"); + key = skeySpec.getEncoded(); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv)); + } + /** + * get the init parameter of the cipher object in order to initialyse correctly a + * remote cipher + */ + public byte[] getParamsEncrypt() throws InvalidParameterSpecException{ + AlgorithmParameters params = cipher_encrypt.getParameters(); + byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); + return iv; + } + /** + * get the cipher key + * @return the cipher key in byte array + */ + public byte[] getKey(){return key;} + +/** + * encrypt a byte array with AES algorithm + * @see org.apache.commons.codec.binary.Hex to convert byte Array into hexString + * @param msg + * @return a byte array containing the ciphered data + * @throws IOException + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + public byte[] encrypt(byte[] msg) throws IOException, IllegalBlockSizeException, BadPaddingException{ + ByteArrayInputStream in= new ByteArrayInputStream(msg); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + crypt(in, out, cipher_encrypt); + return out.toByteArray(); + } + /** + * decrypt a byte array with AES algorithm + * see @link org.apache.commons.codec.binary.Hex to convert byte Array into hexString + * @param msg the msg to decrypt + * @return the message decrypted + * @throws IOException + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + public byte[] decrypt(byte[] msg) throws IOException, IllegalBlockSizeException, BadPaddingException{ + ByteArrayInputStream in= new ByteArrayInputStream(msg); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + crypt(in, out, cipher_decrypt); + return out.toByteArray(); + } + /** + * Crypts or decrypts the specified input stream to the specified output + * stream with a given cipher. The crypting or decrypting operation is + * determined by the cipher's state. + * @param cipher The cipher used to crypt the specified input stream to the specified output + * stream. + * @param in the input srteal stream to be encypted or decrypted. + * @param out the output stream to be encypted or decrypted. + * @throws java.io.IOException if an I/O error occurs during crypting the input stream to the output stream. + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + private void crypt(InputStream in, OutputStream out, Cipher cipher) + throws IOException, IllegalBlockSizeException, BadPaddingException + { + int blockSize = cipher.getBlockSize(); + int outputSize = cipher.getOutputSize(blockSize); + byte[] inBytes = new byte[blockSize]; + byte[] outBytes = new byte[outputSize]; + + int inLength = 0; + boolean done = false; + while(!done) + { + inLength = in.read(inBytes); + if(inLength == blockSize) + { + try + { + int outLength = cipher.update(inBytes, 0, blockSize, outBytes); + out.write(outBytes, 0, outLength); + } + catch(ShortBufferException e) + { + e.printStackTrace(); + } + } + else + done = true; + } + + if(inLength > 0) + outBytes = cipher.doFinal(inBytes, 0, inLength); + else + outBytes = cipher.doFinal(); + out.write(outBytes); + + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/InstallCert.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/InstallCert.java new file mode 100755 index 0000000000..ed3349203f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/InstallCert.java @@ -0,0 +1,193 @@ +package pow; +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * @see http://blogs.sun.com/gc/entry/unable_to_find_valid_certification + */ +import java.io.*; + +import java.security.*; +import java.security.cert.*; + +import javax.net.ssl.*; +/** + * + * query the server about its certificate and create a 'jssecacerts' file to copy + * into /usr/lib/jvm/java-x-x/jre/lib/security + * allow a java http client to connect to https server + */ +public class InstallCert { + + public static void main(String[] args) throws Exception { + String host; + int port; + char[] passphrase; + if ((args.length == 1) || (args.length == 2)) { + String[] c = args[0].split(":"); + host = c[0]; + port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); + String p = (args.length == 1) ? "changeit" : args[1]; + passphrase = p.toCharArray(); + } else { + System.out.println("Usage: java InstallCert [:port] [passphrase]"); + return; + } + + File file = new File("jssecacerts"); + if (file.isFile() == false) { + char SEP = File.separatorChar; + File dir = new File(System.getProperty("java.home") + SEP + + "lib" + SEP + "security"); + file = new File(dir, "jssecacerts"); + if (file.isFile() == false) { + file = new File(dir, "cacerts"); + } + } + System.out.println("Loading KeyStore " + file + "..."); + InputStream in = new FileInputStream(file); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(in, passphrase); + in.close(); + + SSLContext context = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; + SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); + context.init(null, new TrustManager[] {tm}, null); + SSLSocketFactory factory = context.getSocketFactory(); + + System.out.println("Opening connection to " + host + ":" + port + "..."); + SSLSocket socket = (SSLSocket)factory.createSocket(host, port); + socket.setSoTimeout(10000); + try { + System.out.println("Starting SSL handshake..."); + socket.startHandshake(); + socket.close(); + System.out.println(); + System.out.println("No errors, certificate is already trusted"); + } catch (SSLException e) { + System.out.println(); + e.printStackTrace(System.out); + } + + X509Certificate[] chain = tm.chain; + if (chain == null) { + System.out.println("Could not obtain server certificate chain"); + return; + } + + BufferedReader reader = + new BufferedReader(new InputStreamReader(System.in)); + + System.out.println(); + System.out.println("Server sent " + chain.length + " certificate(s):"); + System.out.println(); + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + for (int i = 0; i < chain.length; i++) { + X509Certificate cert = chain[i]; + System.out.println + (" " + (i + 1) + " Subject " + cert.getSubjectDN()); + System.out.println(" Issuer " + cert.getIssuerDN()); + sha1.update(cert.getEncoded()); + System.out.println(" sha1 " + toHexString(sha1.digest())); + md5.update(cert.getEncoded()); + System.out.println(" md5 " + toHexString(md5.digest())); + System.out.println(); + } + + System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); + String line = reader.readLine().trim(); + int k; + try { + k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; + } catch (NumberFormatException e) { + System.out.println("KeyStore not changed"); + return; + } + + X509Certificate cert = chain[k]; + String alias = host + "-" + (k + 1); + ks.setCertificateEntry(alias, cert); + + OutputStream out = new FileOutputStream("jssecacerts"); + ks.store(out, passphrase); + out.close(); + + System.out.println(); + System.out.println(cert); + System.out.println(); + System.out.println + ("Added certificate to keystore 'jssecacerts' using alias '" + + alias + "'"); + } + + private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); + + private static String toHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 3); + for (int b : bytes) { + b &= 0xff; + sb.append(HEXDIGITS[b >> 4]); + sb.append(HEXDIGITS[b & 15]); + sb.append(' '); + } + return sb.toString(); + } + + private static class SavingTrustManager implements X509TrustManager { + + private final X509TrustManager tm; + private X509Certificate[] chain; + + SavingTrustManager(X509TrustManager tm) { + this.tm = tm; + } + + public X509Certificate[] getAcceptedIssuers() { + throw new UnsupportedOperationException(); + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + this.chain = chain; + tm.checkServerTrusted(chain, authType); + } + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetId.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetId.java new file mode 100755 index 0000000000..28f7ac4c9d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetId.java @@ -0,0 +1,118 @@ +package pow.ivyclient; +/** + * this object represents the data concerning a drone extracted from Ivy + * A drone has two identities. One on its ivy drone which can be the same as + * another drone on a different ivy bus. The second identifier is the I.D. of the drone + * on the web. This I.D. is unique. So a link has to be done between these two kind of id. + * @author genin + */ +public class AcNetId { + private int idOfBusIvy; + private String idOnIvy; + private String nameOnIvy; + private String idOnWeb; + private String flightplan_path; + private String setting_path; + private String color; + private int maxAircrafts; /// + /** + * + * @param idBusIvy the id of the ivy bus + * @param idIvy the identifier of the drone on ivy + * @param n the name of the ivy drone (MJ5,TJ1...) + * @param pln the full pathname of the configuration file FlightPlan.xml + * @param s the full pathname of the configuration file Settings.xml + * @param c the color of the drone on ivy (in hexa '#FF00FF' or with its common name 'red') + * @param maxACOnIvy the maximal number of aircrafts on ivy bus (is no important anymore) + */ + public AcNetId(int idBusIvy,String idIvy,String n,String pln,String s,String c,int maxACOnIvy){ + idOfBusIvy= idBusIvy; + idOnIvy=idIvy; + nameOnIvy=n; + flightplan_path = pln; + setting_path= s; + color = c; + maxAircrafts = maxACOnIvy; + idOnWeb = generateIdOnWeb(); + + } + /** + * + * @param idBusIvy the id of the ivy bus + * @param droneWebId the identifier of the drone on the web + * @param idIvy the identifier of the drone on ivy + * @param n the name of the ivy drone (MJ5,TJ1...) + * @param pln the full pathname of the configuration file FlightPlan.xml + * @param s the full pathname of the configuration file Settings.xml + * @param c the color of the drone on ivy (in hexa '#FF00FF' or with its common name 'red') + * @param maxACOnIvy the maximal number of aircrafts on ivy bus (is no important anymore) + */ + public AcNetId(int idBusIvy,String droneWebId,String idIvy,String n,String pln,String s,String c,int maxACOnIvy){ + idOfBusIvy= idBusIvy; + idOnIvy=idIvy; + nameOnIvy=n; + flightplan_path = pln; + setting_path= s; + color = c; + maxAircrafts = maxACOnIvy; + idOnWeb = droneWebId; + + } + /** + * provides the id of the drone on the ivy bus + * @return the id number of the drone on its ivy bus + */ + public String getIdOnIvy() {return idOnIvy;} + /** + * provides the name of the drone on the ivy bus + * @return the name of the drone on its ivy bus + */ + public String getName() {return nameOnIvy;} + /** + * provides the id of the drone on the web + * @return the single id number of the drone on the web server + */ + public String getIdOnWeb() {return idOnWeb;} + /** + * provides the path of the xml file (on the server) containing + * the information of the flightplan of the drone + * (waypoints and blocks of instructions) + * @return the full path of the flight plan config file on the GCS station + */ + public String getPlnPath() {return flightplan_path;} + /** + * provides the path of the xml file (on the server) containing the settings + * of the drone + * @return the full path of the settings file on the GCS station + */ + public String getSettingPath() {return setting_path;} + /** + * provides the color of the drone on the GCS view + * @return the color of the drone on the GCS station (either in string or in hexadecimal) + */ + public String getColor() {return color;} + /** + * generate a unique id for the drone on the web + * @deprecated the id is now sent by the server + * @return the id of the drone on the server + */ + private String generateIdOnWeb() { + //String newId = "" + (Integer.parseInt(idOnIvy) * ((int)Math.pow(maxAircrafts,idOfBusIvy))); + String newId = "" + (Integer.parseInt(idOnIvy) +maxAircrafts*idOfBusIvy*10); + System.out.println("### new Id generated : " + newId + " ###"); + return newId; + } + /** + * return information about the drone in a string format + * @return a string containing information about the drone + */ + public String toString(){ + return "id on ivy :\t" + idOnIvy + + "\nname :\t" + nameOnIvy + + "\nid on web :\t" + idOnWeb + + "\nfpl file :\t" + flightplan_path + + "\nsetting file :\t" + setting_path + + "\ncolor :\t" + color ; + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetIdStorage.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetIdStorage.java new file mode 100755 index 0000000000..4c1963f773 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcNetIdStorage.java @@ -0,0 +1,309 @@ +package pow.ivyclient; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.StringReader; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +import pow.webserver.StrictSSLProtocolSocketFactory; + +import fr.dgac.ivy.*; +/** + * this structure memorize all the drone which exist on the ivy bus. + * A drone has two identities. One on its ivy drone which can be the same as + * another drone on a different ivy bus. The second identifier is the I.D. of the drone + * on the web. This I.D. is unique. So a link has to be done between these two kind of id. + * @author genin + */ +public class AcNetIdStorage { + + private int ivyWebId; + private Ivy bus; + String url; // @server to upload + private HashMap acNetIdMap; + ConcurrentHashMap dronesStates; + private int maxAircrafts; + + public AcNetIdStorage(int ii,Ivy b,String u,int maxAC, ConcurrentHashMap states ){ + bus = b; + ivyWebId=ii; + acNetIdMap= new HashMap(); + url = u; + maxAircrafts = maxAC; + dronesStates = states; + } + /** + * Return the identity object of the drone on the web + * @param idOnIvy + * @return the identity of the drone on the web or null if it is not present + */ + public AcNetId getAcNetId(String idOnIvy) + { + return acNetIdMap.get(idOnIvy); + } + /** + * do the link between the id of the drone on the web and is true id on its ivy bus + * @param idOnWeb the id of the drone on the web + * @return the id of the drone on the ivy bus + */ + public String getAcIvyId(int idOnWeb) + { String res = null; + boolean doIt = true; + Collection col = acNetIdMap.values(); + Iterator it = col.iterator(); + while(it.hasNext()&& doIt) + { + AcNetId ac=it.next(); + if (Integer.parseInt(ac.getIdOnWeb())==idOnWeb){ doIt=false; res = ac.getIdOnIvy();} + } + return res; + } + /** + * search the drone net id of a drone from its ivy id + * if the drone is a new one, a new net id is requested to the server + * @param s the ivy id of the drone + */ + public void seekAcNetId(String s) { + String droneWebId; + AcNetId res = acNetIdMap.get(s); + if (res==null){ + try { + AcStatus acs = dronesStates.get(s); + if (acs==AcStatus.UNKNOWN) + { + dronesStates.replace(s,AcStatus.ASKING_WEB_ID); + droneWebId = getNewDroneWebId(s); + dronesStates.replace(s,AcStatus.WEB_ID_RECEIVED); + // send a message on ivy and wait the server + // answer to get the configuration data and create a acNetId object + String rqst_id = bus.getWBUId(); + String msgSend2Ivy = ivyWebId + " " + rqst_id + " CONFIG_REQ " + s + ""; + String msgtoBind= rqst_id +" (.*) CONFIG (.*) file://(.*) file://(.*) file://(.*) file://(.*) (.*) (.*)"; + try { + bus.bindMsgOnce(msgtoBind, new myListener(droneWebId)); + try { + dronesStates.replace(s,AcStatus.ASKING_IVY_CONF); + bus.sendMsg(msgSend2Ivy); + } catch (IvyException e) { + e.printStackTrace(); + System.out.println("### IvyException : can't send request msg ###"); + } + } catch (IvyException e) { + e.printStackTrace(); + } + } + } catch (IvyConnectionExeption e) { + System.out.println("### ERREUR on WEBID REQUEST for drone " +s+" ###"); + e.printStackTrace(); + } + } + } + + + /** + * upload de fichier de conf sur le serveur + * verifier que ca marche sur long fichier + * si probleme changer avec : + * factory.setSizeThreshold(yourMaxMemorySize); + * factory.setRepository(yourTempDirectory); + * upload.setSizeMax(yourMaxRequestSize); + * @param ac the information object about the drone + * @throws InterruptedException + * @throws FileNotFoundException + */ + + public boolean uploadConfFile(AcNetId ac) throws FileNotFoundException { + boolean res=false ; + String pathFPL = ac.getPlnPath(); + String pathSetting = ac.getSettingPath(); + String droneWebId = ac.getIdOnWeb(); + File f1 = new File(pathFPL); + File f2 = new File(pathSetting); + FilePart fp1 = new FilePart(f1.getName(), f1); + FilePart fp2 = new FilePart(f2.getName(), f2); + PostMethod filePost = new PostMethod(url); + Part[] parts = { + new StringPart("order", "uploadConfFile"), + new StringPart("ivyWebId", ""+ivyWebId), + new StringPart("droneWebId", ""+droneWebId), + fp1, + fp2 + }; + filePost.setRequestEntity( + new MultipartRequestEntity(parts, filePost.getParams()) + ); + //filePost.addParameter("requestWebId", ""+webId); + HttpClient client = new HttpClient(); + // useless ? + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + // + try { + int status = client.executeMethod(filePost); + System.out.println("reponse de la methode post uploading " + HttpStatus.getStatusText(status)); + if (status != HttpStatus.SC_OK) { + System.err.println("Method failed: "); + } + else{ + String responseBody = filePost.getResponseBodyAsString(); + try{ + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(new InputSource(new StringReader(responseBody))); + Element ack_node = (Element)document.getElementsByTagName("UploadAck").item(0); + int ack = Integer.parseInt(ack_node.getTextContent()); + if (ack==1){ + System.out.println("uploading ok for " +ack_node.getAttribute("iddrone")); + res = true; + } + else{ + System.out.println("uploading notok for " +ack_node.getAttribute("iddrone")); + res = false; + } + } + catch(Exception e){ + System.err.println("error during the parsing of xml response to a upload request"); + e.printStackTrace(); + } + + } + } catch (HttpException e) { + System.err.println("HttpException : echec execution requete post : uploading"); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException : echec execution requete post : uploading"); + e.printStackTrace(); + } finally { + // Release the connection. + filePost.releaseConnection(); + } + return res; + } + /** + * ask a unique new web id to the server for a new drone detected on the ivy bus + * @param IvyDroneId the drone id on ivy + * @return the new web drone id + * @throws IvyConnectionExeption + */ + public String getNewDroneWebId(String IvyDroneId) throws IvyConnectionExeption + { + String newDroneId = "#errorWebID#"; + int statusCode=-1; + HttpClient client = new HttpClient(); + client.getParams().setParameter("http.useragent", "Ivy request"); + // inutile mais bon pour 1 connection de temps en temps... + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + // + PostMethod method = new PostMethod(url); + method.addParameter("order", "requestNewDroneWebId"); + method.addParameter("ivyWebId", ""+ivyWebId); + try { + statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) { + System.err.println("Method failed: " + method.getStatusLine()); + } + else + { + String responseBody = method.getResponseBodyAsString(); + if(responseBody.startsWith("")); + } + else + { + throw new IvyConnectionExeption("unable to reach server to get new drone webId"); + } + } + } catch (HttpException e) { + System.err.println("HttpException : post request failed : request new drone webId"); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException : post request failed : request new drone webId"); + e.printStackTrace(); + } finally { + // Release the connection. + method.releaseConnection(); + } + return newDroneId; + } + /** + * inner class, normaly could be nested in the bindMsgOnce method of Ivy but + * seems requested so that the ivy send method works + * @author genin + */ + class myListener implements IvyMessageListener { + private String droneWebId; + + myListener(String dwi){ + droneWebId=dwi; + } + @Override + public void receive(IvyClient arg0, String[] args) { + dronesStates.replace(args[1],AcStatus.IVY_CONF_RECEIVED); + System.out.println("message rqst CONFIG received from ivy for drone "+args[1]); + String idOnIvy = args[1]; + String flightplan_path = args[2]; + String setting_path = args[5]; + String drone_name = args[7]; + String color_drone = checkColor(args[6]); + AcNetId ac = new AcNetId(ivyWebId,droneWebId,idOnIvy,drone_name,flightplan_path,setting_path,color_drone,maxAircrafts); + acNetIdMap.put(idOnIvy, ac); + // upload configuration files on the server + try { + dronesStates.replace(args[1],AcStatus.UPLOADING_CONF); + boolean res = uploadConfFile(ac); + if(res) {dronesStates.replace(args[1],AcStatus.CONF_OK);} + else { + dronesStates.replace(args[1],AcStatus.CONF_NOTOK); + System.out.println("conf files upload of drone "+idOnIvy+" impossible, messages will be skipped");} + } catch (FileNotFoundException e) { + e.printStackTrace(); + System.out.println("### FileNotFoundException ###"); + } + } + /** + * on ivy, drone color can be either in text format or in hexa format + * this function send the color in an hex rgb format + * @param color the color in hexa format or in string format + * @return the color in hexa format + */ + private String checkColor(String color){ + String res = ""; + if ((color.length()==7)&&(color.charAt(0)=='#')){ + res = color; + } + else + { + if(color.equals("blue")){ res = "#0000FF"; } + else if (color.equals("red")){ res = "#FF0000"; } + else if (color.equals("green")){ res = "#00FF00"; } + else if (color.equals("yellow")){ res = "#00FFFF"; } + else if (color.equals("purple")){ res = "#FFFF00"; } + else {res = "#0F0F0F";} + } + return res; + } + + }// fin inner class + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcStatus.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcStatus.java new file mode 100755 index 0000000000..c8b4ee5cfb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/AcStatus.java @@ -0,0 +1,30 @@ +package pow.ivyclient; +/** + * implements the life cycle of a drone when it is detected on the ivy bus. + * these steps are needed to prevent that a ivy message is processed before + * that all information about the drone were retrieved + * these status follow the steps that are followed by the module when a new drone + * is detected on the bus + * @see Ivy2Udp + * @author genin + */ +public enum AcStatus { + /** the system does not know this drone, information are requested*/ + UNKNOWN, + /** a request about the configuration has been sent on ivy*/ + ASKING_IVY_CONF, + /** the configuration has been received from ivy*/ + IVY_CONF_RECEIVED, + /** the module sends request to the web server for having a web id for the drone*/ + ASKING_WEB_ID, + /** the drone web id has been received from the server */ + WEB_ID_RECEIVED, + /** the module upload the two configuration files of the drone on the server */ + UPLOADING_CONF, + /** the 2 configuration files have been uploaded successfully */ + CONF_OK, + /** the module can received ivy message for this drone and send them to the server*/ + ALIVE, + /** a problem occurred during the process*/ + CONF_NOTOK +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/BusIvy_.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/BusIvy_.java new file mode 100755 index 0000000000..50fee0a112 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/BusIvy_.java @@ -0,0 +1,91 @@ +package pow.ivyclient; + +import java.net.*; +import java.util.*; +import java.util.Calendar; +/** + * inner representation of an ivy bus + * store the drones' information about the drones which belong to this ivy bus + * store the IP adress of the machine where the ivy bus is working + */ +public class BusIvy_ +{ + private Calendar oCalendar; + private long oTime; + private InetAddress busAddress; + private ArrayList DronesId = new ArrayList(); + /** + * + * @param myInetAddress the ip address of the ivy host + */ + public void setAddress(InetAddress myInetAddress) + { + busAddress = myInetAddress; + } + /** + * update the 'inner clock' of the object when a message for this bus is detected + * useful to know if the bus is still alive + */ + public void updateTime() + { + oCalendar=Calendar.getInstance(); + oTime = oCalendar.getTimeInMillis(); + } + /** + * inform the bus that a new drone send information on this bus + * @param newDroneId (the ivy id) + */ + public void addDrones(int newDroneId) + { + DronesId.add(newDroneId); + } + /** + * get a array list containing the ivy id of the drones present on the bus + * @return the array list containing the ivy id of the drones present on the bus + */ + public ArrayList getDrones() + { + return DronesId; + } + /** + * display information on stdout about the drones present on the bus + */ + public void displayDrones() + { + System.out.println("Bus Ivy : "); + System.out.println(busAddress); + System.out.println("Drones : "); + for(Integer myDrone : DronesId) + { + System.out.println(myDrone); + } + } + /** + * provides the IP adress of the host hosting the bus + * @return the IP adress of the host hosting the bus + */ + public InetAddress getAddress() + { + return busAddress; + } + /** + * inform if a drone is present or not on the bus + * @param myDroneId the ivy id + * @return true if the drone is present on the bus + */ + public boolean isOwnBy(int myDroneId) + { + return DronesId.contains(myDroneId); + } + /** + * inform if the bus is alive + * @return true if the last message was received less than 10 seconds ago + */ + public boolean isAlive() + { + Calendar iCalendar = Calendar.getInstance(); + long iTime = iCalendar.getTimeInMillis(); + + return ((iTime - oTime)<10000); // 10 secondes + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/HeartBeat.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/HeartBeat.java new file mode 100755 index 0000000000..997f9d05cf --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/HeartBeat.java @@ -0,0 +1,103 @@ +package pow.ivyclient; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; + +import pow.AES; + +/** + * thread which send a periodic message to a client or server to say that the connection + * is still alive (period has to be less than the socket timeout of the the server) + * @author genin + */ +public class HeartBeat implements Runnable { + + private InetAddress serveur; + private int portUdpSend; + private long period2sendheartbeat; + private boolean doIt; // to stop thread + private int webId; + private SimpleDateFormat dateformat; + private int num_msg; + private AES aes; + + /** + * define the parameter of the heartbeat message + * @param cipher the way to encrypt message to be send on udp channel + * @param webId the id of the bus + * @param srv the ip address of the host hosting the ivy bus + * @param port2send the udp port on which the heartbeat is sent + * @param heartbeatPeriod the period of time to send heartbeat message + */ + public HeartBeat(AES cipher,int webId, InetAddress srv,int port2send,long heartbeatPeriod) { + aes = cipher; + this.webId = webId; + serveur = srv; + + portUdpSend = port2send; + period2sendheartbeat = heartbeatPeriod; + dateformat = new SimpleDateFormat("d:M:y:HH:mm:ss"); + num_msg = 0; + doIt =true; + } + + + /** + * send a periodic heartbeat message + */ + public void run(){ + + String msg = "HEARTBEAT "+ webId; + String full_msg; + byte[] buffer; + DatagramPacket dataUdp; + DatagramSocket socketUdp=null; + while(doIt){ + try{ + Thread.sleep(period2sendheartbeat); + full_msg = add_info_msg(msg); + buffer = aes.encrypt(full_msg.getBytes()); // method should be synchronized ? + try { + socketUdp = new DatagramSocket(); + dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + socketUdp.send(dataUdp); + System.out.println("H"); + } catch (IOException e) { + System.out.println("socket ioexception : can't send heart beat"); + } + finally{ + if (socketUdp!=null) {socketUdp.close();socketUdp=null;} + } + } + catch(InterruptedException iex){ + System.out.println("heartbeat sleep failed"); + } + catch(BadPaddingException bpex){System.out.println("error padding heartbeat");} + catch(IllegalBlockSizeException ex){System.out.println("error illegal block heartbeat");} + catch(IOException ioex){System.out.println("error io heartbeat");} + } + System.out.println("Thread HeartBeat stopped !"); + } + + /** + * add usefull info to msg for storage in database + * its requested because of the format of messages that server is waiting + */ + private String add_info_msg(String msg){ + String monHeure = this.dateformat.format(new Date()); + String res = "" + this.webId+" " + this.num_msg + " " + monHeure +" " + msg; + this.num_msg++; + return res; + } + /** + * stop the heartbeat thread by ending the infinite loop + */ + public void stop_thread(){doIt=false;} +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2Udp.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2Udp.java new file mode 100755 index 0000000000..dc60bd3962 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2Udp.java @@ -0,0 +1,1020 @@ +package pow.ivyclient; + +import java.io.*; +import java.net.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +//import java.util.Vector; + +import fr.dgac.ivy.*; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; + +import java.io.StringReader; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +import pow.AES; +import pow.webserver.StrictSSLProtocolSocketFactory; + +/** + * It contact the server to get an identifier, some configuration parameter and + * the key to encrypt and decrypt messages. + * Then it listens messages on the ivy bus and send messages on active drones to the + * web server. + * @author jabln, thomas genin + * @version 2.0 + */ +public class Ivy2Udp implements Runnable{ + private InetAddress serveur; + private String login; + private String password; + final static int portUdpSend = 8535; + final static int portUdpReceive = 8536; + private Ivy bus; + private Thread heartbeatThread; + private HeartBeat heartbeatRun; + final static int taille = 1024; + static int maxAircrafts = 1000; // TODO a changer !!! mettre une map ou qqch + static int datagramLength = 17; // modif , on a rajoute la couleur a la fin + private String datagramMatrix[][] = new String[maxAircrafts][datagramLength];// TODO a changer !!! mettre une map ou qqch + private int aircraftNumber = 0; + private Boolean aircraftAlive[] = new Boolean[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int count[] = new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int countSettings[]=new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private HashMap> settingsToBeChanged = new HashMap>(); + private int webId=-999; + private byte[] aesKey ; + private AES aesCipher; + private String url; + private AcNetIdStorage acNetIds; + private ConcurrentHashMap dronesStatus; + /* *********************** */ + private long time2resetWptFilter = 20*60*1000; // on nettoie les filtres tous les 20min !!!!! + private MsgFilter waypointMsgFilter; + private long chrono_start; + private long elapsed_time; + private long timeToSendValues=60*1000; // on envoie les values d'un drone toutes les 60 secondes + private HashMap lastvaluesMap; + private long lastivymessage; + /* ************************ */ + private long num_msg; + private SimpleDateFormat dateformat; + /* ************************** */ + private int socketTimeOut ; + /* ************************* */ + private boolean continueListening ; + private boolean reconnect = false; + private HashSet bindSet; + IvyIHM ihm; + /** + * create an object which listens on the local ivy bus and send messages to the server + * @param urlObj describes information about the server + * @param login + * @param password + */ + public Ivy2Udp(IvyIHM ihm,PowUrl urlObj,String login, String password) + { + this.ihm = ihm; + continueListening = true; + num_msg = 0; + dateformat = new SimpleDateFormat("d:M:y:HH:mm:ss"); + try{ + this.login = login; + this.password = password; + serveur = InetAddress.getByName(urlObj.getServerName()); + // ********************************************* // + this.url = urlObj.getWebUrl(); + // ********************************************* // + dronesStatus = new ConcurrentHashMap(); + lastvaluesMap = new HashMap(); + // ********************************************* // + waypointMsgFilter = new MsgFilter(); + chrono_start = System.currentTimeMillis(); + // ********************************************* // + bindSet = new HashSet(); + bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + } catch (Exception ie) { + System.out.println("Error : cannot connect to server"); + } + } + /* ******************************** */ + /* *********** structure de correspondance entre webid et ivyid pour chaque drone ************ */ + /** initiate the object which allow to store information about drones */ + public void setStorage(){ + acNetIds = new AcNetIdStorage(webId,bus,url,maxAircrafts,dronesStatus); + } + /** provides the structure where data about the drone present on the ivy bus are stored + * @return the structure which allow to store information about drones */ + public AcNetIdStorage getStorage(){ + return acNetIds ; + } + /** return the id of the bus for the server + * this id is provided by the server and is unique + * @return the unique id of this ivy bus for the server */ + public int getIvyWebId(){ + return webId; + } + /** + * request a single id for the bus to the web server + * method get + * see @link http://hc.apache.org/httpclient-3.x/tutorial.html + * see @link blogs.sun.com/gc/entry/unable_to_find_valid_certification + * see @link http://blogs.sun.com/andreas/entry/no_more_unable_to_find + */ + public void getWebId() throws IvyConnectionExeption + { + int statusCode=-1; + // http config + HttpClient client = new HttpClient(); + client.getParams().setParameter("http.useragent", "Ivy request"); + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + PostMethod method = new PostMethod(url); + method.addParameter("order", "requestWebId"); + method.addParameter("login", login); + method.addParameter("pwd", password); + try { + System.out.println("### envoie de la requete requestWebId###"); + statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) { + System.err.println("Method failed: " + method.getStatusLine()); + throw new IvyConnectionExeption("Erreur de retour de la requete de connection"); + } + else + { + // Read the response body. + try { + String responseBody = method.getResponseBodyAsString();//getResponseBody();//); + // Deal with the response + try { + // parse response in XML tree + // @SEE http://java.developpez.com/faq/xml/?page=dom + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(new InputSource(new StringReader(responseBody))); + // get login acknowledgment + Element ack_node = (Element)document.getElementsByTagName("ConnectionAck").item(0); + int ack = Integer.parseInt(ack_node.getTextContent()); + if (ack==1){ + // get webid node + Element webid_node = (Element)document.getElementsByTagName("webid").item(0); + webId = Integer.parseInt(webid_node.getTextContent()); + if (webId==-999) {throw new IvyConnectionExeption("unable to have correct webId");} + // get key node + Element aeskey_node= (Element)document.getElementsByTagName("aeskey").item(0); + String str_hex_aeskey = aeskey_node.getTextContent(); + // get parameter key node + Element aesiv_node= (Element)document.getElementsByTagName("aesiv").item(0); + String str_hex_aesIvParameter = aesiv_node.getTextContent(); + // get periods of time + Element time2resetWptFilter_node=(Element)document.getElementsByTagName("time2resetFilter").item(0); + this.time2resetWptFilter =Long.parseLong(time2resetWptFilter_node.getTextContent()); + Element timeToSendValues_node =(Element)document.getElementsByTagName("timeToSendValues").item(0); + this.timeToSendValues=Long.parseLong(timeToSendValues_node.getTextContent()); + Element socketTimeOut_node =(Element)document.getElementsByTagName("socketTimeOut").item(0); + this.socketTimeOut=Integer.parseInt(socketTimeOut_node.getTextContent()); + // + aesKey = Hex.decodeHex(str_hex_aeskey.toCharArray()); + byte[] iv = Hex.decodeHex(str_hex_aesIvParameter.toCharArray()); + aesCipher = new AES(aesKey,iv); + // + System.out.println("##########################"); + System.out.println("### connection ok+\t###"); + System.out.println("### web id = "+ webId +"\t###"); + System.out.println("### aes key = "+ str_hex_aeskey +"\t###"); + System.out.println("##########################"); + } + else if (ack==2){ + throw new IvyConnectionExeption("login ok, but aes encryption not supported by server"); + } + else if (ack==3){ + throw new IvyConnectionExeption("login ok, but server unable to generate a web id"); + } + else + { + throw new IvyConnectionExeption("login process failed, you're not allowed to access the server"); + } + } + catch(Exception e) { + e.printStackTrace(); + throw new IvyConnectionExeption("unable to read the server response"); + } + } + catch (IOException e) { + System.err.println("IOException : echec execution requete post : request webId"); + e.printStackTrace(); + throw new IvyConnectionExeption("No response from the server"); + } + } + } catch (HttpException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("HttpException : echec execution requete post : request webId"); + } catch (IOException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("IOException : echec execution requete post : request webId"); + } finally { + method.releaseConnection(); // Release the connection. + + } + } + + + /** + * create a thread which send heart beat message to the server + */ + public void startHeartBeat(){ + heartbeatRun = new HeartBeat(aesCipher,webId,serveur,portUdpSend,socketTimeOut/3);// socket timeout = 10000 for server + heartbeatThread = new Thread(heartbeatRun); + heartbeatThread.start(); + System.out.println("process heartbeat started"); + } + + /** + * This method binds the object to some messages + * of the bus Ivy. Each information that is needed by the web server is put in an + * array. This array is sent to server. + */ + public void bindMsg2Ivy() throws IvyException { + for (int i = 0; i < countSettings.length; i++) { + countSettings[i] = 0; + } + + for (int i = 0; i < count.length; i++) { + count[i] = 0; + } + for (int i = 0; i < datagramMatrix.length; i++) { + for (int j = 0; j < datagramMatrix[i].length - 1; j++) { + datagramMatrix[i][j] = new String(" "); + } + } + for (int i = 0; i < aircraftAlive.length; i++) { + aircraftAlive[i] = true; + } + // fetch flight parameters + // see message feature in paparazzi folder + // file /conf/message.xml + // listen a specific message on the ivy bus and define a callback function + bindSet.add(bus.bindMsg("ground FLIGHT_PARAM ([^ ]*) [^ ]* [^ ]* [^ ]* ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][3] = args[1]; + datagramMatrix[acIndex][4] = args[2]; + datagramMatrix[acIndex][5] = args[3]; + datagramMatrix[acIndex][6] = args[4]; + datagramMatrix[acIndex][7] = args[5]; + datagramMatrix[acIndex][8] = args[6]; + datagramMatrix[acIndex][9] = args[7]; + send(acIndex); + } + else // other states UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + + System.out.println("Can't process FLIGHT_PARAM information"); + ie.printStackTrace(); + } + + } + })); + + bindSet.add(bus.bindMsg("ground ENGINE_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][10] = args[1]; + send(acIndex); + } + else // other states UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process ENGINE_STATUS information"); + } + + } + })); + + bindSet.add(bus.bindMsg("ground ENGINE_STATUS ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][12] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + })); + + + bindSet.add(bus.bindMsg("ground AP_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][11] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + })); + + // when a JUMP_TO_BLOCK message is sent after a web user order + // we have to wait for this message to have a real acknowledgment of the order + bindSet.add(bus.bindMsg("ground NAV_STATUS ([^ ]*) ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][13] = args[1]; + // + String j2b[] = new String[1]; + j2b[0] = args[1]; + String s = new String("NAV_STATUS"); + send(acIndex,s,j2b); + + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process NAV_STATUS information"); + } + + } + })); + // when a DL_SETTING message is sent after a web user order + // we have to wait for this message to have a real acknowledgment of the order + bindSet.add(bus.bindMsg("ground DL_VALUES ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + public void receive(IvyClient client, String[] args){ + lastivymessage = System.currentTimeMillis(); + try{ + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + String[] settingSplited = args[1].split(","); + String settingId = new String (""); + settingId = settingId + countSettings[acIndex]; + datagramMatrix[acIndex][14] = settingId; + datagramMatrix[acIndex][15] = settingSplited[countSettings[acIndex]]; + send(acIndex); + countSettings[acIndex] = (countSettings[acIndex] + 1) % settingSplited.length; + // gestion de l'A/R de DL_SETTING + // on attend que la valeur du setting soit effectivement change pour envoyer l'A/R + if (settingsToBeChanged.containsKey(acIndex)){ + HashMap h = settingsToBeChanged.get(acIndex); + Set k = h.keySet(); + Iterator itr = k.iterator(); + + while(itr.hasNext()){ + int current_settingid = itr.next(); + float value = h.get(current_settingid); + if(value==Float.parseFloat(settingSplited[current_settingid])){ + h.remove(current_settingid); + String chgSet[] = new String[2]; + chgSet[0] = ""+current_settingid; + chgSet[1] = ""+value; + String s = new String("DL_SETTING_ACK"); + send(acIndex,s,chgSet); + System.out.print("%"); + } + } + } + // gestion de l'envoie de l'ensemble des valeurs de + // setting pour un drone , on envoie la trame par periode timeToSendValues + Long lasttime = lastvaluesMap.get(acIndex); + long nowtime = System.currentTimeMillis(); + boolean firsttime = false; + if (lasttime==null){ + lasttime = nowtime; + lastvaluesMap.put(acIndex,nowtime); + firsttime = true ; + } + + if (firsttime||((nowtime-lasttime)>timeToSendValues)){ + // on envoie la value + String csv[] = new String[1]; + csv[0] = args[1]; + String s = new String("SETTINGS_VALUES"); + send(acIndex,s,csv); + System.out.print("+"); + lastvaluesMap.put(acIndex,nowtime); + } + + + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch(Exception ie) { + System.out.println("Can't process DL_VALUES information"); + System.out.println("acid= "+args[0]); + System.out.println("csv= "+args[1]); + System.out.println("********************\n"+ie.toString()+"\n********************"); + } + } + })); + // when a MOVE_WAYPOINT message is sent after a web user order + // we have to wait for this message to have a real acknowledgment of the order + bindSet.add(bus.bindMsg("ground WAYPOINT_MOVED ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)",new IvyMessageListener(){ + public void receive(IvyClient client, String[] args){ + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + String mvWp[] = new String[4]; + for (int j = 0;j<4;j++){ + mvWp[j] = args[j+1]; + } + String s = new String("WAYPOINT_MOVED"); + send(i,s,mvWp); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process MOVE_WAYPOINT information"); + } + } + })); + // as there are many DL_VALUES messages on ivy bus, when a DL_SETTING order is sent + // we have to keep a link between the order and the response we are waiting for having a real + // acknowledgment + bindSet.add(bus.bindMsg("DL_SETTING ([^ ]*) ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + + public void receive(IvyClient client, String[] args){ + lastivymessage = System.currentTimeMillis(); + try{ + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int indexAircraft = a.getAcId(); + int indexSetting = Integer.parseInt(args[1]); + float valueSetting = Float.parseFloat(args[2]); + // memorisation qu'une requete DL_SETTING a ete faire + // voir traitement dans ground DL_VALUES + if (!settingsToBeChanged.containsKey(indexAircraft)){ + settingsToBeChanged.put(indexAircraft, new HashMap()); + } + settingsToBeChanged.get(indexAircraft).put(indexSetting, valueSetting); + System.out.print("$"); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process DL_SETTING information"); + } + } + })); + // allow to be sure that a drone is still alive + // this message is sent by ivy server to inform when the last message about a drone + // was sent + bindSet.add(bus.bindMsg("ground TELEMETRY_STATUS ([^ ]*) ([^ ]*)", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + lastivymessage = System.currentTimeMillis(); + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + if (i != -1) { + float f = Float.parseFloat(args[1]); + if (aircraftAlive[i] && f > 30) { + aircraftAlive[i] = false; + String s = new String("Plane_Die"); + send(i, s); + } else { + if (!aircraftAlive[i] && f < 30) { + aircraftAlive[i] = true; + String s = new String("Plane_Resurect"); + send(i, s); + } + } + } + } + } catch (Exception ie) { + + System.out.println("Can't process TELEMETRY_STATUS information"); + } + + } + })); + + bus.start(null); + } + /** + * stop all the thread Ivy2Udp , HeartBeat and ivy2UdpWriting + */ + public void stop_thread(){ + + Iterator itr = bindSet.iterator(); + while(itr.hasNext()){ + try { + bus.unBindMsg(itr.next()); + } catch (IvyException e) { + System.out.println("unable to unbind ivy msg"); + } + } + bus.stop();bus=null; + System.out.println("link to bus ivy stopped !"); + if(this.heartbeatRun!=null) this.heartbeatRun.stop_thread(); + continueListening = false; + } + /** + * add usefull info to msg for storage in database + * web_id + * number the message if we want to order then on the server (because udp is not safe) + */ + private String add_info_msg(String msg){ + String monHeure = this.dateformat.format(new Date()); + String res = "" + this.webId+" " + this.num_msg + " " + monHeure +" " + msg; + this.num_msg++; + return res; + } + + /** + * This method send to the web server the datagram containing the informations + * about the aircraft + * @param acId Line of the matrix containing the informations about the plane + * @throws java.lang.Exception + */ + public void send(int acId){ + DatagramSocket socketUdp = null; + String s = ""; + if (count[acId] == 5) { + if (aircraftAlive[acId]) { + byte buffer[]; + s = ""; + for (int i = 1; i < 7; i++) { + s = s + datagramMatrix[acId][i] + " "; + } + for(int i = 7; i< 10;i++){ + StringBuffer str = new StringBuffer(datagramMatrix[acId][i]); + str.setLength(5); + s = s + str + " "; + } + for(int i = 10; itaille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + System.out.print("#"); + count[acId] = 0; + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + finally{if(socketUdp!=null){socketUdp.close();socketUdp=null;}} + + } + catch( IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + } else { + count[acId]++; + } + } + + + /** + * This method send to the web server a specific order with parameters + * @param acId : Line of the matrix containing the informations about the plane + * @param s : order + * @param as : parameters + */ + + public void send(int acId, String s, String[] as){ + String order = s; + DatagramSocket socketUdp=null; + s = s + " " + datagramMatrix[acId][1]+ " "; + for (int i =0; i< as.length;i++){ + s = s + as[i] + " "; + } + byte buffer[]; + // gestion de l'ecoute ou non des msg waypoint_moved et des autres msg speciaux + boolean isnew = true; + // on filtre certains messages + if (order.equals("WAYPOINT_MOVED") + ||order.equals("NAV_STATUS")) + { + elapsed_time = System.currentTimeMillis() - chrono_start; + if (elapsed_time>time2resetWptFilter) + { + waypointMsgFilter.resetfilter(); + chrono_start = System.currentTimeMillis(); + } + isnew = waypointMsgFilter.isNew(s); + } + if(isnew){ + System.out.print("!"); + s = this.add_info_msg(s); + buffer = s.getBytes(); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + finally{if(socketUdp!=null){socketUdp.close();socketUdp=null;}} + } + catch (IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + } + + + + /** + * This method send a particular message about an aircraft + * @param acId line of the matrix containing the informations about the plane + * @param s message that is to be sent to send + */ + public void send(int acId, String s) { + DatagramSocket socketUdp= null; + s = s + " " + datagramMatrix[acId][1]; + byte buffer[] ; + s = this.add_info_msg(s); + buffer = s.getBytes(); + System.out.println(s); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + finally{if(socketUdp!=null){socketUdp.close();socketUdp=null;}} + } + catch (IOException ex){System.out.print("cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + + /** + * listen the udp socket to get orders from web clients and send them to ivy + */ + public void run() { + byte[] complete_data ; + int true_length_of_msg ; + int i; + long elapsed_ivy; + byte[] data_with_no_padding; + boolean heartbeat_is_running = false; + DatagramSocket socket = null; + // login procedure + setStorage(); + try{ + bindMsg2Ivy(); + this.startHeartBeat(); + // start the module which listens to the orders coming from web users + try + { + lastivymessage = System.currentTimeMillis(); + System.out.println("on lance udp writing "); + int portUdpReceive = 8536 ; + socket = new DatagramSocket(portUdpReceive); + socket.setSoTimeout(this.socketTimeOut); + while (continueListening) { + // check last ivy message + elapsed_ivy = System.currentTimeMillis()-lastivymessage; + /* + if(elapsed_ivy>10000) { this.heartbeatRun.stop_thread();heartbeat_is_running = false;} + else if (!heartbeat_is_running){ + //Reconnection + } + */ + //listening server (hertbeat and true messages + byte buffer[] = new byte[taille]; + DatagramPacket data = new DatagramPacket(buffer, buffer.length); + try{ + socket.receive(data); + String[] messageed; + try{ + complete_data = data.getData(); + // we have to remove the padding bytes present in the udp trame if the message is too short + true_length_of_msg = data.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + byte[] decrypted_data = aesCipher.decrypt(data_with_no_padding); + String s = new String(decrypted_data); + if (!s.equals("SERVER_HEARTBEAT")){ + System.out.print("data received from server web : "); + System.out.println(s); + messageed = s.split(" "); + try{ + // creer un objet d'envoie qui connait la correspondance ivyid et webid pour chaque drone + new Ivy2UdpWriting(messageed, getStorage()); + } + catch(IvyException e1){ System.out.println("erreur sending msg to ivy : " + s);} + } + // else {System.out.println("\nHEARTBEAT FROM SERVER");} + } + catch(IOException ex){System.out.print("cipher error : cannot decrypt msg : msg not sended to ivy");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + catch(SocketTimeoutException ex){ + // no heartbeat + continueListening = false ; + this.stop_thread(); + reconnect = true; + ihm.setReLogged(true); + } + catch(IOException e){ e.printStackTrace();System.out.println("erreur socket when receive message");} + } + + System.out.println("Thread Ivy2Udp stopped !"); + } + catch(SocketException e){ System.out.println("erreur creation de socket server-->ivy ");} + finally{if (socket!=null){socket.close();socket=null;}} + + } + catch (IvyException e){ + System.out.println("unable to bind to ivy...connection failed"); + e.printStackTrace(); + System.exit(0); + } + + } + + + /** + * Inner class which manage to search in acNetIdStorage, the index of a plane according to its ivyid + * if the drone is unknown , an identifiant is requested to the server and its conf files are uploaded + */ + class aircraftIdSeeker { + private String droneId; + private int res; + + public aircraftIdSeeker(String s){ + + droneId = s; + res = -1; + } + + public int getAcId() {return res;} + + public void seek(){ + // seek if the drone status + AcStatus droneState = dronesStatus.get(droneId); + int i = 0; + // ALIVE means that the information about the drone were already fetched and so + // we can directly seek them on the datamatrix + if (droneState==AcStatus.ALIVE){ + while (i < maxAircrafts && !droneId.equals(datagramMatrix[i][0])) { + i++; + } + if (i < aircraftNumber) { + res = (i); + } + else { + // big error should not arrive + System.out.println("ERROR , ALIVE BUT NOT IN MATRIX !!!"); + } + }// + // if status in unknown we have to seek th information on the ivy bus and + //ask the server a new web id for the drone + else if (droneState==AcStatus.UNKNOWN) + { + acNetIds.seekAcNetId(droneId); + }// if conf is ok , we can fill the datamatrix and put the drone in ALIVE STATUS + // when the next message for this bus will arrive it will be processed normally + else if (droneState==AcStatus.CONF_OK) { + AcNetId ac = acNetIds.getAcNetId(droneId); + datagramMatrix[aircraftNumber][0] = ac.getIdOnIvy(); // id on IvyBus + datagramMatrix[aircraftNumber][1] = ac.getIdOnWeb(); // id on Web Client + datagramMatrix[aircraftNumber][2] = ac.getName(); // name + datagramMatrix[aircraftNumber][16] = ac.getColor(); + dronesStatus.replace(droneId,AcStatus.ALIVE); + // + if (datagramMatrix[aircraftNumber][0].equals(" ")) { + res= (-1); + } else { + aircraftNumber++; + String newPlane = new String("New_Plane"); + String name[] = new String[1]; + name[0] = ac.getName(); + send(aircraftNumber - 1, newPlane,name); + res= (aircraftNumber - 1); + } + } + else { // that means that the drone is in a intermediate status we have to wait that + // the status becomes CONF_OK to continue ( on the next ivy message) + // do nothing + } + } + } //fin class acId + +} // fin class ivy2udpreading + + + + + + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2UdpWriting.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2UdpWriting.java new file mode 100755 index 0000000000..4bb15c6ca5 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/Ivy2UdpWriting.java @@ -0,0 +1,62 @@ +package pow.ivyclient; + +import fr.dgac.ivy.*; + +/** + * This class aims to give order to the drones according to the datagrams it + * receive from the web + * @author jabln + */ +public class Ivy2UdpWriting implements IvyMessageListener { + + + private Ivy bus; + private AcNetIdStorage netIdStorage; + private String[] message; //Array which contains the informations are to be sent on the bus + private String IvyAcId; //Identity of the aircraft on the bus Ivy + + /** + * This constructor of the class binds to the bus Ivy and implements the + * method receive to send on the bus the informations given in parametres + * in an array of string + * @param message Informations that is to be sent on the bus Ivy + * @param storage the object which to do the link between webid and ivyid for each drone + * @throws java.lang.Exception + */ + Ivy2UdpWriting(String[] message, AcNetIdStorage storage) throws IvyException { + this.message = message; + netIdStorage = storage; + int acwebid = Integer.parseInt(message[1]); + this.IvyAcId = netIdStorage.getAcIvyId(acwebid); + if ( this.IvyAcId != null) { + bus = new Ivy("Web Writing", "Web Writing ready", null); + bus.start(null); + + bus.bindMsg("FLIGHT_PARA.*", this); + } + else + { + System.out.println("enable to make the link between webid on ivyidy"); + } + } + + /** + * This method implements the method receive of the bus Ivy class. + * It sends the informations on the ivy bus and stop the binding + * @param client + * @param args + */ + public void receive(IvyClient client, String args[]) { + try { + String s = "WEB_MSG "; + s = s + message[0] + " " + IvyAcId + " "; + for (int i = 2; i < message.length; i++) { + s = s + message[i] + " "; + } + bus.sendMsg(s); + bus.stop(); + } catch (IvyException ie) { + System.out.println("can't send my message on the bus"); + } + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyConnectionExeption.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyConnectionExeption.java new file mode 100755 index 0000000000..30d7ecb825 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyConnectionExeption.java @@ -0,0 +1,25 @@ +package pow.ivyclient; + +public class IvyConnectionExeption extends Exception { + + /** + * create a specific exception linked with Ivy problem + */ + private static final long serialVersionUID = 1805159521752564076L; + private String reason; + + /** + * create an ivy exception with a particular message + * @param res the message + */ + public IvyConnectionExeption(String res){ + super(); + reason = res; + } + /** + * display the exception on stdout + */ + public String toString() { + return "IvyConnectionExeption : "+reason; + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyIHM.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyIHM.java new file mode 100755 index 0000000000..db22e05081 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/IvyIHM.java @@ -0,0 +1,337 @@ +package pow.ivyclient; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +/** + * represent the interface for a ivy user who wants to connect a bus ivy to + * the web server + * @author genin + * + */ +public class IvyIHM implements Runnable{ + private JFrame glob_fenetre; + private JLabel login_lbl; + private JTextField login_txtfield; + private JLabel pwd_lbl; + private JPasswordField pwd_txtfield; + private JLabel url_lbl; + private JTextField url_txtfield; + + private Container contenuMore; + private boolean moreIsVisible ; + private JLabel protocol_lbl; + private JComboBox protocol_field; + private JLabel port_lbl; + private JComboBox port_field; + private JLabel site_lbl; + private JTextField site_txtfield; + private JLabel servlet_lbl; + private JTextField servlet_txtfield; + private String[] protocolsStrings = { "http", "https" }; + private String[] portsStrings = { "none", "80","8080","443" }; + private JButton log_btn; + private JButton quit_btn; + private JButton more_btn; + private JButton stop_btn; + private boolean logged ; + private boolean relogged ; + private static int taille_text = 20; + + private Ivy2Udp module; + /** + * construct the interface + */ + public IvyIHM(){ + module = null; + logged = false;relogged=false; + glob_fenetre = new JFrame("Connection to POW Server"); + glob_fenetre.setLocation(100,200); + + Container contenuTextField ; + //ensemble des textfiled + JPanel listTextField= new JPanel(); + listTextField.setLayout(new BoxLayout(listTextField, BoxLayout.PAGE_AXIS)); + contenuTextField = new JPanel(new FlowLayout()); + login_lbl = new JLabel("login"); + login_txtfield= new JTextField("your login",taille_text); + contenuTextField.add(login_lbl); + contenuTextField.add(login_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + pwd_lbl = new JLabel("password"); + pwd_txtfield= new JPasswordField("",taille_text); + contenuTextField.add(pwd_lbl); + contenuTextField.add(pwd_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + url_lbl = new JLabel("hostname"); + url_txtfield= new JTextField("blanc",taille_text); + contenuTextField.add(url_lbl); + contenuTextField.add(url_txtfield); + listTextField.add(contenuTextField); + // + listTextField.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + // les trois boutons + more_btn = new JButton("More..."); + log_btn = new JButton("Log !"); + stop_btn = new JButton("Stop !"); + quit_btn = new JButton("Quit !"); + Container contenuButton = new JPanel(new FlowLayout()); + contenuButton.add(quit_btn); + contenuButton.add(log_btn); + contenuButton.add(stop_btn); + contenuButton.add(more_btn); + more_btn.addActionListener(new MoreAction(glob_fenetre)); + log_btn.addActionListener(new LogAction()); + stop_btn.addActionListener(new StopAction()); + quit_btn.addActionListener(new QuitAction()); + //le panneau more.... + contenuMore = new JPanel(); + contenuMore.setLayout(new BoxLayout(contenuMore, BoxLayout.PAGE_AXIS)); + + Container contenuMoreMore = new JPanel(new FlowLayout()); + + protocol_field = new JComboBox(protocolsStrings); + protocol_lbl = new JLabel("protocol"); + contenuMoreMore.add(protocol_lbl); + contenuMoreMore.add(protocol_field); + //contenuMore.add(contenuMoreMore); + + //contenuMoreMore = new JPanel(new FlowLayout()); + port_lbl = new JLabel("port"); + port_field = new JComboBox(portsStrings);; + contenuMoreMore.add(port_lbl); + contenuMoreMore.add(port_field); + contenuMore.add(contenuMoreMore); + + contenuMoreMore = new JPanel(new FlowLayout()); + site_lbl= new JLabel("site name"); + site_txtfield= new JTextField("ServletPow",taille_text); + contenuMoreMore.add(site_lbl); + contenuMoreMore.add(site_txtfield); + contenuMore.add(contenuMoreMore); + + contenuMoreMore = new JPanel(new FlowLayout()); + servlet_lbl= new JLabel("servlet name"); + servlet_txtfield= new JTextField("Ivy2TomcatHttpServer.srv",taille_text); + contenuMoreMore.add(servlet_lbl); + contenuMoreMore.add(servlet_txtfield); + contenuMore.add(contenuMoreMore); + moreIsVisible = false; + contenuMore.setVisible(moreIsVisible); + // + glob_fenetre.setLayout(new BorderLayout()); + Container contenu = glob_fenetre.getContentPane(); + contenu.add(listTextField,BorderLayout.NORTH); + contenu.add(contenuMore,BorderLayout.CENTER); + contenu.add(contenuButton,BorderLayout.SOUTH); + glob_fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + glob_fenetre.pack(); + glob_fenetre.setVisible(true); + } + /** + * specify whether the module should reconnected or not + * @param l true or false + */ + public void setReLogged(boolean l){ + relogged = l; + } + /** + * loop to perform a periodic check for automatic reconnection + */ + public void run(){ + while(true){ + try { + Thread.sleep(15000); + if(module !=null){ + + if(relogged){ + System.out.println("module auto reconnecting to server"); + module = null; + relogged=!connectModule(false); + + } + } + //check + } catch (InterruptedException e) {} + } + } + /** + * launch the interface to connect the ivy bus to POW server + * @param args + */ + public static void main(String[] args) + { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + IvyIHM ivyihm = new IvyIHM(); + new Thread(ivyihm).start(); + } + }); + } + /** + * implements the action performed when the quit button is pressed + * @author genin + */ + class QuitAction implements ActionListener { + public void actionPerformed(ActionEvent e){ + Runnable code = new Runnable() { + public void run() { + System.exit(0); + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + + } + } + /** + * implements the action performed when the stop button is pressed + * @author genin + */ + class StopAction implements ActionListener { + public void actionPerformed(ActionEvent e){ + + Runnable code = new Runnable() { + public void run() { + module.stop_thread(); + logged = false;relogged = false; + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + } + } + + /** + * implements the action performed when the log button is pressed + * @author genin + */ + class LogAction implements ActionListener { + public void actionPerformed(ActionEvent e){ + if(!logged){ + Runnable code = new Runnable() { + public void run() { + connectModule(true); + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + } + else{ + JOptionPane.showMessageDialog(glob_fenetre, + "you are already logged and send information to server", + "Info",JOptionPane.WARNING_MESSAGE); + } + } + + } + /** + * performs all the step to run the ivy module + * @param displayWarning set if information about wrong login are displayed + * @return true if the https connection to the server is successful + */ + private boolean connectModule(boolean displayWarning){ + boolean res; + String login = login_txtfield.getText(); + String host = url_txtfield.getText(); + char[] pwd_array = pwd_txtfield.getPassword(); + String pwd = new String(pwd_array); + if (moreIsVisible){ + String siteName = site_txtfield.getText(); + String servletName = servlet_txtfield.getText(); + String strports ; + strports = portsStrings[port_field.getSelectedIndex()]; + int port=-1; + if (!strports.equals("none")){ + port = Integer.parseInt(strports); + } + String strProto = protocolsStrings[ protocol_field.getSelectedIndex()]; + System.out.println("port : "+port+"\tproto :"+ strProto); + PowUrl info = new PowUrl(strProto,host,port,siteName,servletName); + JOptionPane.showMessageDialog(glob_fenetre, + "you will be connected to "+ info.getWebUrl(), + "logging info", + JOptionPane.INFORMATION_MESSAGE); + module = new Ivy2Udp(this,info,login,pwd); + } + else{ + PowUrl info = new PowUrl("https",host,-1,site_txtfield.getText(), servlet_txtfield.getText()); + System.out.println("logging to : " + info.getWebUrl()); + module = new Ivy2Udp(this,info,login,pwd); + } + try { + module.getWebId(); + new Thread(module).start(); + logged = true; + res = true; + } catch (IvyConnectionExeption e) { + module.stop_thread(); + // echec du log + //custom title, error icon + System.out.println("erreur de connection : "+e.toString()); + if (displayWarning){ + JOptionPane.showMessageDialog(glob_fenetre, + "Your password or your login are not correct, retry please...\n"+ + "Be sure a valid SSL certificat exist in your $JAVA_HOME/jre/lib/security folder,\n"+ + "otherwise use InstallCert [hostname] java programm"+ + "\nit's possible also that server is not currenlty running", + "logging error", + JOptionPane.ERROR_MESSAGE); + } + logged = false; + res = false; + } + // clearing + for(int i = 0; i< pwd_array.length;i++){ + pwd_array[i]='0'; + } + return res; + } + + /** + * implements the action performed when the more button is pressed + * @author genin + */ + class MoreAction implements ActionListener { + JFrame globalFrame; + + MoreAction(JFrame g){ + globalFrame = g; + } + public void actionPerformed(ActionEvent e){ + Runnable code = new Runnable() { + public void run() { + if(moreIsVisible){ + contenuMore.setVisible(false);moreIsVisible=false;more_btn.setText("More...");} + else { + contenuMore.setVisible(true);moreIsVisible=true;more_btn.setText("Less..."); + } + globalFrame.pack(); + + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + + } + } + +} + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/MsgFilter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/MsgFilter.java new file mode 100755 index 0000000000..fbe63135dc --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/MsgFilter.java @@ -0,0 +1,36 @@ +package pow.ivyclient; +import java.util.HashSet; + +/** + * this class filters the message, thanks to their hash code + * it is used because Paparazzi send periodic messages that are often the same + * so we filter them to lighten the server load and the bandwidth of the udp channel + * @author genin + * + */ +public class MsgFilter { + + + private HashSet msgset; + /** + * create a message filter + */ + public MsgFilter(){ + msgset = new HashSet(); + } + /** + * inform whether the message is new or not + * @param msg + * @return true if the message is a new one and was added to the filter + */ + public boolean isNew(String msg){ + boolean res = msgset.add(msg); + return res; + } + /** + * empty the filter + */ + public void resetfilter(){ + msgset.clear(); + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/PowUrl.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/PowUrl.java new file mode 100755 index 0000000000..62a3f19376 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/ivyclient/PowUrl.java @@ -0,0 +1,40 @@ +package pow.ivyclient; +/** + * object which store all information about the url to log on the server + * @author genin + * + */ +public class PowUrl { + private String protocole="http"; + private int port =-1; + private String serverName; + private String webAppName; + private String servletLoginName; + /** + * create all the information requested to connect the ivy module to the server + * when all parameters are correct can give an url like + * https://paparazzi.fr/ServletPow/Login.srv + * @param protocol the protocol used to log to the server (HTTP by default) + * @param server the server name (paparazzi.fr) for example + * @param port a specific protocol port ( -1 means that this parameter is not used ) + * @param webapp the name of the application on the server (ServletPow for example) + * @param servletName the name of the login servlet (Login.srv) + */ + public PowUrl(String protocol,String server,int port,String webapp,String servletName){ + if (protocol.equals("https")) this.protocole="https"; + this.port = port; + this.serverName =server; + this.webAppName = webapp; + this.servletLoginName = servletName; + } + /** provides the server name to which the module is connected + * @return server hostname*/ + public String getServerName() {return serverName;} + /** provides the complete URL to log on the POW server + * @return the complete url to log in as a string */ + public String getWebUrl() { + if (port==-1) return ""+protocole+"://"+serverName+"/"+webAppName+"/"+servletLoginName; + else + return ""+protocole+"://"+serverName+":"+port+"/"+webAppName+"/"+servletLoginName; + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AjaxRqst.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AjaxRqst.java new file mode 100755 index 0000000000..8bffd549aa --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AjaxRqst.java @@ -0,0 +1,477 @@ +package pow.webserver; + + +import java.io.*; +import java.net.*; +import java.util.Iterator; +import java.util.Map; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +// SEE http://java.developpez.com/faq/xml/?page=dom +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.*; +import javax.xml.transform.stream.*; + +import org.w3c.dom.*; +import org.xml.sax.*; + +import org.apache.commons.codec.binary.Hex; + +/*import org.jdom.*; +import org.jdom.input.*; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; +import org.jdom.filter.*; +*/ +import java.util.*; + +import pow.AES; +import pow.ivyclient.BusIvy_; +import pow.webserver.Conf; + +/** + * Servlet implementation class ajaxRqst + * handles the different request from a web client which wants to give orders to a drone + * and it handles administrator queries to manage users' profiles + */ +public class AjaxRqst extends HttpServlet { + private static final long serialVersionUID = 1L; + private String default_folder="blabla"; + private ServletContext srvCtxt; + private Conf myConf; + /** + * @see HttpServlet#HttpServlet() + */ + public AjaxRqst() { + super(); + } + + /** + * init the servlet + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); // necessaire sinon getServletContext renvoie null dans doPost + default_folder = config.getServletContext().getRealPath(""); + srvCtxt = config.getServletContext(); + myConf = new Conf(default_folder,"pow_conf.xml"); + } + + /** + * handles different request from web users : + * orders to send to ivy buses and admin request to deal with users' account as well + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpSession session = request.getSession(true); + // recupere les parametres + PrintWriter out = response.getWriter(); + String order = request.getParameter("order"); // fpl_update... + if(order!=null) { + if (order.equals("fpl_update")) + { + System.out.println("move waypoint requested !!!"); + String wpt_name = request.getParameter("wpt_name"); + String aircraft_id = request.getParameter("aircraft_id"); + String wpt_id = request.getParameter("wpt_id"); + String new_alt = request.getParameter("new_alt"); + String new_lat = request.getParameter("new_lat"); + String new_lon = request.getParameter("new_lon"); + String new_alt_for_fpl = request.getParameter("new_alt_for_fpl"); + String dragged = request.getParameter("dragged"); + doFplUpdate(wpt_name,aircraft_id, wpt_id,new_alt, new_lat, new_lon, new_alt_for_fpl); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + + } + else if (order.equals("activate_block")){ + System.out.println("block activation requested !!!"); + String block_id = request.getParameter("block_id"); + String aircraft_id = request.getParameter("aircraft_id"); + doActivateBlock(block_id ,aircraft_id); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("modif_setting")){ + System.out.println("modif setting requested !!!"); + String aircraft_id = request.getParameter("aircraft_id"); + String setting_id = request.getParameter("setting_id"); + String newsetting_value = request.getParameter("value"); + doModifSetting(aircraft_id,setting_id,newsetting_value); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("create_user")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + String right = request.getParameter("right"); + HashSet set_of_drone = null; + if (right.equals("user")){ + String liste_drone = request.getParameter("immats"); + StringTokenizer st = new StringTokenizer(liste_drone,";"); + set_of_drone = new HashSet(); + try{ + while (st.hasMoreTokens()) { + set_of_drone.add( st.nextToken()); + } + } + catch (NoSuchElementException ex){} + } + boolean res = doCreateUser(login,pwd,right,set_of_drone); + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + } + else if (order.equals("delete_user")){ + String login = request.getParameter("login"); + boolean res = doDeleteUser(login); + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + } + else if (order.equals("info_user")){ + String login = request.getParameter("login"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + User usr = logTab.seek(login); + String right = getRight(usr.getRights()); + String liste = usr.getListDrone(); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("modify_user")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + String right = request.getParameter("right"); + String liste_drone = request.getParameter("liste_drone"); + StringTokenizer st = new StringTokenizer(liste_drone,";"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + User usr = logTab.seek(login); + if (!pwd.equals("")) {usr.setPwd(pwd);} + usr.setRights(getRight(right)); + usr.clearListDrone(); + try{ + while (st.hasMoreTokens()) { + usr.addDrone(st.nextToken()); + } + } + catch (NoSuchElementException ex){} + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("delete_drone")){ + String name = request.getParameter("name"); + try{ + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // read an xml file and build DOM structure + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + NodeList dronenameList = document.getElementsByTagName("drone"); + Element root= (Element) document.getElementsByTagName("immat").item(0); + int i = 0; + boolean doIt = true; + // removing node + while(i"); + + if(!doIt) out.println(""); + else out.println(""); + + out.println(""); + }catch(ParserConfigurationException pce){ + System.out.println("Erreur de configuration du parseur DOM"); + System.out.println("lors de l'appel à fabrique.newDocumentBuilder();"); + }catch(SAXException se){ + System.out.println("Erreur lors du parsing du document"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + }catch(IOException ioe){ + System.out.println("Erreur d'entrée/sortie"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + } + } + else if (order.equals("add_drone")){ + String name = request.getParameter("name"); + try{ + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // read an xml file and build DOM structure + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + Element root= (Element) document.getElementsByTagName("immat").item(0); + // inserting node + Element dronename = document.createElement("drone"); + dronename.setAttribute("name",name); + root.appendChild(dronename); + // save + writeXmlFile(document, default_folder + "/conf/"+"immat.xml"); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } catch(ParserConfigurationException pce){ + System.out.println("Erreur de configuration du parseur DOM"); + System.out.println("lors de l'appel à fabrique.newDocumentBuilder();"); + }catch(SAXException se){ + System.out.println("Erreur lors du parsing du document"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + }catch(IOException ioe){ + System.out.println("Erreur d'entrée/sortie"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + } + + } + else if (order.equals("delete_ivyusr")){ + String name = request.getParameter("login"); + boolean res ; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + logTab.remove(name); + res = !logTab.isInside(name); + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + + } + else if (order.equals("add_ivyusr")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + User n = new User(login,pwd,Rights.IVY); + try{ + logTab.insert(n); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } catch(AlreadyRegisteredUserException e){ + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + } + } + out.close(); + } + /** + * translate the right from string to a class + */ + private Rights getRight(String r) + { + if (r.equals("admin")) {return Rights.ADMIN;} + else if (r.equals("user")) {return Rights.USER;} + else {return Rights.VISITOR;} + } + /** + * translate the right from a class to a string + */ + private String getRight(Rights r) + { + if (r== Rights.ADMIN) {return "admin";} + else if (r== Rights.USER) {return "user";} + else {return "visitor";} + } + /** + * delete an user from the file which stores the users + */ + private boolean doDeleteUser(String login){ + boolean res ; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + logTab.remove(login); + res = !logTab.isInside(login); + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + return res; + } + /** + * create an user in the file which stores the users + */ + private boolean doCreateUser(String login, String pwd,String right,Set set_of_drone){ + boolean res; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + Rights rght = this.getRight(right); + User usr = new User(login,pwd,rght); + if (rght==Rights.USER){ + Iterator itr = set_of_drone.iterator(); + while (itr.hasNext()){ + usr.addDrone(itr.next()); + } + } + try{ + logTab.insert(usr); + res = true; + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + } + catch (AlreadyRegisteredUserException ex){ // existe deja + res = false; + } + return res; + + } + /** + * send an order to modif a setting of a drone which belongs to a specific ivy bus + */ + private void doModifSetting(String aircraft_web_id,String setting_id,String newsetting_value){ + String order = "DL_SETTING "+ aircraft_web_id + " " + setting_id + " " + newsetting_value; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + } + /** + * send an order to jump to a new block for a drone which belongs to a specific ivy bus + */ + private void doActivateBlock(String block_id,String aircraft_web_id){ + // send msg via serveur.java + String order = "JUMP_TO_BLOCK " + aircraft_web_id + " " + block_id ; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + } + /** + * send an order to move to a new waypoint for a drone which belongs to a specific ivy bus + */ + private void doFplUpdate(String wpt_name,String aircraft_web_id, String wpt_id, + String new_alt, String new_lat, String new_lon,String new_alt_for_fpl) { + // send msg via serveur.java + String order = "MOVE_WAYPOINT " + aircraft_web_id + " " + wpt_id + " " + new_lat + " " + new_lon + " " + new_alt ; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + }// end method + + + /**This method writes a DOM document to a file + * + * @param doc the xml Document + * @param filename the name of the file to write in + */ + private static void writeXmlFile(Document doc, String filename) + { + try { + // Prepare the DOM document for writing + Source source = new DOMSource(doc); + // Prepare the output file + File file = new File(filename); + Result result = new StreamResult(file); + // Write the DOM document to the file + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.transform(source, result); } + catch (TransformerConfigurationException e) { } + catch (TransformerException e) { } + } + + + /** + * send an order to a specific ivybus via udp + * @param ac_web_id the id of the drone on the web + * @param order the message to send + */ + private void sendOrder2Ivy(int ac_web_id,String order) + { + DatagramSocket socket=null; + try { + System.out.println("attempt to send order to ivy"); + socket = new DatagramSocket(); + socket.setSoTimeout(myConf.getSocketTimeout()); + ServletContext srvCtxt = getServletContext(); + // retrieve in the servlet context (shared memory) the table where the ivy session are stored + HashMap tableIvySession = (HashMap) srvCtxt.getAttribute("ivySessionTable"); + if ((socket!=null)&&(tableIvySession!=null)){ + byte buffer[] = new byte[myConf.getUdpSize()]; + Iterator> itr = tableIvySession.entrySet().iterator(); + BusIvy_ checked_bus=null; + boolean doIt=true; + // search for the session which owns the drone + while(itr.hasNext()&&doIt){ + checked_bus = itr.next().getValue().getBusIvy(); + if(checked_bus.isOwnBy(ac_web_id)){ + doIt = false ; + } + } + if(!doIt){ + InetAddress address = checked_bus.getAddress(); + SessionIvy session = tableIvySession.get(address); + AES aesCipher = session.getCipher(); + try{ + buffer = aesCipher.encrypt(order.getBytes()); + DatagramPacket DataEmitted = new DatagramPacket(buffer, buffer.length, address, myConf.portWebToIvy()); + try { + socket.send(DataEmitted); + System.out.println("\tmsg sended to ivy "+ address.toString()+":"+myConf.portWebToIvy()); + System.out.println("\t"+order); + //System.out.print("*"); + } catch (IOException e) { + System.out.println("\terreur msg not sended to " +address.toString()+":"+myConf.portWebToIvy()); + e.printStackTrace(); + } + } catch (IOException e) { + System.out.println("\terreur in encryption, msg not sended to " +address.toString()+":"+myConf.portWebToIvy()); + e.printStackTrace(); + } + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("\torder := "+(new String(Hex.encodeHex(order.getBytes())))); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("\torder := "+(new String(Hex.encodeHex(order.getBytes())))); + } + } + } + else + { + // error + System.out.println("\tunable to know socket udp or session "); + } + socket.close(); + } catch (SocketException e1) { + System.out.println("\tunable to open socket webtoIvy for an user request"); + e1.printStackTrace(); + } + finally{if(socket!=null){socket.close();socket=null;}} + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AlreadyRegisteredUserException.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AlreadyRegisteredUserException.java new file mode 100755 index 0000000000..674a33ce3c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/AlreadyRegisteredUserException.java @@ -0,0 +1,20 @@ +package pow.webserver; +/** + * exception to inform that a user cannot be created in the users' file + * because it exists yet + * @author genin + * + */ +public class AlreadyRegisteredUserException extends Exception { + private static final long serialVersionUID = 1L; + private User usr; + + public AlreadyRegisteredUserException (User u){ + usr = u; + } + + public String toString() { + return "AlreadyRegisteredUserException : login " + usr.getLogin() + " is already used" ; + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Conf.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Conf.java new file mode 100755 index 0000000000..1d9a0a1253 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Conf.java @@ -0,0 +1,165 @@ +package pow.webserver; +import java.io.*; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; +/** + * + * store useful data about the server configuration + * and database connection by + * reading a specific file place in the 'conf' folder of + * the web application + */ +public class Conf { + /** The mail of the administrator to contact if any problems occurs + * (appears in the help.jsp page. */ + private String mailAdmin; + /** The administrator login (not used). */ + private String adminLogin; + /** The port in which the module listen to get udp trames from ivy buses. */ + private int portIvyToWeb; + /** The dimension of the datagrams received. */ + private int tailleUdpTrame; + /** The passWord of the database */ + private String dbPassword; + /** The userName of the dataBase */ + private String dbUserName; + /** The Name of the dataBase */ + private String dataBaseName; + /** The timeout of the connection */ + private int udpTimeout; + /** The port in which messages from web are sent to ivy buses */ + private int portWebToIvy ; + /** period of time in millisec to reset the filter of waypoint_moved messages */ + private long time2resetFilter; + /** period of time in millisec to send all the parameter values for a specific drone */ + private long timeToSendValues; + /** time to wait for the acknowledgement of an order */ + private int order_response_timeout; + /** time to wait after a die event to remove the drone */ + private int dieEventTimeoutTime; + /** time to wait after receiving no data for a drone to remove the drone */ + private int dataEventTimeoutTime; + /** period of time to check for dead ivy buses in serveur.java*/ + private long time2checkDeadBuses; + /** how the database work VERBOSE or SILENT*/ + private DbMode dbMode; + /** + * + * @param default_folder folder of the web application on the server + * @param conf_filename name of the configuration file placed in 'conf' folder of the web application + */ + public Conf(String default_folder,String conf_filename) + { + try{ + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + // création d'un constructeur de documents + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // lecture du contenu d'un fichier XML avec DOM + File xml = new File(default_folder + "/conf/"+conf_filename); + Document document = constructeur.parse(xml); + Element mailAdmin_node = (Element)document.getElementsByTagName("mailWebAdmin").item(0); + Element adminLogin_node = (Element)document.getElementsByTagName("webAdminLogin").item(0); + Element portIvyToWeb_node = (Element)document.getElementsByTagName("portIvyToWeb").item(0); + Element taille_node = (Element)document.getElementsByTagName("sizeUdpTrame").item(0); + Element passWord_node = (Element)document.getElementsByTagName("dbPassword").item(0); + Element userName_node = (Element)document.getElementsByTagName("dbUserName").item(0); + Element dataBaseName_node = (Element)document.getElementsByTagName("dataBaseName").item(0); + Element timeout_node = (Element)document.getElementsByTagName("udpSocketTimeout").item(0); + Element portWebToIvy_node = (Element)document.getElementsByTagName("portWebToIvy").item(0); + Element time2resetFilter_node = (Element)document.getElementsByTagName("time2resetFilter").item(0); + Element timeToSendValuesy_node = (Element)document.getElementsByTagName("timeToSendValues").item(0); + Element order_response_timeout_node = (Element)document.getElementsByTagName("order_response_timeout").item(0); + Element dieEventTimeoutTime_node = (Element)document.getElementsByTagName("dieEventTimeoutTime").item(0); + Element dataEventTimeoutTime_node = (Element)document.getElementsByTagName("dataEventTimeoutTime").item(0); + Element time2checkDeadBuses_node = (Element)document.getElementsByTagName("time2checkDeadBuses").item(0); + + Element dbMode_node = (Element)document.getElementsByTagName("dbMode").item(0); + String dbMode_str = dbMode_node.getTextContent(); + if (dbMode_str.equals("verbose")){dbMode = DbMode.VERBOSE;} + else {dbMode = DbMode.SILENT;} + mailAdmin=mailAdmin_node.getTextContent(); + adminLogin=adminLogin_node.getTextContent(); + portIvyToWeb=Integer.parseInt(portIvyToWeb_node.getTextContent()); + tailleUdpTrame=Integer.parseInt(taille_node.getTextContent()); + dbPassword=passWord_node.getTextContent(); + dbUserName=userName_node.getTextContent(); + dataBaseName=dataBaseName_node.getTextContent(); + udpTimeout=Integer.parseInt(timeout_node.getTextContent()); + portWebToIvy=Integer.parseInt(portWebToIvy_node.getTextContent()); + time2resetFilter=Long.parseLong(time2resetFilter_node.getTextContent()); + timeToSendValues=Long.parseLong(timeToSendValuesy_node.getTextContent()); + order_response_timeout=Integer.parseInt(order_response_timeout_node.getTextContent()); + dieEventTimeoutTime=Integer.parseInt(dieEventTimeoutTime_node.getTextContent()); + dataEventTimeoutTime=Integer.parseInt(dataEventTimeoutTime_node.getTextContent()); + time2checkDeadBuses =Integer.parseInt(time2checkDeadBuses_node.getTextContent()); + } catch(ParserConfigurationException pce){ + System.out.println("error in loading configuration file : "+default_folder + "/conf/"+conf_filename); + pce.printStackTrace(); + }catch(SAXException se){ + System.out.println("error in loading configuration file : "+default_folder + "/conf/"+conf_filename); + se.printStackTrace(); + }catch(IOException ioe){ + System.out.println("error in loading configuration file : "+default_folder + "/conf/"+conf_filename); + ioe.printStackTrace(); + } + } + /** @return the udp port on which the server receive data from ivy buses */ + public int portIvyToWeb() + { + return portIvyToWeb; + } + /** @return the udp port on which the server send data to ivy buses */ + public int portWebToIvy() + { + return portWebToIvy; + } + /** @return the max size of an udp trame */ + public int getUdpSize() + { + return tailleUdpTrame; + } + /** @return the password to connect to the database*/ + public String getDBPassword() + { + return dbPassword; + } + /** @return the login to connect to the database*/ + public String getDBUserName() + { + return dbUserName; + } + /** @return the database name*/ + public String getDataBaseName() + { + return dataBaseName; + } + /** @return a time after what an exception is thrown if no message has been received by server*/ + public int getSocketTimeout() + { + return udpTimeout; + } + /** @return the mail to contact if any problem occurs */ + public String mailAdmin(){return mailAdmin;} + /** @return the login of the administrator of the site */ + public String adminLogin(){return adminLogin;} + /**@return period of time in millisec to reset the filter of waypoint_moved messages */ + public long getTime2resetFilter(){return time2resetFilter;} + /**@return period of time in millisec to send all the parameter values for a specific drone */ + public long getTimeToSendValues(){return timeToSendValues;} + /**@return time to wait for the acknowledgement of an order */ + public int getOrderResponseTimeout(){return order_response_timeout;} + /**@return time to wait after a die event to remove the drone */ + public int getDieEventTimeoutTime(){return dieEventTimeoutTime;} + /**@return time to wait after receiving no data for a drone to remove the drone */ + public int getDataEventTimeoutTime(){return dataEventTimeoutTime;} + /**@return period of time to check for dead ivy buses in serveur.java*/ + public long getTime2checkDeadBuses(){return time2checkDeadBuses;} + /**@return SILENT or VERBOSE */ + public DbMode getDbMode(){return dbMode;} +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbMode.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbMode.java new file mode 100755 index 0000000000..e7b55cc8a0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbMode.java @@ -0,0 +1,11 @@ +package pow.webserver; +/** + * specify how the database works + * @author genin + */ +public enum DbMode { + /** the database records all ivy messages the server receives */ + VERBOSE, + /** the database stores only connection activity of ivy client */ + SILENT +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbOrder.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbOrder.java new file mode 100755 index 0000000000..8af9576f31 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/DbOrder.java @@ -0,0 +1,18 @@ +package pow.webserver; +/** + * represents 4 kind of message stored in database + * CONNECT first connection of an ivy bus --> inform db + * DECONNECT ivy bus deconnected --> inform db + * ADD add message to db + * @author genin + */ +public enum DbOrder { + /** store the message and create a record in the 'connexion' table */ + CONNECT, + /** store the message and complete the end field in the 'connexion' table */ + DECONNECT, + /** just store the data in the log table*/ + ADD_DATA, + /** the message is an order coming from a web user */ + ADD_ORDER +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Greeting.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Greeting.java new file mode 100755 index 0000000000..00367b91d0 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Greeting.java @@ -0,0 +1,101 @@ +package pow.webserver; + +import java.io.File; +import java.io.PrintWriter; +import java.io.IOException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.*; +import java.util.Iterator; + +/** + * Servlet implementation class Greeting + * Handles the connection request from a new web client + * check the login's information and rights + */ +public class Greeting extends HttpServlet { + private static final long serialVersionUID = 1L; + private String default_folder="blabla"; + + public void init(ServletConfig config) throws ServletException { + super.init(config); // needed otherwise getServletContext return null in doPost method + default_folder = config.getServletContext().getRealPath(""); + // create a default web user file if it does not exist + File def_user_file = new File(default_folder + "/conf/"+"userTable.tbl"); + if (!def_user_file.exists()){ + User usr0 = new User("admin","pwdadmin",Rights.ADMIN); + User usr1 = new User("user1","pwduser1",Rights.USER); + usr1.addDrone("MJ5"); + usr1.addDrone("TJ1"); + UserTab logTab = new UserTab(); + try{ + logTab.insert(usr0); + logTab.insert(usr1); + } + catch(AlreadyRegisteredUserException e) {} + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + } + } + + public Greeting(){ + super(); + + } + + /** + * handles web user login request + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // jsp session + HttpSession session = request.getSession(true); + String login = request.getParameter("login"); + String password; + response.setContentType("text/html;charset=UTF-8"); + PrintWriter out = response.getWriter(); + if (login ==null) + { + login = "VISITOR"; + password=null; + session.setAttribute("login",login); + session.setAttribute("rights","visitor"); + // ok start the interface + out.println(""); + } + else { + // on verifie la validite du mot de passe + login = request.getParameter("login").toString(); + password = request.getParameter("password").toString(); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + if (logTab.checkUser(login, password)){ + + Rights r = logTab.seek(login).getRights(); + session.setAttribute("login",login); + if (r==Rights.ADMIN){ + session.setAttribute("rights","admin"); + } + else if (r==Rights.USER) { + session.setAttribute("rights","user"); + Iterator itr = logTab.getItrUsr(login); + String dronenameallowedtobectl=""; + if (itr!=null){ + while(itr.hasNext()){ + dronenameallowedtobectl+=itr.next()+";"; + // transmettre la liste des avions a la page web + } + } + session.setAttribute("dronectl",dronenameallowedtobectl); + } + else { + session.setAttribute("rights","visitor");// inutile normalement + } + // ok on lance l'interface + out.println(""); + } + else { + // we send the error page + out.println(""); + } + } + out.close(); + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/HeartBeat.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/HeartBeat.java new file mode 100755 index 0000000000..c7e6135892 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/HeartBeat.java @@ -0,0 +1,84 @@ +package pow.webserver; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.servlet.ServletContext; + +import pow.AES; + +public class HeartBeat implements Runnable{ + /** to retrieve AES cipher and InetAddress for a specific ivy bus*/ + + private ServletContext srvCtxt; + private int heartPeriod; + private boolean doIt; + private int port; + /** + * + * @param s the object which stores ivysessions + * @param h the period of the heartbeats + * @param p the udp port to use to send heartbeat + */ + public HeartBeat( ServletContext s,int h,int p){ + srvCtxt = s; + heartPeriod = h ; + port = p; + doIt= true; + } + /** + * send a periodic heartbeat message to every connected ivy bus + */ + public void run(){ + + String msg = "SERVER_HEARTBEAT"; + byte[] buffer; + DatagramSocket socket=null; + AES cipher ; + InetAddress ip_addr; + while(doIt) + { + try { + Thread.sleep(heartPeriod); + socket = new DatagramSocket(); + HashMap tableIvySession = (HashMap) srvCtxt.getAttribute("ivySessionTable"); + if (tableIvySession!=null){ + Iterator> itr = tableIvySession.entrySet().iterator(); + while(itr.hasNext()){ + Map.Entry n= itr.next(); + cipher = n.getValue().getCipher(); + ip_addr = n.getKey();System.out.println("send heart to "+ ip_addr); + buffer = cipher.encrypt(msg.getBytes()); + DatagramPacket DataEmitted = new DatagramPacket(buffer, buffer.length, ip_addr, port); + try { + socket.send(DataEmitted); + //System.out.println("\nHeartbeat sended to "+ip_addr); + } catch (IOException e) { + System.out.println("\tHeartbeat pbm");e.printStackTrace(); + } + } + } + + } catch (InterruptedException e) {System.out.println("\tHeartbeat pbm");e.printStackTrace(); } + catch (SocketException ex) { System.out.println("\tHeartbeat pbm");ex.printStackTrace();} + catch(BadPaddingException ex){System.out.println("\tHeartbeat pbm");ex.printStackTrace();} + catch(IllegalBlockSizeException ex){System.out.println("\tHeartbeat pbm");ex.printStackTrace();} + catch(IOException ex){System.out.println("\tHeartbeat pbm");ex.printStackTrace();} + finally{if(socket!=null){socket.close();socket = null ;} } + } + } + /** + * stop the heartbeat process of the server + */ + public void stop_thread(){ + doIt=false; + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Ivy2TomcatHttpServer.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Ivy2TomcatHttpServer.java new file mode 100755 index 0000000000..a310d00187 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Ivy2TomcatHttpServer.java @@ -0,0 +1,334 @@ +package pow.webserver; + +import java.io.PrintWriter; +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.fileupload.*; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; + +import pow.AES; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.List; +import java.util.Iterator; +import java.io.File; +import java.net.InetAddress; +/** + * Handles the connection request from a new ivy bus + * provide a unique id for the ivy bus + * provide a unique id for each new drone on a ivy bus + * handles the uploading of the configuration files for each new drone on a ivy bus + */ +public class Ivy2TomcatHttpServer extends HttpServlet { + private static final long serialVersionUID = 1L; + private static int webIdCount = 1; + private static int droneIdCount = 1; + private ServletContext srvCtxt = null; + private String default_folder="blabla"; + private HashMap tableIvySession ;// correspondance webid,session ivy + private Conf myConf; + + /** + * + */ + public Ivy2TomcatHttpServer() { + super(); + } + + public void init(ServletConfig config) throws ServletException { + + // TODO clear the upload folder ? + srvCtxt = config.getServletContext(); + default_folder = config.getServletContext().getRealPath(""); + // + myConf = new Conf(default_folder,"pow_conf.xml"); + // + String filepath = default_folder + "/upload"; + File repository = new File(filepath); + deleteDirectory(repository); + repository = new File(filepath); + if ((!repository.exists()) && (!repository.isDirectory())) { + repository.mkdir(); // exists isDirectory() + } + tableIvySession = new HashMap(); + // put the table in the memory shared by all the servlet of the web application (context) + config.getServletContext().setAttribute("ivySessionTable", tableIvySession); + // create a default ivy user file if it does not exist + File def_user_file = new File(default_folder + "/conf/"+"userIvyTable.tbl"); + if (!def_user_file.exists()){ + User usr0 = new User("admin_ivy","pwdadmin_ivy",Rights.IVY); + UserTab logTab = new UserTab(); + try{ + logTab.insert(usr0); + } + catch(AlreadyRegisteredUserException e) {} + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + } + } + /** + * delete recursivly a folder + * @param path the path of the folder to delete + * @return true if the folder is correctly deleted + */ + static private boolean deleteDirectory(File path) { + boolean resultat = true; + + if( path.exists() ) { + File[] files = path.listFiles(); + for(int i=0; i"); + out.println("1"); + out.println(""+newWebId+""); + out.println(""+aesKey+""); + out.println(""+aesIv+""); + out.println(""+myConf.getTime2resetFilter()+""); + out.println(""+myConf.getTimeToSendValues()+""); + out.println(""+myConf.getSocketTimeout()+""); + out.println(""); + InetAddress remoteClient = InetAddress.getByName(request.getRemoteAddr()); + SessionIvy session = new SessionIvy(login,newWebId,cipher_aes,remoteClient); + tableIvySession.put(remoteClient,session); + out.close(); + System.out.println("**************************************"); + System.out.println("Web Id sended = " + newWebId); + System.out.println("remote client = " + request.getRemoteAddr() + " host=" + request.getRemoteHost() + " port=" + request.getRemotePort()); + System.out.println("key sended = " + aesKey ); + System.out.println("iv parameter = " + aesIv ); + System.out.println("**************************************"); + } + catch (Exception ex){ + PrintWriter out = response.getWriter(); + out.println(""); + out.println("2"); + out.println(""); + out.close(); + System.out.println("AES encryption not supported by server!!!\n"); + ex.printStackTrace(); + } + } + else{ + PrintWriter out = response.getWriter(); + out.println(""); + out.println("3"); + out.println(""); + out.close(); + System.out.println("DataBase unable to give a webId!!!\n"); + } + } + else { + PrintWriter out = response.getWriter(); + out.println(""); + out.println("0"); + out.println(""); + out.close(); + System.out.println("Not authorized access attempt from an ivy client!!!"); + } + } + else if (order.equals("reconnect")) + { + + } + else if (order.equals("requestNewDroneWebId")) + {// client has a webId (not in multipart post) yet and wants to do somtheing else than uploading + System.out.println("Drone Web Id for new drone requested !!!"); + String ivyId = request.getParameter("ivyWebId"); + System.out.println("ivyId " + ivyId + " request new Drone Web Id for unknown ivy drone ");// + ivyDroneId); + int webidsession = Integer.parseInt(ivyId); + int newdroneWebId = droneIdCount;droneIdCount++; + PrintWriter out = response.getWriter(); + out.println(""); + out.close(); + System.out.println("new drone Web Id sended (dronewebid = "+newdroneWebId+") !!!"); + } + } + else // client has a webId ( in multipart post) yet and wants to upload conf files + { + System.out.println("uploading file requested..."); + String res = uploadFile(request); + PrintWriter out = response.getWriter(); + out.println(""); + out.println(res); + out.println(""); + out.close(); + }// end if check IvyId + + } + + + /** + * contact database if any to have a new webid + * @return a webid>0 or -1 if failed + */ + public int getWebId(String login){ + int res ; + Connection connection = null; + Statement stmt = null; + ResultSet rs = null; + // récupération du dbName,dbLogin et dbPwd + + String dbName = (String) srvCtxt.getAttribute("dbName"); + String dbUser = (String) srvCtxt.getAttribute("dbUser"); + String dbPwd = (String) srvCtxt.getAttribute("dbPwd"); + String url = "jdbc:mysql://localhost/"+dbName; + try{ + Class.forName("com.mysql.jdbc.Driver").newInstance(); + connection = DriverManager.getConnection(url,dbUser,dbPwd); + stmt = connection.createStatement(); + Timestamp t = new Timestamp(System.currentTimeMillis()); + String monHeure = t.toString(); + stmt.executeUpdate("INSERT INTO connexion (login,start) VALUES ('"+login+"','"+monHeure+"')"); + rs = stmt.executeQuery("SELECT MAX(webId) as nextwebid FROM connexion"); + rs.first(); + if (!rs.wasNull()) res = rs.getInt("nextwebid"); + else res = -1; + } + catch(Exception e){ + e.printStackTrace(); + System.out.println("attempt to get new web id from database failed"); + res= -1; + } + finally{ + if(connection!=null){try{connection.close();}catch(Exception e){e.printStackTrace();}} + webIdCount++; + } + return res; + } + + /* + * handles the upload of a file from a ivy bus to the server via http + */ + private String uploadFile(HttpServletRequest request){ + boolean isMultipart = ServletFileUpload.isMultipartContent(request); + String resu = "-1"; + List items=null; + String webid="zzz"; + String droneid = "yyy"; + String filepath=""; + + System.out.println("!!!def upload rep !!! " + default_folder); + File uploadedFile; + if (isMultipart) + { + + // Create a factory for disk-based file items + FileItemFactory factory = new DiskFileItemFactory(); + // Set factory constraints + // factory.setSizeThreshold(yourMaxMemorySize); + // factory.setRepository(yourTempDirectory); + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(factory); + // Set overall request size constraint + // upload.setSizeMax(yourMaxRequestSize); + // Parse the request + try { + items = upload.parseRequest(request); + // Process the uploaded items + // searching for the webId parameter + boolean doIt1 = true;boolean doIt2 = true; + Iterator iter = items.iterator(); + while ((doIt1||doIt2) && iter.hasNext()) { + FileItem item = (FileItem) iter.next(); + if (item.isFormField()) { + String fieldName = item.getFieldName(); + if (fieldName.equals("ivyWebId")){ + doIt1 = false ; + webid = item.getString(); + } + else if (fieldName.equals("droneWebId")){ + doIt2 = false; + droneid = item.getString(); + } + } + } + filepath = default_folder +"/upload/"+droneid; + File repository = new File(filepath); + if ((!repository.exists()) && (!repository.isDirectory())) { + boolean res=repository.mkdir(); // exists isDirectory() + System.out.println("repertoire "+filepath+" cree ? " + res); + } + if (!webid.equals("zzz")){ + // searching for file parameters + iter = items.iterator(); + while (iter.hasNext()) { + FileItem item = (FileItem) iter.next(); + if (!item.isFormField()) { // check the type of the item + String fileName = item.getName(); + //String contentType = item.getContentType(); + //boolean isInMemory = item.isInMemory(); + //long sizeInBytes = item.getSize(); + uploadedFile = new File(filepath+"/"+fileName); + try { + item.write(uploadedFile); + resu = "1"; + System.out.println("file: "+fileName+" for web drone "+droneid+" was uploaded successfully"); + } catch (Exception e) { + resu = "0"; + System.out.println("unable to write file on server : "+droneid+"/"+fileName); + e.printStackTrace(); + } + } //end if + } // end while + } + } catch (FileUploadException e) { + System.out.println("unable to parse client request "); + e.printStackTrace(); + } + } // end if multipart + return resu; + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/IvyMsg.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/IvyMsg.java new file mode 100755 index 0000000000..ecbbdea270 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/IvyMsg.java @@ -0,0 +1,57 @@ +package pow.webserver; + +/** + * represents information which are sended by the source event to the database on the queue fifo + * @author genin + * + */ +public class IvyMsg { + + private int webId; + private long num_msg; + private String timeMsg;//"d:M:y:HH:mm:ss" add 2000 to d + private String ivyMsg; + private DbOrder order; + + public IvyMsg(int wId,long num,String date,String msg,DbOrder order){ + webId = wId; + num_msg = num; + timeMsg = date; + ivyMsg = msg; + this.order = order; + } + + public IvyMsg(int wId,long num,String date,String msg){ + webId = wId; + num_msg = num; + timeMsg = date; + ivyMsg = msg; + this.order = null; + } + + public IvyMsg(int wId){ + webId = wId; + num_msg = -1; + timeMsg = "-1"; + ivyMsg = "deconnect all drone"; + this.order = DbOrder.DECONNECT; + } + /** @return the ivy web ivy which has sent the message */ + public int getWebId(){return webId;} + /** @return the number of the message */ + public long getNumMsg() {return num_msg;} + /** @return the time at which the message was sent*/ + public String getTimeMsg() {return timeMsg;} + /** @return the ivy message */ + public String getIvyMsg() {return ivyMsg;} + /** @return an order on how to store the ivy message in database */ + public DbOrder getOrder() {return order;} + /** + * specify how to store the message in database + * @see DbOrder + * @param o the way to store the message in database + */ + public void setOrder(DbOrder o ) { order=o;} + + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Log.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Log.java new file mode 100755 index 0000000000..7dce539a6c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Log.java @@ -0,0 +1,73 @@ +package pow.webserver; +import java.io.*; +import java.util.Calendar; +/** + * Handles the writing of a log in a file + * @author from V1 + * @since V1 + */ +public class Log { + + private File oFile = null; + private FileWriter oFileWriter = null; + private BufferedWriter oBufferedWriter = null; + /** + * create a log file into the log floder of the web application + * @param path the complete path of the web application + */ + public Log(String path) + { + Calendar Today = Calendar.getInstance(); + String fileName = String.valueOf(Today.get(Calendar.DAY_OF_MONTH)) + + String.valueOf(Today.get(Calendar.MONTH)) + + String.valueOf(Today.get(Calendar.YEAR)) + + String.valueOf(Today.get(Calendar.HOUR_OF_DAY)) + + String.valueOf(Today.get(Calendar.MINUTE)) + + String.valueOf(Today.get(Calendar.SECOND)) + + ".log"; + + try + { + oFile = new File(path+"/log/" + fileName); + oFile.createNewFile(); + oFileWriter = new FileWriter(oFile); + oBufferedWriter = new BufferedWriter(oFileWriter); + + oBufferedWriter.write("##########################################"); oBufferedWriter.newLine(); + oBufferedWriter.write("########## PAPARAZZI ON THE WEB ##########"); oBufferedWriter.newLine(); + oBufferedWriter.write("##########################################"); oBufferedWriter.newLine(); + oBufferedWriter.newLine(); + oBufferedWriter.write("Beginning of log : "); oBufferedWriter.newLine(); + oBufferedWriter.newLine(); + oBufferedWriter.flush(); + } + catch(IOException ex) + { + System.out.println("No log file created "); + ex.printStackTrace(); + } + } + /** + * write a string in log file and on stdout + * @param writing the string to write in the log file + */ + public void write(String writing) + { + Calendar Now = Calendar.getInstance(); + String Time = String.valueOf(Now.get(Calendar.HOUR_OF_DAY)) + ":" + + String.valueOf(Now.get(Calendar.MINUTE)) + ":" + + String.valueOf(Now.get(Calendar.SECOND)); + writing = writing.trim(); + try + { + oBufferedWriter.write(Time + " -> " + writing); oBufferedWriter.newLine(); + oBufferedWriter.flush(); + System.out.println("\nlog at : " + Time + " -> " + writing); + } + catch(IOException ex) + { + System.out.println(ex.getMessage()); + } + + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Md5.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Md5.java new file mode 100755 index 0000000000..95e2c840ba --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Md5.java @@ -0,0 +1,90 @@ +package pow.webserver; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +/** + * tool class to implemente MD5 encoding + * ( found on the web ) + */ +public class Md5 +{ + /** + * @param password the string to encode with MD5 algorithm + * @return the encoded string with MD5 algorithm + */ + public static String encode(String password) + { + byte[] uniqueKey = password.getBytes(); + byte[] hash = null; + + try + { + hash = MessageDigest.getInstance("MD5").digest(uniqueKey); + } + catch (NoSuchAlgorithmException e) + { + throw new Error("No MD5 support in this VM."); + } + + StringBuilder hashString = new StringBuilder(); + for (int i = 0; i < hash.length; i++) + { + String hex = Integer.toHexString(hash[i]); + if (hex.length() == 1) + { + hashString.append('0'); + hashString.append(hex.charAt(hex.length() - 1)); + } + else + hashString.append(hex.substring(hex.length() - 2)); + } + return hashString.toString(); + } +/* + // example to adapt for SHA encoding + public static String hash(String plaintext) { + MessageDigest md = null; + + try { + md = MessageDigest.getInstance("SHA-1"); // SHA-1 generator instance + } catch(NoSuchAlgorithmException e) { + return ""; + } + + try { + //8859_1 ou UTF-8 + md.update(plaintext.getBytes("UTF-8")); // Message summary generation + } catch(UnsupportedEncodingException e) { + return ""; + } + + byte raw[] = md.digest(); // Message summary reception + + try{ + String hash = new String(org.apache.commons.codec.binary.Base64.encodeBase64(raw),"UTF-8"); + //String hash = new String(raw); + return hash; + } + catch (UnsupportedEncodingException use){ + return ""; + } + } + + */ + /** + * example + */ + public static void main(String[] args) + { + if (args.length != 1) + { + System.out.println("Usage: java Md5 "); + return; + } + + String toEncode = args[0]; + + System.out.println("Original string ... " + toEncode); + System.out.println("String MD5 ........ " + encode(toEncode)); + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Rights.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Rights.java new file mode 100755 index 0000000000..b0fda632c2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Rights.java @@ -0,0 +1,16 @@ +package pow.webserver; +/** + * describe the different rights a web user can have + * @author genin + * + */ +public enum Rights { + /** can only see the drones */ + VISITOR, + /** can pilot all the drones and manage user's account and create others administrators*/ + ADMIN, + /** can pilot only specific drones which are specified in its user account */ + USER, + /** specify an ivy user which send data to the server via UDP */ + IVY +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SGBDfeeder.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SGBDfeeder.java new file mode 100755 index 0000000000..fd566db8ef --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SGBDfeeder.java @@ -0,0 +1,154 @@ +package pow.webserver; + +import java.sql.Connection; +import java.sql.DriverManager; +//import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.concurrent.LinkedBlockingQueue; + + +/** + * thread which waits for ivy messages sent by event source (serveur.java) + * and stores them into a mysql database + * the ivy messages are extracted from a blocking queue (fifo) + * parameter of the database are extracted from conf file + * @link http://dev.mysql.com/doc/refman/5.0/fr/sql-syntax.html + */ +public class SGBDfeeder implements Runnable { + + private String dbName; + private String dbLogin; + private String dbPwd; + private String url ; + private LinkedBlockingQueue fifo; + private boolean doIt; + private DbMode mode; + /** + * create a thread which fill the database with the message it extracts from the fifo + * @param dbname the name of the database + * @param dbuser the user login to connect to the database + * @param dbpwd the user password to connect to the database + */ + public SGBDfeeder(String dbname,String dbuser,String dbpwd,DbMode mode){ + //fifo = new ConcurrentLinkedQueue(); + fifo = new LinkedBlockingQueue(); + dbName = dbname; + dbLogin= dbuser; + dbPwd = dbpwd; + url = "jdbc:mysql://localhost/"+dbName; + doIt = true; + this.mode = mode; + } + /** + * + * @return the fifo to communicate with the database feeder + */ + public LinkedBlockingQueue getQueueFIFO(){ + return fifo; + } + /** + * stop the thread by ending run method + * used caused Thread.stop is now deprecated + */ + public void kill(){ + doIt= false; + } + /** + * listens fifo queue and stores ivy messages in database + * if the message has the DECONNECT type it also fills the end field corresponding + * to this ivy session into the 'connexion' table + */ + public void run() { + while(doIt){ + try { + IvyMsg msg = fifo.take(); // fetch an ivy message in the fifo or wait + // store it in db + DbOrder order = msg.getOrder(); + switch(order){ + case DECONNECT :{ + storeDeconnectionMsg(msg.getIvyMsg(), msg.getWebId()); + break; + } + default : { + if (mode == DbMode.VERBOSE) // if mode is silent, we don't store messages in db + { + storeMsg(msg.getIvyMsg(), msg.getWebId()); + } + break; + } + } + } catch (InterruptedException e) { + System.out.println("database exception : no receiving data"); + //e.printStackTrace(); + } + } + System.out.println("fin thread datafeeder ok"); + } + + /** + * connecting to db and store a no specific message + * @param msg + * @param webId + */ + private void storeMsg(String msg, int webId){ + Connection connection = null; + Statement stmt = null; + // ResultSet rs; + try { + Class.forName("com.mysql.jdbc.Driver").newInstance(); + connection = DriverManager.getConnection(url,dbLogin,dbPwd); + try{ + stmt = connection.createStatement(); + stmt.executeUpdate("INSERT INTO log (msg,webId) VALUES ('"+msg+"',"+webId+")"); + } + catch (SQLException ex) { + System.out.println("SQLException: " + ex.getMessage()); + System.out.println("SQLState: " + ex.getSQLState()); + System.out.println("VendorError: " + ex.getErrorCode()); + } + } + catch (SQLException ex) {System.out.println("unable to connect to db");} + catch (ClassNotFoundException ex) {ex.printStackTrace();} + catch (IllegalAccessException ex){ex.printStackTrace();} + catch ( InstantiationException ex){ex.printStackTrace();} + finally + { + if(connection!=null){try{connection.close();}catch(Exception e){e.printStackTrace();}} + } + } + /** + * deconnection message , fill the end field in connexion table + * and store the message in log table + */ + private void storeDeconnectionMsg(String msg, int webId){ + Connection connection = null; + Statement stmt = null; + Timestamp t = new Timestamp(System.currentTimeMillis()); + String monHeure = t.toString(); + try { + Class.forName("com.mysql.jdbc.Driver").newInstance(); + connection = DriverManager.getConnection(url,dbLogin,dbPwd); + try{ + stmt = connection.createStatement(); + stmt.executeUpdate("UPDATE connexion SET end='"+monHeure+"' WHERE webId="+webId); + stmt = connection.createStatement(); + stmt.executeUpdate("INSERT INTO log (msg,webId) VALUES ('"+msg+"',"+webId+")"); + } + catch (SQLException ex) { + System.out.println("SQLException: " + ex.getMessage()); + System.out.println("SQLState: " + ex.getSQLState()); + System.out.println("VendorError: " + ex.getErrorCode()); + } + } + catch (SQLException ex) {System.out.println("unable to connect to db");} + catch (ClassNotFoundException ex) {ex.printStackTrace();} + catch (IllegalAccessException ex){ex.printStackTrace();} + catch ( InstantiationException ex){ex.printStackTrace();} + finally + { + if(connection!=null){try{connection.close();}catch(Exception e){e.printStackTrace();}} + } + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SSLUtilities.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SSLUtilities.java new file mode 100755 index 0000000000..dc2cce1cfd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/SSLUtilities.java @@ -0,0 +1,322 @@ +package pow.webserver; + +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * This class provide various static methods that relax X509 certificate and + * hostname verification while using the SSL over the HTTP protocol. + * call: + * SSLUtilities.trustAllHostnames() to turn off the default hostname verification on HTTPS connection; + * SSLUtilities.trustAllHttpsCertificates() to turn off the default certificate validation on HTTPS connection. + * + * @link http://en.wikibooks.org/wiki/WebObjects/Web_Services/How_to_Trust_Any_SSL_Certificate + * @author Francis Labrie + */ +public final class SSLUtilities { + + /** + * Hostname verifier for the Sun's deprecated API. + * + * @deprecated see {@link #_hostnameVerifier}. + */ + private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier; + /** + * Thrust managers for the Sun's deprecated API. + * + * @deprecated see {@link #_trustManagers}. + */ + private static com.sun.net.ssl.TrustManager[] __trustManagers; + /** + * Hostname verifier. + */ + private static HostnameVerifier _hostnameVerifier; + /** + * Thrust managers. + */ + private static TrustManager[] _trustManagers; + + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. This method uses the old deprecated API from the + * com.sun.ssl package. + * + * @deprecated see {@link #_trustAllHostnames()}. + */ + private static void __trustAllHostnames() { + // Create a trust manager that does not validate certificate chains + if(__hostnameVerifier == null) { + __hostnameVerifier = new _FakeHostnameVerifier(); + } // if + // Install the all-trusting host name verifier + com.sun.net.ssl.HttpsURLConnection. + setDefaultHostnameVerifier(__hostnameVerifier); + } // __trustAllHttpsCertificates + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. This method uses the + * old deprecated API from the com.sun.ssl package. + * + * @deprecated see {@link #_trustAllHttpsCertificates()}. + */ + private static void __trustAllHttpsCertificates() { + com.sun.net.ssl.SSLContext context; + + // Create a trust manager that does not validate certificate chains + if(__trustManagers == null) { + __trustManagers = new com.sun.net.ssl.TrustManager[] + {new _FakeX509TrustManager()}; + } // if + // Install the all-trusting trust manager + try { + context = com.sun.net.ssl.SSLContext.getInstance("SSL"); + context.init(null, __trustManagers, new SecureRandom()); + } catch(GeneralSecurityException gse) { + throw new IllegalStateException(gse.getMessage()); + } // catch + com.sun.net.ssl.HttpsURLConnection. + setDefaultSSLSocketFactory(context.getSocketFactory()); + } // __trustAllHttpsCertificates + + /** + * Return true if the protocol handler property java. + * protocol.handler.pkgs is set to the Sun's com.sun.net.ssl. + * internal.www.protocol deprecated one, false + * otherwise. + * + * @return true if the protocol handler + * property is set to the Sun's deprecated one, false + * otherwise. + */ + private static boolean isDeprecatedSSLProtocol() { + return("com.sun.net.ssl.internal.www.protocol".equals(System. + getProperty("java.protocol.handler.pkgs"))); + } // isDeprecatedSSLProtocol + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. + */ + private static void _trustAllHostnames() { + // Create a trust manager that does not validate certificate chains + if(_hostnameVerifier == null) { + _hostnameVerifier = new FakeHostnameVerifier(); + } // if + // Install the all-trusting host name verifier: + HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier); + } // _trustAllHttpsCertificates + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. + */ + private static void _trustAllHttpsCertificates() { + SSLContext context; + + // Create a trust manager that does not validate certificate chains + if(_trustManagers == null) { + _trustManagers = new TrustManager[] {new FakeX509TrustManager()}; + } // if + // Install the all-trusting trust manager: + try { + context = SSLContext.getInstance("SSL"); + context.init(null, _trustManagers, new SecureRandom()); + } catch(GeneralSecurityException gse) { + throw new IllegalStateException(gse.getMessage()); + } // catch + HttpsURLConnection.setDefaultSSLSocketFactory(context. + getSocketFactory()); + } // _trustAllHttpsCertificates + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. + */ + public static void trustAllHostnames() { + // Is the deprecated protocol setted? + if(isDeprecatedSSLProtocol()) { + __trustAllHostnames(); + } else { + _trustAllHostnames(); + } // else + } // trustAllHostnames + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. + */ + public static void trustAllHttpsCertificates() { + // Is the deprecated protocol setted? + if(isDeprecatedSSLProtocol()) { + __trustAllHttpsCertificates(); + } else { + _trustAllHttpsCertificates(); + } // else + } // trustAllHttpsCertificates + + /** + * This class implements a fake hostname verificator, trusting any host + * name. This class uses the old deprecated API from the com.sun. + * ssl package. + * + * @author Francis Labrie + * + * @deprecated see {@link SSLUtilities.FakeHostnameVerifier}. + */ + public static class _FakeHostnameVerifier + implements com.sun.net.ssl.HostnameVerifier { + + /** + * Always return true, indicating that the host name is an + * acceptable match with the server's authentication scheme. + * + * @param hostname the host name. + * @param session the SSL session used on the connection to + * host. + * @return the true boolean value + * indicating the host name is trusted. + */ + public boolean verify(String hostname, String session) { + return(true); + } // verify + } // _FakeHostnameVerifier + + + /** + * This class allow any X509 certificates to be used to authenticate the + * remote side of a secure socket, including self-signed certificates. This + * class uses the old deprecated API from the com.sun.ssl + * package. + * + * @author Francis Labrie + * + * @deprecated see {@link SSLUtilities.FakeX509TrustManager}. + */ + public static class _FakeX509TrustManager + implements com.sun.net.ssl.X509TrustManager { + + /** + * Empty array of certificate authority certificates. + */ + private static final X509Certificate[] _AcceptedIssuers = + new X509Certificate[] {}; + + + /** + * Always return true, trusting for client SSL + * chain peer certificate chain. + * + * @param chain the peer certificate chain. + * @return the true boolean value + * indicating the chain is trusted. + */ + public boolean isClientTrusted(X509Certificate[] chain) { + return(true); + } // checkClientTrusted + + /** + * Always return true, trusting for server SSL + * chain peer certificate chain. + * + * @param chain the peer certificate chain. + * @return the true boolean value + * indicating the chain is trusted. + */ + public boolean isServerTrusted(X509Certificate[] chain) { + return(true); + } // checkServerTrusted + + /** + * Return an empty array of certificate authority certificates which + * are trusted for authenticating peers. + * + * @return a empty array of issuer certificates. + */ + public X509Certificate[] getAcceptedIssuers() { + return(_AcceptedIssuers); + } // getAcceptedIssuers + } // _FakeX509TrustManager + + + /** + * This class implements a fake hostname verificator, trusting any host + * name. + * + * @author Francis Labrie + */ + public static class FakeHostnameVerifier implements HostnameVerifier { + + /** + * Always return true, indicating that the host name is + * an acceptable match with the server's authentication scheme. + * + * @param hostname the host name. + * @param session the SSL session used on the connection to + * host. + * @return the true boolean value + * indicating the host name is trusted. + */ + public boolean verify(String hostname, + javax.net.ssl.SSLSession session) { + return(true); + } // verify + } // FakeHostnameVerifier + + + /** + * This class allow any X509 certificates to be used to authenticate the + * remote side of a secure socket, including self-signed certificates. + * + * @author Francis Labrie + */ + public static class FakeX509TrustManager implements X509TrustManager { + + /** + * Empty array of certificate authority certificates. + */ + private static final X509Certificate[] _AcceptedIssuers = + new X509Certificate[] {}; + + + /** + * Always trust for client SSL chain peer certificate + * chain with any authType authentication types. + * + * @param chain the peer certificate chain. + * @param authType the authentication type based on the client + * certificate. + */ + public void checkClientTrusted(X509Certificate[] chain, + String authType) { + } // checkClientTrusted + + /** + * Always trust for server SSL chain peer certificate + * chain with any authType exchange algorithm types. + * + * @param chain the peer certificate chain. + * @param authType the key exchange algorithm used. + */ + public void checkServerTrusted(X509Certificate[] chain, + String authType) { + } // checkServerTrusted + + /** + * Return an empty array of certificate authority certificates which + * are trusted for authenticating peers. + * + * @return a empty array of issuer certificates. + */ + public X509Certificate[] getAcceptedIssuers() { + return(_AcceptedIssuers); + } // getAcceptedIssuers + } // FakeX509TrustManager +} // SSLUtilities diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Serveur.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Serveur.java new file mode 100755 index 0000000000..6586210480 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/Serveur.java @@ -0,0 +1,665 @@ +package pow.webserver; + +import nl.justobjects.pushlet.core.Dispatcher; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventSource; +import java.io.*; +import java.net.*; +import java.util.*; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.servlet.ServletContext; + +import org.apache.commons.codec.binary.Hex; +import org.jdom.*; +import org.jdom.input.*; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; + +import pow.AES; +import pow.ivyclient.BusIvy_; + +import java.util.HashMap; +import java.util.List; +import java.util.Iterator; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class which receive a datagramm from ivy bus via UDP + * transforms it into a Pushlet event and send it to the Pushlet server + * in order that it will be sent to web clients + * @author genin + */ +public class Serveur { +static public class IvyEventSource implements EventSource , Runnable { + + private ServletContext srvCtxt; + private String default_folder = "blabla"; + HeartBeat heartBeatRun; + Thread thread = null; + private boolean active = false; + private int restarts = 1; + /* *********************** */ + private static Log myLog; + private static Conf myConf; + /* *********************** */ + private DatagramSocket socket; + private String[] myDataSplited; // Tableau contenant toutes les donnees envoyees + /* *********************** */ + private static long time2checkDeadBuses = 30*1000; // period of time where dead bus are removed from bus list + /* *********************** */ + /* to retrieve AES cipher for a specific ivy bus*/ + private HashMap tableIvySession; + /* ********* */ + private IvyMsg currentIvyMsg=null; + /* ********* */ + private LinkedBlockingQueue fifoToDatabase; + private SGBDfeeder t_sgbd_feeder; + private Thread dbThread; + /* ********* */ + public IvyEventSource() { + System.out.println(" Thread de recuperation des données IVY"); + } + /* *********************************** */ + /* EventSource specific functions */ + /* *********************************** */ + /** + * Activate the event source. + * load configuration, create log and create link to database MySQL + * ! setServletContext method should be called before activating + * @see nl.justobjects.pushlet.core.EventSourceManager class + */ + synchronized public void activate() { + System.out.println("activating the event source...."); + // creating log + myLog = new Log(default_folder); + // loading configuration + try {loadingConfiguration();} catch (Exception e) { + System.out.println("erreur loading configuration"); + e.printStackTrace();} + // reading configuration + time2checkDeadBuses = myConf.getTime2checkDeadBuses(); + // get database configuration + // create object to communicate with database + + String dbname = myConf.getDataBaseName(); + String dbuser = myConf.getDBUserName(); + String dbpwd = myConf.getDBPassword(); + srvCtxt.setAttribute("dbName",dbname); + srvCtxt.setAttribute("dbUser",dbuser); + srvCtxt.setAttribute("dbPwd",dbpwd); + t_sgbd_feeder = new SGBDfeeder( dbname, dbuser, dbpwd,myConf.getDbMode()); + fifoToDatabase = t_sgbd_feeder.getQueueFIFO(); + dbThread = new Thread(t_sgbd_feeder); + dbThread.start(); + myLog.write("SGBD feeder started. mode = " + myConf.getDbMode().toString()); + // launch heartbeat process + heartBeatRun = new HeartBeat(srvCtxt,myConf.getSocketTimeout()/3,myConf.portWebToIvy()); + Thread heartThread = new Thread(heartBeatRun); + heartThread.start(); + myLog.write("heartbeat thread started"); + // Stop a possibly running thread + stopThread(); + // Start new thread and + thread = new Thread(this, "DATA FROM IVY " + (restarts++)); + active = true; + thread.start(); + System.out.println("event source activated !!!"); + } + + /** + * Desactivate the event source. + */ + synchronized public void passivate() { + + active = false; + stopThread(); + // stop data base feeder + t_sgbd_feeder.kill(); + System.out.println("database feeder stopped."); + // + heartBeatRun.stop_thread(); + System.out.println("heartbeat thread stopped."); + } + + /** + * Desactivate the event source. + */ + synchronized public void stop() { + } + + /** + * stop a eventually runnig thread + */ + private void stopThread() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + /** + * load configuration from a specific configuration file on the server + * in tomcat6/../webapps/ServletPow/conf/pow_conf.xml + * and initiates a log file to. + */ + private void loadingConfiguration() throws Exception + { + myConf = new Conf(default_folder,"pow_conf.xml"); + myLog.write("Loading Configuration !"); + myLog.write(""); + myLog.write("Configuration Details :"); + myLog.write("Port : " + myConf.portIvyToWeb()); + myLog.write("Size of Datagrams : " + myConf.getUdpSize()); + myLog.write("DataBase used : " + myConf.getDataBaseName()); + myLog.write(""); + } + + /** + * This procedure convert the byte array into a String and returns an array containing all the + * the datas separately. + * extract also the information concerning the sender to send them to data base + * @param Data The raw of byte containing udp msg which will be processed + * @return An array containing all the datas separately + */ + private String[] dataProcessing(byte[] data) //throws Exception + { + // This array contain all the datas transmitted + String[] myDataSplited=null; + currentIvyMsg=null; + // Number of datas transmitted + int nbr_datas; + // Data separator + String sep_datas = " "; + // The datagram is converted into String + String myData = new String(data); + // check if format of message is correct ( see java.util.regex.Pattern for syntax) + Pattern p = Pattern.compile("\\d+ \\d+ (\\d+:){5}\\d+ .*"); //regular expression + Matcher m = p.matcher(myData); + boolean dataok = m.matches(); + if (dataok){ + // + myDataSplited = myData.split(sep_datas,4); // 4 = number of substring + int webId = Integer.parseInt(myDataSplited[0]); + long numMsg = Long.parseLong(myDataSplited[1]); + String timeMsg = myDataSplited[2]; + String ivyMsg = myDataSplited[3]; + currentIvyMsg = new IvyMsg(webId,numMsg,timeMsg,ivyMsg); //create a ivy msg + myDataSplited = myDataSplited[3].split(sep_datas); + nbr_datas = myDataSplited.length; + // The last data is trimed in order to erase all the space + myDataSplited[nbr_datas - 1] = myDataSplited[nbr_datas - 1].trim(); + } + // The array containing all the datas is return + return myDataSplited; + } + + /* Runnable specific functions*/ + /** + * main loop : + * listens to the udp channel + * deciphers the udp message + * checks if the sender is a new bus or not + * send the message to database through a fifo + * turns the ivy message into a pushlet event + * send the event to web users + * checks if there are some buses that doesn't send messages anymore + * removes drone which belonged to dead buses + */ + public void run() { + boolean decrypt_ok; + long chrono_start; + long elapsed_time; + byte[] complete_data ; + byte[] decrypted_data = null; + int true_length_of_msg ; + int i; + byte[] data_with_no_padding; + boolean firsttime=true; + System.out.println(" Thread lancé"); + //The server is launched and listen on port number 8535 + try{ + socket = new DatagramSocket(myConf.portIvyToWeb()); + socket.setSoTimeout(myConf.getSocketTimeout()); + myLog.write("Server launched !"); + //The module wait the reception of datagrams + chrono_start = System.currentTimeMillis(); + while(active) + { + // deciphering AES + // if I receive a udp packet that means that there was a ivy connection procedure before + // so I can fetch the table containing the ivy sessions + if (firsttime){ + tableIvySession = (HashMap) this.srvCtxt.getAttribute("ivySessionTable"); + } + if (tableIvySession!=null){ + firsttime =false; + }// end if tableSession!=null + byte buffer[] = new byte[myConf.getUdpSize()]; + DatagramPacket dataReceived = new DatagramPacket(buffer,buffer.length); + try + { + socket.receive(dataReceived); + if(dataReceived != null){ + if (firsttime){ // retrieve the table which store the ivy sessions in the servlet context (shared memory) + tableIvySession = (HashMap) this.srvCtxt.getAttribute("ivySessionTable"); + } + if (tableIvySession!=null){ + firsttime =false; + System.out.print("d"); + //The module checks if there is a new Bus Ivy incoming + SessionIvy clientIvy = tableIvySession.get(dataReceived.getAddress()); + if (clientIvy!=null){ + // decipher message + decrypt_ok = false; + AES cipher = clientIvy.getCipher(); + try{ + complete_data = dataReceived.getData(); + // we get the entire data field but as original message is short , + // the udp protocol has inserted a lot of zero byte to pad the data field + // we have to remove them + true_length_of_msg = dataReceived.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; + // we retrieve real data + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + try{ + decrypted_data = cipher.decrypt(data_with_no_padding); + decrypt_ok = true; + } + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("message length = " + true_length_of_msg); + System.out.println("msg no padding := "+(new String(Hex.encodeHex(data_with_no_padding)))); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("message length = " + true_length_of_msg); + System.out.println("msg no padding := "+(new String(Hex.encodeHex(data_with_no_padding)))); + } + } + catch(IOException ex){ + System.out.print("\npbm decrypting msg"); + System.out.print(ex.toString()); + } + if (decrypt_ok) + { + // extract data from message and create ivyMsg + myDataSplited = dataProcessing(decrypted_data); + if (myDataSplited!=null){ + // check if a new ivy bus is coming + BusIvy_ current_bus = clientIvy.getBusIvy(); + if (current_bus==null){ + current_bus = new BusIvy_(); + current_bus.setAddress(dataReceived.getAddress()); + current_bus.updateTime(); + clientIvy.setBusIvy(current_bus); + myLog.write("New Ivy Connection detected : " + dataReceived.getAddress()); + // send message de connection + currentIvyMsg.setOrder(DbOrder.CONNECT); + send2DateBase(currentIvyMsg); + } + else + { + current_bus.updateTime(); + } + // according to type of ivy message a specific event is created and sent to web clients + if((myDataSplited[0].equals("New_Plane")) + ||(myDataSplited[0].equals("Plane_Die")) + ||(myDataSplited[0].equals("Plane_Resurect")) + ||(myDataSplited[0].equals("DL_SETTING_ACK")) + ||(myDataSplited[0].equals("WAYPOINT_MOVED")) + ||(myDataSplited[0].equals("NAV_STATUS")) + ||(myDataSplited[0].equals("SETTINGS_VALUES"))) + { + myLog.write("Order Received From : " + dataReceived.getAddress() + " ---> " + new String(decrypted_data)); + sendOrderToServer(myDataSplited); + if(!(current_bus.isOwnBy(Integer.parseInt(myDataSplited[1])))) + { + current_bus.addDrones(Integer.parseInt(myDataSplited[1])); + } + currentIvyMsg.setOrder(DbOrder.ADD_ORDER); + send2DateBase(currentIvyMsg); + currentIvyMsg = null; + } + else if(myDataSplited[0].equals("HEARTBEAT")){ + myLog.write("HeartBeat From webID : " +myDataSplited[1] +" ip="+ dataReceived.getAddress()); + } + else + { + sendDataToServer(myDataSplited); + if(!(current_bus.isOwnBy(Integer.parseInt(myDataSplited[0])))) + { + current_bus.addDrones(Integer.parseInt(myDataSplited[0])); + } + currentIvyMsg.setOrder(DbOrder.ADD_DATA); + send2DateBase(currentIvyMsg); + currentIvyMsg = null; + } + System.out.print("."); + } + else + { + System.out.print("\ndata de crypted but does not fit appropriate format, message skipped."); + } + } + else + { + System.out.print("\nerror while decrypting data, message skipped."); + } + + }// fin if ivyclient != null + else + { + System.out.print("\nno ivy client stored for this datagramm from "+dataReceived.getAddress()); + } + // check dead buses (period of 30sec ) + elapsed_time =System.currentTimeMillis()- chrono_start; + if (elapsed_time>time2checkDeadBuses){ + chrono_start = System.currentTimeMillis(); + Iterator> itr = tableIvySession.entrySet().iterator(); + BusIvy_ checked_bus; + SessionIvy checked_session; + while(itr.hasNext()){ + checked_session = itr.next().getValue(); + checked_bus = checked_session.getBusIvy(); + if((checked_bus!=null)&&(!checked_bus.isAlive())){ + myLog.write("Ivy Bus not alive is deconnected : " + checked_bus.getAddress()); + for(Integer deadDrone : checked_bus.getDrones()) + { + deconnectDrone(deadDrone); + } + checked_session.setBusIvy(null); + // deconnect message sent to database + currentIvyMsg = new IvyMsg(checked_session.getWebId()); + send2DateBase(currentIvyMsg); + currentIvyMsg = null; + // + tableIvySession.remove(checked_session.getIvyInetAddress()); + } + } + } + } // fin if tablesession != null + else + { + // on a recu un diagramme mais il n'y a pas de session recorded donc on + // doit envoyer un message au sender comme quoi il doit se relogger + System.out.println("\nno session recorder "+dataReceived.getAddress()+ "should relog to server"); + } + }// fin if datareceived!=null + }// fin du try socket received + catch(SocketTimeoutException ex) + { + if(tableIvySession!=null){ + Iterator> itr = tableIvySession.entrySet().iterator(); + BusIvy_ checked_bus; + SessionIvy checked_session; + while(itr.hasNext()){ + checked_session = itr.next().getValue(); + checked_bus = checked_session.getBusIvy(); + if (checked_bus!=null){ + myLog.write("Socket TimeOut : Ivy bus at " + checked_bus.getAddress()+" deconnected"); + for(Integer deadDrone : checked_bus.getDrones()) + { + deconnectDrone(deadDrone); + } + // deconnect message sent to database + currentIvyMsg = new IvyMsg(checked_session.getWebId()); + send2DateBase(currentIvyMsg); + currentIvyMsg = null; + checked_session.setBusIvy(null); + tableIvySession.remove(checked_session.getIvyInetAddress()); + } + } + } + myLog.write("No Bus Ivy connected..."); + dataReceived = null; + } + catch(IOException ex){ + System.out.println("exception socket receive serveur.java"); + ex.printStackTrace(); + } + }// fin while true + } catch (SocketException soe){ + System.out.print("Socket Exception !"); + soe.printStackTrace(); + } + finally{ + if (socket!=null) { + socket.close(); + System.out.println("socket server closed"); + } + } + } + + /** + * send a iskill event when a drone has disappeared from an ivy bus + * @param droneId + * @throws Exception + */ + private void deconnectDrone(int droneId) + { + Event event = Event.createDataEvent("/data/drone/iskill"); + event.setField("aircraftId",droneId); + event.setField("iskill", 1 + "" ); // 1 ==true + Dispatcher.getInstance().multicast(event); + //TODO erasing the associated configuration files ???? + } + + /** + * send a IvyMsg to database through fifo buffer + */ + private void send2DateBase(IvyMsg m) + { + try{ + fifoToDatabase.put(m); + } + catch (InterruptedException e){ + System.out.println("message was not sent to database"); + } + } + /** + * send a datagramm containing all useful information on a drone + * @param myDataSplited + * @throws Exception + */ + private void sendDataToServer(String myDataSplited[])// throws Exception + { + int i; + int nbr_datas = myDataSplited.length; + String[] myDataName = new String[nbr_datas]; + // id of the drone + myDataName[0] = "id"; + // name of the drone + myDataName[1] = "dbName"; + // latitude + myDataName[2] = "dbLatitude"; + // longitude + myDataName[3] = "dbLongitude"; + // speed + myDataName[4] = "dbSpeed";// + // bearing + myDataName[5] = "dbCourse"; + // amsl + myDataName[6] = "dbAmsl";// + // vertical speed + myDataName[7] = "dbVert_speed";// + // agl + myDataName[8] = "dbAgl";// + // battery load + myDataName[9] = "dbStat_battery";// + // gps_status + myDataName[10] = "dbStat_gps";// + // Engine status + myDataName[11] = "dbEngine_status";// + // active block + myDataName[12] = "dbActive_block";// + // id of the setting + myDataName[13] = "dbId_Setting";// + // value of the setting + myDataName[14] = "dbSetting_Value";// + // color of the drone , rajout thomas + myDataName[15] = "drone_color";// + + Event event = Event.createDataEvent("/data/drones_maj"); + event.setField("aircraftId",myDataSplited[0]); + for(i=1;i. + * + * [Additional notices, if required by prior licensing conditions] + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Lesser General Public License Version 2 or later + * (the "LGPL"), in which case the provisions of the LGPL are + * applicable instead of those above. See terms of LGPL at + * . + * If you wish to allow use of your version of this file only under + * the terms of the LGPL and not to allow others to use your version + * of this file under the Apache Software License, indicate your + * decision by deleting the provisions above and replace them with + * the notice and other provisions required by the LGPL. If you do + * not delete the provisions above, a recipient may use your version + * of this file under either the Apache Software License or the LGPL. + */ + +package pow.webserver; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.UnknownHostException; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.security.cert.X509Certificate; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A SecureProtocolSocketFactory that uses JSSE to create + * SSL sockets. It will also support host name verification to help preventing + * man-in-the-middle attacks. Host name verification is turned on by + * default but one will be able to turn it off, which might be a useful feature + * during development. Host name verification will make sure the SSL sessions + * server host name matches with the the host name returned in the + * server certificates "Common Name" field of the "SubjectDN" entry. + * + * @author Sebastian Hauer + *

    + * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

    + */ +public class StrictSSLProtocolSocketFactory + implements SecureProtocolSocketFactory { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(StrictSSLProtocolSocketFactory.class); + + /** Host name verify flag. */ + private boolean verifyHostname = true; + + + /** + * Constructor for StrictSSLProtocolSocketFactory. + * @param verifyHostname The host name verification flag. If set to + * true the SSL sessions server host name will be compared + * to the host name returned in the server certificates "Common Name" + * field of the "SubjectDN" entry. If these names do not match a + * Exception is thrown to indicate this. Enabling host name verification + * will help to prevent from man-in-the-middle attacks. If set to + * false host name verification is turned off. + * + * Code sample: + * + *
    + * Protocol stricthttps = new Protocol( + * "https", new StrictSSLProtocolSocketFactory(true), 443); + * + * HttpClient client = new HttpClient(); + * client.getHostConfiguration().setHost("localhost", 443, stricthttps); + *
    + * + */ + public StrictSSLProtocolSocketFactory(boolean verifyHostname) { + super(); + this.verifyHostname = verifyHostname; + } + + /** + * Constructor for StrictSSLProtocolSocketFactory. + * Host name verification will be enabled by default. + */ + public StrictSSLProtocolSocketFactory() { + super(); + } + + /** + * Set the host name verification flag. + * + * @param verifyHostname The host name verification flag. If set to + * true the SSL sessions server host name will be compared + * to the host name returned in the server certificates "Common Name" + * field of the "SubjectDN" entry. If these names do not match a + * Exception is thrown to indicate this. Enabling host name verification + * will help to prevent from man-in-the-middle attacks. If set to + * false host name verification is turned off. + */ + public void setHostnameVerification(boolean verifyHostname) { + this.verifyHostname = verifyHostname; + } + + /** + * Gets the status of the host name verification flag. + * + * @return Host name verification flag. Either true if host + * name verification is turned on, or false if host name + * verification is turned off. + */ + public boolean getHostnameVerification() { + return verifyHostname; + } + + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket(String host, int port, + InetAddress clientHost, int clientPort) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port, + clientHost, + clientPort); + verifyHostname(sslSocket); + + return sslSocket; + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

    + * This method employs several techniques to circumvent the limitations of older JREs that + * do not support connect timeout. When running in JRE 1.4 or above reflection is used to + * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older + * JREs a controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the timeout + * expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

    + * + * @param host the host name/IP + * @param port the port on the host + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + Socket socket = null; + + SocketFactory socketfactory = SSLSocketFactory.getDefault(); + if (timeout == 0) { + socket = socketfactory.createSocket(host, port, localAddress, localPort); + } else { + socket = socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + socket.bind(localaddr); + socket.connect(remoteaddr, timeout); + } + verifyHostname((SSLSocket)socket); + return socket; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port); + verifyHostname(sslSocket); + + return sslSocket; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket(Socket socket, String host, int port, + boolean autoClose) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(socket, host, + port, autoClose); + verifyHostname(sslSocket); + + return sslSocket; + } + + + /** + * Describe verifyHostname method here. + * + * @param socket a SSLSocket value + * @exception SSLPeerUnverifiedException If there are problems obtaining + * the server certificates from the SSL session, or the server host name + * does not match with the "Common Name" in the server certificates + * SubjectDN. + * @exception UnknownHostException If we are not able to resolve + * the SSL sessions returned server host name. + */ + private void verifyHostname(SSLSocket socket) + throws SSLPeerUnverifiedException, UnknownHostException { + if (! verifyHostname) + return; + + SSLSession session = socket.getSession(); + String hostname = session.getPeerHost(); + try { + InetAddress addr = InetAddress.getByName(hostname); + } catch (UnknownHostException uhe) { + throw new UnknownHostException("Could not resolve SSL sessions " + + "server hostname: " + hostname); + } + + X509Certificate[] certs = session.getPeerCertificateChain(); + if (certs == null || certs.length == 0) + throw new SSLPeerUnverifiedException("No server certificates found!"); + + //get the servers DN in its string representation + String dn = certs[0].getSubjectDN().getName(); + + //might be useful to print out all certificates we receive from the + //server, in case one has to debug a problem with the installed certs. + if (LOG.isDebugEnabled()) { + LOG.debug("Server certificate chain:"); + for (int i = 0; i < certs.length; i++) { + LOG.debug("X509Certificate[" + i + "]=" + certs[i]); + } + } + //get the common name from the first cert + String cn = getCN(dn); + if (hostname.equalsIgnoreCase(cn)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Target hostname valid: " + cn); + } + } else { + throw new SSLPeerUnverifiedException( + "HTTPS hostname invalid: expected '" + hostname + "', received '" + cn + "'"); + } + } + + + /** + * Parses a X.500 distinguished name for the value of the + * "Common Name" field. + * This is done a bit sloppy right now and should probably be done a bit + * more according to RFC 2253. + * + * @param dn a X.500 distinguished name. + * @return the value of the "Common Name" field. + */ + private String getCN(String dn) { + int i = 0; + i = dn.indexOf("CN="); + if (i == -1) { + return null; + } + //get the remaining DN without CN= + dn = dn.substring(i + 3); + // System.out.println("dn=" + dn); + char[] dncs = dn.toCharArray(); + for (i = 0; i < dncs.length; i++) { + if (dncs[i] == ',' && i > 0 && dncs[i - 1] != '\\') { + break; + } + } + return dn.substring(0, i); + } + + public boolean equals(Object obj) { + if ((obj != null) && obj.getClass().equals(StrictSSLProtocolSocketFactory.class)) { + return ((StrictSSLProtocolSocketFactory) obj).getHostnameVerification() + == this.verifyHostname; + } else { + return false; + } + } + + public int hashCode() { + return StrictSSLProtocolSocketFactory.class.hashCode(); + } + +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/User.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/User.java new file mode 100755 index 0000000000..9f771179b1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/User.java @@ -0,0 +1,121 @@ +package pow.webserver; +import java.util.HashSet; +import java.util.Iterator; + +/** + * represents a ivy or a web user account + * for the web user the account nest also the list of drones that the user can control + * the list contains the ivy name of the drone (MJ5, TJ1...). + * In Paparazzi a drone is not identified in a unique identifier, that means that if a user + * can pilot a drone MJ5, he can pilot all 'MJ5' drone + * @author genin + */ +public class User implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + private String login = ""; + private String password = ""; + private HashSet dronesNamePermitted; + private Rights right; + /** + * create a user account + * @param log the login of the user + * @param pwd the password of the user + * @param rght the type of the user + */ + public User(String log, String pwd,Rights rght) { + this.login = log; + this.password = Md5.encode(pwd); + this.right = rght; + this.dronesNamePermitted = new HashSet(); + } + /** + * @return an iterator containing the list of all drone that the user can control + */ + public Iterator getSetItr(){ + return dronesNamePermitted.iterator(); + } + /** + * reset the list of drone that the web user can control + */ + public void clearListDrone(){ + dronesNamePermitted.clear(); + } + /** + * the list of drone that the web user can control + * @return a formatted string containing all the drone that the user can control separated by commas + */ + public String getListDrone(){ + Iterator itr = dronesNamePermitted.iterator(); + String res = ""; + while(itr.hasNext()){ + res = res + itr.next() + ";"; + } + return res; + } + /** + * add a drone name to the list of drones that the user can control + * @param d + */ + public void addDrone(String d){ + dronesNamePermitted.add(d); + } + /** + * inform whether the user can pilot a drone or not + * @param droneName the name of the drone + * @return true if the user can pilot the drones with this name + */ + public boolean canControl(String droneName) + { + if ((right == Rights.ADMIN)|| ((right==Rights.USER)&&dronesNamePermitted.contains(droneName))) + { return true; } + else + { return false; } + } + /** @return the type of right granted to the user*/ + public Rights getRights(){ + return this.right; + } + /** + * specify the type of right granted to the user + * @param r the right granted to the user + */ + public void setRights(Rights r){ + this.right=r; + } + /** + * @return the login of the user + */ + public String getLogin() { + return login; + } + /** + * specify the login of the user + * @param log the login of the user + */ + public void setNom(String log) { + this.login = log; + } + /** + * @return the password of the user encoded with md5 algorithm + */ + public String getPassword() { + return password; + } + /** + * specify the user password, it's not stored in clear (md5 hash) + * @param pwd the user password in clear + */ + public void setPwd(String pwd) { + this.password = Md5.encode(pwd); + } + /** + * check if the password given in argument corresponds to the password user + * @param pwd the password to check + * @return true if the password is correct + */ + public boolean IsPwdTrue(String pwd) { + return this.password.equals(Md5.encode(pwd)); + } +} + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/UserTab.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/UserTab.java new file mode 100755 index 0000000000..4839d0ea36 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/src/pow/webserver/UserTab.java @@ -0,0 +1,125 @@ +package pow.webserver; + +import java.util.HashMap; +import java.util.Iterator; +import java.io.*; +/** + * User objects are stored in a UserTab object which can be serialized in a file on the server disk + * @see User + * @author genin + */ +public class UserTab implements java.io.Serializable { + + + private static final long serialVersionUID = 1L; + private HashMap tabUser; + /** + * create a empty list of users + */ + public UserTab(){ + tabUser = new HashMap(); + } + /** + * insert a user in the list + * @param u a user object to insert + * @throws AlreadyRegisteredUserException + */ + public void insert(User u) throws AlreadyRegisteredUserException { + String log = u.getLogin(); + if (!tabUser.containsKey(log)) tabUser.put(u.getLogin(),u); + else { throw new AlreadyRegisteredUserException(u) ;} + } + /** + * remove the user with the spefied login + * @param log the login of the user to remove + */ + public void remove(String log){ + tabUser.remove(log) ; + } + /** + * return the user corresponding to the given login + * @param log the login of the user to seek + * @return the user object corresponding to the login or null if it is not present + */ + public User seek(String log){ + return tabUser.get(log); + } + /** + * check if an user with this logging exists yet + * @param log the login of the user to check + * @return true if the user having the login exists + */ + public boolean isInside(String log){ + return tabUser.containsKey(log); + } + + /** + * Check if the password of the user having the specified login is correct + * @param log the login of the user + * @param pwd the password + * @return true if there is a user with this login and this password + */ + public boolean checkUser(String log,String pwd){ + boolean res = false; + User usr = tabUser.get(log); + if (usr!=null){ + res=usr.IsPwdTrue(pwd); + } + return res; + } + /** + * return the list of all drone which may be controlled by the user + * @param log the login of the user + * @return an iterator containing the list of drone or null is the user does not exist + */ + public Iterator getItrUsr(String log){ + Iterator res = null; + User usr = tabUser.get(log); + if (usr!=null){ + res=usr.getSetItr(); + } + return res; + } + /** + * @return an iterator on all login in the list + */ + public Iterator getLoginIterator(){ + return tabUser.keySet().iterator(); + } + /** + * Save the object in a file + * @param nomfichier the file where the user's accounts will be stored + */ + public void serialize(String nomfichier){ + try { + FileOutputStream fichier = new FileOutputStream(nomfichier); + ObjectOutputStream oos = new ObjectOutputStream(fichier); + oos.writeObject(this); + oos.flush(); + oos.close(); + } + catch (java.io.IOException e) { + e.printStackTrace(); + } + } + /** + * load the object from a file + * @param nomfichier the file where the user's accounts are stored + * @return an object containing the users list or null if the pathname is not correct + */ + public static UserTab unserialize(String nomfichier) { + try { + FileInputStream fichier = new FileInputStream(nomfichier); + ObjectInputStream ois = new ObjectInputStream(fichier); + UserTab usrtab = (UserTab) ois.readObject(); + return usrtab; + } + catch (java.io.IOException e) { + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/Version.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/Version.java new file mode 100755 index 0000000000..a2563f7192 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/Version.java @@ -0,0 +1,37 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet; + +/** + * Version info class. + * + *

    Purpose

    + * Extract version info from jar manifest file. + * + * @author Just van den Broecke + * @version $Id: Version.java,v 1.4 2006/05/06 00:10:11 justb Exp $ + */ + +public class Version { + /** Version info extracted from the .jar manifest file (see build.xml and build.properties). */ + public static final String SOFTWARE_VERSION = Version.class.getPackage().getSpecificationVersion(); + public static final String BUILD_DATE = Version.class.getPackage().getImplementationVersion(); +} + +/* + * $Log: Version.java,v $ + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2004/02/08 16:07:55 justb + * *** empty log message *** + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/11 21:29:48 justb + * first checkin + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java new file mode 100755 index 0000000000..f2dc390f26 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java @@ -0,0 +1,699 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventParser; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.OutputStream; +import java.net.*; +import java.util.Map; + +/** + * Client API for Java HTTP client applets or apps. + *

    + * Use this class within Java client applications or applets. + * Implement a PushletClientListener to receive callbacks for + * data-related Event objects pushed by the server. + *

    + * This class may also be used as a base class and be extended + * for custom clients, hence the presence of many proteced methods. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: PushletClient.java,v 1.19 2009/06/04 12:46:35 justb Exp $ + * @see PushletClientListener + * @see nl.justobjects.pushlet.test.PushletApplet + * @see nl.justobjects.pushlet.test.PushletPingApplication + */ +public class PushletClient implements Protocol { + /** + * Pushlet URL. + */ + private String pushletURL; + + /** + * Debug flag for verbose output. + */ + private boolean debug; + + /** + * Id gotten on join ack + */ + private String id; + + /** + * Internal listener for data events pushed by server. + */ + protected DataEventListener dataEventListener; + + /** + * Constructor with full pushlet URL. + */ + public PushletClient(String aPushletURL) { + pushletURL = aPushletURL; + } + + /** + * Constructor with host and port using default URI. + */ + public PushletClient(String aHost, int aPort) { + this("http://" + aHost + ":" + aPort + DEFAULT_SERVLET_URI); + } + + /** + * Set proxy options and optional proxy authentication. + *

    + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + *

    + * Usage: + * PushletClient pushletClient = new PushletClient("http:://www.domain.com/pushlet"); + * pushletClient.setProxyOptions("proxy.bla.com", "8080", ....); + *

    + * use pushletClient further as normal + */ + public void setProxyOptions(String aProxyHost, + String aProxyPort, String theNonProxyHosts, + String aUserName, String aPassword, String anNTLMDomain) { + + // Enable proxying + System.setProperty("http.proxySet", "true"); + System.setProperty("http.proxyHost", aProxyHost); + System.setProperty("http.proxyPort", aProxyPort); + + // Set optional non-proxy hosts + if (theNonProxyHosts != null) { + System.setProperty("http.nonProxyHosts", theNonProxyHosts); + } + + // If user name specified configure proxy authentication + if (aUserName != null) { + System.setProperty("http.proxyUser", aUserName); + System.setProperty("http.proxyPassword", aPassword); + + // See inner class below + Authenticator.setDefault(new HTTPAuthenticateProxy(aUserName, aPassword)); + + // Optional NT domain + if (anNTLMDomain != null) { + System.setProperty("http.auth.ntlm.domain", anNTLMDomain); + } + } + } + + /** + * Join server, starts session. + */ + public void join() throws PushletException { + Event event = new Event(E_JOIN); + event.setField(P_FORMAT, FORMAT_XML); + Event response = doControl(event); + throwOnNack(response); + + // Join Ack received + id = response.getField(P_ID); + } + + /** + * Leave server, stops session. + */ + public void leave() throws PushletException { + stopListen(); + throwOnInvalidSession(); + Event event = new Event(E_LEAVE); + event.setField(P_ID, id); + Event response = doControl(event); + + throwOnNack(response); + id = null; + } + + /** + * Open data channel. + */ + public void listen(PushletClientListener aListener) throws PushletException { + listen(aListener, MODE_STREAM); + } + + /** + * Open data channel in stream or push mode. + */ + public void listen(PushletClientListener aListener, String aMode) throws PushletException { + listen(aListener, aMode, null); + } + + /** + * Open data channel in stream or push mode with a subject. + */ + public void listen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + throwOnInvalidSession(); + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_LISTEN + + "&" + P_ID + "=" + id + + "&" + P_MODE + "=" + aMode; + if (aSubject != null) { + listenURL = listenURL + "&" + P_SUBJECT + "=" + aSubject; + } + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Immediate listener: joins/subscribes and listens in one action. + */ + public void joinListen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_JOIN_LISTEN + + "&" + P_FORMAT + "=" + FORMAT_XML + + "&" + P_MODE + "=" + aMode + + "&" + P_SUBJECT + "=" + aSubject; + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Publish an event through server. + */ + public void publish(String aSubject, Map theAttributes) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_PUBLISH, theAttributes); + event.setField(P_SUBJECT, aSubject); + event.setField(P_ID, id); + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject, String aLabel) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_SUBSCRIBE); + event.setField(P_ID, id); + event.setField(P_SUBJECT, aSubject); + + // Optional label, is returned in data events + if (aLabel != null) { + event.setField(P_SUBSCRIPTION_LABEL, aLabel); + } + + // Send request + Event response = doControl(event); + throwOnNack(response); + + return response.getField(P_SUBSCRIPTION_ID); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject) throws PushletException { + return subscribe(aSubject, null); + } + + /** + * Unsubscribes with subscription id. + */ + public void unsubscribe(String aSubscriptionId) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_UNSUBSCRIBE); + event.setField(P_ID, id); + + // Optional subscription id + if (aSubscriptionId != null) { + event.setField(P_SUBSCRIPTION_ID, aSubscriptionId); + } + + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Unsubscribes from all subjects. + */ + public void unsubscribe() throws PushletException { + unsubscribe(null); + } + + /** + * Stop the listener. + */ + public void stopListen() throws PushletException { + if (dataEventListener != null) { + unsubscribe(); + dataEventListener.stop(); + dataEventListener = null; + } + } + + public void setDebug(boolean b) { + debug = b; + } + + /** + * Starts default DataEventListener and waits for its thread to start. + */ + protected void startDataEventListener(PushletClientListener aListener, String aListenURL) { + // Suggestion by Jeff Nowakowski 29.oct.2006 + dataEventListener = new DataEventListener(aListener, aListenURL); + + synchronized (dataEventListener) { + dataEventListener.start(); + try { + // Wait for data event listener (thread) to start + dataEventListener.wait(); + } catch (InterruptedException e) { + } + } + } + + protected void throwOnNack(Event anEvent) throws PushletException { + if (anEvent.getEventType().equals(E_NACK)) { + throw new PushletException("Negative response: reason=" + anEvent.getField(P_REASON)); + } + } + + protected void throwOnInvalidSession() throws PushletException { + if (id == null) { + throw new PushletException("Invalid pushlet session"); + } + } + + protected Reader openURL(String aURL) throws PushletException { + // Open URL connection with server + try { + p("Connecting to " + aURL); + URL url = new URL(aURL); + URLConnection urlConnection = url.openConnection(); + + // Disable any kind of caching. + urlConnection.setUseCaches(false); + urlConnection.setDefaultUseCaches(false); + + // TODO: later version may use POST + // Enable HTTP POST + // urlConnection.setDoOutput(true); + + // Do the POST with Event in XML in body + // OutputStream os = urlConnection.getOutputStream(); + // os.write(anEvent.toXML().getBytes()); + // os.flush(); + // os.close(); + + // Get the stream from the server. + // reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + // Note: somehow the client does not work with some JVMs when using + // BufferedInputStream... So do unbuffered input. + // p("Opening urlConnection inputstream"); + return new InputStreamReader(urlConnection.getInputStream()); + + } catch (Throwable t) { + warn("openURL() could not open " + aURL, t); + throw new PushletException(" could not open " + aURL, t); + } + } + + + /** + * Send control events to server and return response. + */ + protected Event doControl(Event aControlEvent) throws PushletException { + String controlURL = pushletURL + "?" + aControlEvent.toQueryString(); + + p("doControl to " + controlURL); + + // Open URL connection with server + Reader reader = openURL(controlURL); + + // Get Pushlet event from stream + Event event = null; + try { + p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + return event; + } catch (Throwable t) { + // Stop and report error. + warn("doControl() exception", t); + throw new PushletException(" error parsing response from" + controlURL, t); + } + } + + /** + * Util: print. + */ + protected void p(String s) { + if (debug) { + System.out.println("[PushletClient] " + s); + } + } + + /** + * Util: warn. + */ + protected void warn(String s) { + warn(s, null); + } + + /** + * Util: warn with exception. + */ + protected void warn(String s, Throwable t) { + System.err.println("[PushletClient] - WARN - " + s + " ex=" + t); + + if (t != null) { + t.printStackTrace(); + } + } + + /** + * Internal (default) listener for the Pushlet data channel. + */ + protected class DataEventListener implements Runnable { + /** + * Client's listener that gets called back on events. + */ + private PushletClientListener listener; + + /** + * Receiver receiveThread. + */ + private Thread receiveThread = null; + private Reader reader; + private String refreshURL; + private String listenURL; + + public DataEventListener(PushletClientListener aListener, String aListenURL) { + listener = aListener; + listenURL = aListenURL; + } + + public void start() { + // All ok: start a receiver receiveThread + receiveThread = new Thread(this); + receiveThread.start(); + + } + + /** + * Stop listening; may restart later with start(). + */ + public void stop() { + p("In stop()"); + bailout(); + } + + /** + * Receive event objects from server and callback listener. + */ + public void run() { + p("Start run()"); + try { + while (receiveThread != null && receiveThread.isAlive()) { + // Connect to server + reader = openURL(listenURL); + + synchronized (this) { + // Inform the calling thread we're ready to receive events. + // Suggestion by Jeff Nowakowski 29.oct.2006 + this.notify(); + } + + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; + try { + // p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + } catch (Throwable t) { + + // Stop and report error. + // warn("Stop run() on exception", t); + if (listener != null) { + listener.onError("exception during receive: " + t); + } + + break; + } + + // Handle event by calling listener + if (event != null && listener != null) { + // p("received: " + event.toXML()); + String eventType = event.getEventType(); + if (eventType.equals(E_HEARTBEAT)) { + listener.onHeartbeat(event); + } else if (eventType.equals(E_DATA)) { + listener.onData(event); + } else if (eventType.equals(E_JOIN_LISTEN_ACK)) { + id = event.getField(P_ID); + } else if (eventType.equals(E_LISTEN_ACK)) { + p("Listen ack ok"); + } else if (eventType.equals(E_REFRESH_ACK)) { + // ignore + } else if (eventType.equals(E_ABORT)) { + listener.onAbort(event); + listener = null; + break; + } else if (eventType.equals(E_REFRESH)) { + refresh(event); + } else { + handleUnknownEventType(eventType, event, listener); + } + } + } + } + } catch (Throwable t) { + warn("Exception in run() ", t); + // bailout(); + } + } + + protected void disconnect() { + p("start disconnect()"); + if (reader != null) { + try { + // this blocks, find another way + // reader.close(); + p("Closed reader ok"); + } catch (Exception ignore) { + } finally { + reader = null; + } + } + p("end disconnect()"); + } + + /** + * Stop receiver receiveThread. + */ + public void stopThread() { + p("In stopThread()"); + + // Keep a reference such that we can kill it from here. + Thread targetThread = receiveThread; + + receiveThread = null; + + // This should stop the main loop for this receiveThread. + // Killing a receiveThread on a blcing read is tricky. + // See also http://gee.cs.oswego.edu/dl/cpj/cancel.html + if ((targetThread != null) && targetThread.isAlive()) { + + targetThread.interrupt(); + + try { + + // Wait for it to die + targetThread.join(500); + } catch (InterruptedException ignore) { + } + + // If current receiveThread refuses to die, + // take more rigorous methods. + if (targetThread.isAlive()) { + + // Not preferred but may be needed + // to stop during a blocking read. + targetThread.stop(); + + // Wait for it to die + try { + targetThread.join(500); + } catch (Throwable ignore) { + } + } + + p("Stopped receiveThread alive=" + targetThread.isAlive()); + + } + } + + /** + * Stop listening on stream from server. + */ + public void bailout() { + p("In bailout()"); + stopThread(); + disconnect(); + } + + /** + * Handle refresh, by pausing. + */ + protected void refresh(Event aRefreshEvent) throws PushletException { + try { + // Wait for specified time. + Thread.sleep(Long.parseLong(aRefreshEvent.getField(P_WAIT))); + } catch (Throwable t) { + warn("abort while refresing"); + refreshURL = null; + return; + } + + // If stopped during sleep, don't proceed + if (receiveThread == null) { + return; + } + + // Create url to refresh + refreshURL = pushletURL + + "?" + P_ID + "=" + id + + "&" + P_EVENT + "=" + E_REFRESH + ; + + if (reader != null) { + try { + reader.close(); + + } catch (IOException ignore) { + + } + reader = null; + } + + reader = openURL(refreshURL); + } + + /** + * Handle unknown Event (default behaviour). + */ + protected void handleUnknownEventType(String eventType, Event event, PushletClientListener listener) { + warn("unsupported event type received: " + eventType); + } + } + + /** + * Authenticator + */ + private static class HTTPAuthenticateProxy extends Authenticator { + + /** + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + */ + + private String thePassword = ""; + private String theUser = ""; + + public HTTPAuthenticateProxy(String username, String password) { + + thePassword = password; + theUser = username; + } + + protected PasswordAuthentication getPasswordAuthentication() { + // System.out.println("[HttpAuthenticateProxy] Username = " + theUser); + // System.out.println("[HttpAuthenticateProxy] Password = " + thePassword); + + return new PasswordAuthentication(theUser, thePassword.toCharArray()); + } + + } + +} + +/* + * $Log: PushletClient.java,v $ + * Revision 1.19 2009/06/04 12:46:35 justb + * PushletClient: add more hooks for extension (feat ID: 2799694 Craig M) + * + * Revision 1.18 2007/11/10 13:52:47 justb + * make startDataEventListener method protected to allow overriding + * + * Revision 1.17 2006/10/29 16:47:57 justb + * included patch from Jeff Nowakowski: wait until listener thread runs + * + * Revision 1.16 2005/05/06 20:08:20 justb + * client enhancements + * + * Revision 1.15 2005/03/27 17:42:27 justb + * enhancements + * + * Revision 1.14 2005/03/25 23:54:04 justb + * *** empty log message *** + * + * Revision 1.13 2005/02/28 16:59:40 justb + * fixes for leave and disconnect + * + * Revision 1.12 2005/02/28 15:57:54 justb + * added SimpleListener example + * + * Revision 1.11 2005/02/21 12:31:44 justb + * added proxy contribution from Dele Olajide + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/02/18 09:54:12 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.7 2005/02/15 15:46:30 justb + * client API improves + * + * Revision 1.6 2005/02/15 13:28:56 justb + * first quick rewrite adapt for v2 protocol + * + * Revision 1.5 2004/10/25 21:23:44 justb + * *** empty log message *** + * + * Revision 1.4 2004/10/24 13:52:51 justb + * small fixes in client lib + * + * Revision 1.3 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 20:14:17 justb + * renamed all *JavaPushletClient* to *PushletClient* + * + * Revision 1.10 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.9 2003/08/17 20:30:20 justb + * cosmetic changes + * + * Revision 1.8 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java.patch b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java.patch new file mode 100755 index 0000000000..63d660354d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClient.java.patch @@ -0,0 +1,29 @@ +--- PushletClient.java 6 May 2005 20:08:20 -0000 1.16 ++++ PushletClient.java 28 Oct 2006 23:19:12 -0000 +@@ -142,7 +142,13 @@ + } + + dataEventListener = new DataEventListener(aListener, listenURL); +- dataEventListener.start(); ++ synchronized (dataEventListener) { ++ dataEventListener.start(); ++ try { ++ dataEventListener.wait(); ++ } catch (InterruptedException e) { ++ } ++ } + } + + /** Immediate listener. */ +@@ -354,6 +360,11 @@ + // Connect to server + reader = openURL(listenURL); + ++ synchronized (this) { ++ // Inform the calling thread we're ready to receive events. ++ this.notify(); ++ } ++ + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClientListener.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClientListener.java new file mode 100755 index 0000000000..74cee7b2b2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/client/PushletClientListener.java @@ -0,0 +1,50 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; + +/** + * Interface for listener of the PushletClient object. + * + * @version $Id: PushletClientListener.java,v 1.5 2005/02/21 11:50:37 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public interface PushletClientListener extends Protocol { + /** Abort event from server. */ + public void onAbort(Event theEvent); + + /** Data event from server. */ + public void onData(Event theEvent); + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent); + + /** Error occurred. */ + public void onError(String message); +} + +/* +* $Log: PushletClientListener.java,v $ +* Revision 1.5 2005/02/21 11:50:37 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.4 2005/02/15 15:46:31 justb +* client API improves +* +* Revision 1.3 2004/10/24 12:58:18 justb +* revised client and test classes for new protocol +* +* Revision 1.2 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.1 2004/03/10 20:14:17 justb +* renamed all *JavaPushletClient* to *PushletClient* +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/BrowserAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/BrowserAdapter.java new file mode 100755 index 0000000000..8aa226b659 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/BrowserAdapter.java @@ -0,0 +1,203 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Iterator; + +/** + * Generic implementation of ClientAdapter for browser clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: BrowserAdapter.java,v 1.6 2007/11/09 13:15:35 justb Exp $ + */ +public class BrowserAdapter implements ClientAdapter, Protocol { + + public static final String START_DOCUMENT = + "" + + "" + + "\n"; + public static final String END_DOCUMENT = ""; + + private PrintWriter servletOut; + private HttpServletResponse servletRsp; + private int bytesSent; + + /** + * Constructor. + */ + public BrowserAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + /** + * Generic init. + */ + public void start() throws IOException { + // Keep servlet request/response objects until page ends in stop() + // Content type as HTML + servletRsp.setStatus(HttpServletResponse.SC_OK); + servletRsp.setContentType("text/html;charset=UTF-8"); + + // http://www.junlu.com/msg/45902.html + // Log.debug("bufsize=" + aRsp.getBufferSize()); + servletOut = servletRsp.getWriter(); + send(START_DOCUMENT); + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + Log.debug("BCA event=" + anEvent.toXML()); + + // Check if we should refresh + if (anEvent.getEventType().equals(Protocol.E_REFRESH)) { + // Append refresh and tail of HTML document + // Construct the JS callback line to be sent as last line of doc. + // This will refresh the request using the unique id to determine + // the subscriber instance on the server. The client will wait for + // a number of milliseconds. + long refreshWaitMillis = Long.parseLong(anEvent.getField(P_WAIT)); + + // Create servlet request for requesting next events (refresh) + String url = anEvent.getField(P_URL); + String jsRefreshTrigger = "\n"; + + + send(jsRefreshTrigger + END_DOCUMENT); + } else { + send(event2JavaScript(anEvent)); + } + } + + /** + * End HTML page in client browser. + */ + public void stop() { + // To be garbage collected if adapter remains active + servletOut = null; + } + + /** + * Send any string to browser. + */ + protected void send(String s) throws IOException { + // Send string to browser. + // Log.debug("Adapter: sending: " + s); + if (servletOut == null) { + throw new IOException("Client adapter was stopped"); + } + + servletOut.print(s); + + servletOut.flush(); + + // Note: this doesn't seem to have effect + // in Tomcat 4/5 if the client already disconnected. + servletRsp.flushBuffer(); + + bytesSent += s.length(); + Log.debug("bytesSent= " + bytesSent); + // Log.debug("BCA sent event: " + s); + } + + /** + * Converts the Java Event to a JavaScript function call in browser page. + */ + protected String event2JavaScript(Event event) throws IOException { + + // Convert the event to a comma-separated string. + String jsArgs = ""; + for (Iterator iter = event.getFieldNames(); iter.hasNext();) { + String name = (String) iter.next(); + String value = event.getField(name); + String nextArgument = (jsArgs.equals("") ? "" : ",") + "'" + name + "'" + ", \"" + value + "\""; + jsArgs += nextArgument; + } + + // Construct and return the function call */ + return ""; + } + +} + +/* + * $Log: BrowserAdapter.java,v $ + * Revision 1.6 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.5 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:44 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.12 2005/02/15 13:30:23 justb + * changes for Tomcat buffering (now working in tc4 and 5.0) + * + * Revision 1.11 2005/01/24 22:45:58 justb + * getting safari to work + * + * Revision 1.10 2005/01/18 16:46:27 justb + * buffer size setting ignored by tomcat workings + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:07 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:02 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/10/30 14:15:47 just + * no message + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ClientAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ClientAdapter.java new file mode 100755 index 0000000000..c7ea141fee --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ClientAdapter.java @@ -0,0 +1,72 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.IOException; + +/** + * Adapter interface for encapsulation of specific HTTP clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ClientAdapter.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public interface ClientAdapter { + + /** + * Start event push. + */ + public void start() throws IOException; + + /** + * Push single Event to client. + */ + public void push(Event anEvent) throws IOException; + + /** + * Stop event push. + */ + public void stop() throws IOException; +} + +/* + * $Log: ClientAdapter.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/21 11:50:45 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Command.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Command.java new file mode 100755 index 0000000000..dbba4fae76 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Command.java @@ -0,0 +1,158 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Servlets; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Wraps pushlet request/response data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Command.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +public class Command implements Protocol { + + /** + * Pushlet request event. + */ + public final Event reqEvent; + + /** + * Pushlet response event. + */ + private Event rspEvent; + + /** + * HTTP Servlet GET/POST request. + */ + public final HttpServletRequest httpReq; + + /** + * HTTP Servlet GET/POST response. + */ + public final HttpServletResponse httpRsp; + + /** + * Pushlet session. + */ + public final Session session; + + /** + * Per-response client adapter. + */ + private ClientAdapter clientAdapter; + + /** + * Constructor. + */ + private Command(Session aSession, Event aRequestEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + session = aSession; + reqEvent = aRequestEvent; + httpReq = aHTTPReq; + httpRsp = aHTTPRsp; + } + + /** + * Create new Command object. + */ + public static Command create(Session aSession, Event aReqEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + return new Command(aSession, aReqEvent, aHTTPReq, aHTTPRsp); + } + + /** + * Set pushlet response event. + */ + public void setResponseEvent(Event aResponseEvent) { + rspEvent = aResponseEvent; + } + + /** + * Get pushlet response event. + */ + public Event getResponseEvent() { + return rspEvent; + } + + /** + * Get client adapter for request. + */ + public ClientAdapter getClientAdapter() throws PushletException { + if (clientAdapter == null) { + // Create and initialize client-specific adapter. + clientAdapter = createClientAdapter(); + } + return clientAdapter; + } + + /** + * Create client notifier based on "format" parameter passed in request. + */ + protected ClientAdapter createClientAdapter() throws PushletException { + + // Assumed to be set by parent. + String outputFormat = session.getFormat(); + + // Determine client adapter to create. + if (outputFormat.equals(FORMAT_JAVASCRIPT)) { + // Client expects to receive Events as JavaScript dispatch calls.. + return new BrowserAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_SERIALIZED_JAVA_OBJECT)) { + // Client expects to receive Events as Serialized Java Objects. + return new SerializedAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML)) { + // Client expects to receive Events as stream of XML docs. + return new XMLAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML_STRICT)) { + // Client expects to receive Events embedded in single XML doc. + return new XMLAdapter(httpRsp, true); + } else { + throw new PushletException("Null or invalid output format: " + outputFormat); + } + } + + /** + * Sends HTTP response headers. + */ + protected void sendResponseHeaders() { + // Just to try to prevent caching in any form. + Servlets.setNoCacheHeaders(httpRsp); + + // Close connection for Java enabled browsers + if (session.getUserAgent().indexOf("java") > 0) { + // The connection should be closed after this request + // NB: this allows sending a "long response". Some clients + // in particular java.net.URL in VMs > 1.1 that use HTTP/1.1 + // will block if + // - the content length is not sent + // - if Connection: close HTTP header is not sent. + // + // Since we don't know the content length we will assume + // the underlying servlet engine will use chunked encoding. + httpRsp.setHeader("Connection", "close"); + } + } + + +} + +/* + * $Log: Command.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.2 2005/02/28 17:25:15 justb + * commented + * + * Revision 1.1 2005/02/28 12:45:59 justb + * introduced Command class + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Config.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Config.java new file mode 100755 index 0000000000..c598e033d7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Config.java @@ -0,0 +1,152 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Sys; + +import java.io.File; +import java.util.Properties; + +/** + * Loads and maintains overall configuration. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Config.java,v 1.5 2007/11/23 21:10:17 justb Exp $ + */ +public class Config implements ConfigDefs { + private static final String PROPERTIES_FILE = "pushlet.properties"; + private static Properties properties; + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return an instance of class denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Object createObject(String aClassNameProp, String aDefault) throws PushletException { + Class clazz = getClass(aClassNameProp, aDefault); + try { + return clazz.newInstance(); + } catch (Throwable t) { + // Usually a misconfiguration + throw new PushletException("Cannot instantiate class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return a Class object denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Class getClass(String aClassNameProp, String aDefault) throws PushletException { + // Singleton + factory pattern: create object instance + // from configured class name + String clazz = (aDefault == null ? getProperty(aClassNameProp) : getProperty(aClassNameProp, aDefault)); + + try { + return Class.forName(clazz); + } catch (ClassNotFoundException t) { + // Usually a misconfiguration + throw new PushletException("Cannot find class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Initialize event sources from properties file. + */ + public static void load(String aDirPath) { + // Load Event sources using properties file. + try { + // Try loading through classpath first (e.g. in WEB-INF/classes or from .jar) + Log.info("Config: loading " + PROPERTIES_FILE + " from classpath"); + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("Config: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("Config: cannot load properties file from " + filePath, t); + + // Give up + return; + } + } + + Log.info("Config: loaded values=" + properties); + } + + public static String getProperty(String aName, String aDefault) { + return properties.getProperty(aName, aDefault); + } + + public static String getProperty(String aName) { + String value = properties.getProperty(aName); + if (value == null) { + throw new IllegalArgumentException("Unknown property: " + aName); + } + return value; + } + + public static boolean getBoolProperty(String aName) { + String value = getProperty(aName); + try { + return value.equals("true"); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static int getIntProperty(String aName) { + String value = getProperty(aName); + try { + return Integer.parseInt(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static long getLongProperty(String aName) { + String value = getProperty(aName); + try { + return Long.parseLong(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static boolean hasProperty(String aName) { + return properties.containsKey(aName); + } + + +} + +/* + * $Log: Config.java,v $ + * Revision 1.5 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ConfigDefs.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ConfigDefs.java new file mode 100755 index 0000000000..df00d41beb --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/ConfigDefs.java @@ -0,0 +1,104 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Definition of config property strings. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ConfigDefs.java,v 1.9 2007/12/07 12:57:40 justb Exp $ + */ +public interface ConfigDefs { + /** + * Class factory definitions, used to insert your custom classes. + */ + public static final String CONTROLLER_CLASS = "controller.class"; + public static final String DISPATCHER_CLASS = "dispatcher.class"; + public static final String LOGGER_CLASS = "logger.class"; + public static final String SESSION_MANAGER_CLASS = "sessionmanager.class"; + public static final String SESSION_CLASS = "session.class"; + public static final String SUBSCRIBER_CLASS = "subscriber.class"; + public static final String SUBSCRIPTION_CLASS = "subscription.class"; + + /** + * Session management. + */ + public static final String SESSION_ID_SIZE = "session.id.size"; + public static final String SESSION_ID_GENERATION = "session.id.generation"; + public static final String SESSION_ID_GENERATION_UUID = "uuid"; + public static final String SESSION_ID_GENERATION_RANDOMSTRING = "randomstring"; + public static final String SESSION_TIMEOUT_MINS = "session.timeout.mins"; + + public static final String SOURCES_ACTIVATE = "sources.activate"; + + /** + * Logging + */ + public static final String LOG_LEVEL = "log.level"; + public static final int LOG_LEVEL_FATAL = 1; + public static final int LOG_LEVEL_ERROR = 2; + public static final int LOG_LEVEL_WARN = 3; + public static final int LOG_LEVEL_INFO = 4; + public static final int LOG_LEVEL_DEBUG = 5; + public static final int LOG_LEVEL_TRACE = 6; + + /** + * Queues + */ + public static final String QUEUE_SIZE = "queue.size"; + public static final String QUEUE_READ_TIMEOUT_MILLIS = "queue.read.timeout.millis"; + public static final String QUEUE_WRITE_TIMEOUT_MILLIS = "queue.write.timeout.millis"; + + /** + * Listening modes. + */ + public static final String LISTEN_FORCE_PULL_ALL = "listen.force.pull.all"; + public static final String LISTEN_FORCE_PULL_AGENTS = "listen.force.pull.agents"; + + + public static final String PULL_REFRESH_TIMEOUT_MILLIS = "pull.refresh.timeout.millis"; + public static final String PULL_REFRESH_WAIT_MIN_MILLIS = "pull.refresh.wait.min.millis"; + public static final String PULL_REFRESH_WAIT_MAX_MILLIS = "pull.refresh.wait.max.millis"; + + + public static final String POLL_REFRESH_TIMEOUT_MILLIS = "poll.refresh.timeout.millis"; + public static final String POLL_REFRESH_WAIT_MIN_MILLIS = "poll.refresh.wait.min.millis"; + public static final String POLL_REFRESH_WAIT_MAX_MILLIS = "poll.refresh.wait.max.millis"; + +} + +/* + * $Log: ConfigDefs.java,v $ + * Revision 1.9 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.8 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2007/11/10 14:48:35 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/21 16:59:00 justb + * SessionManager and session lease introduced + * + * Revision 1.3 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.2 2005/02/21 11:16:44 justb + * add log level config prop + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Controller.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Controller.java new file mode 100755 index 0000000000..ca90b1539e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Controller.java @@ -0,0 +1,502 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; + +/** + * Handles servlet requests from client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Controller.java,v 1.9 2007/11/23 14:33:07 justb Exp $ + */ +public class Controller implements Protocol, ConfigDefs { + + private Session session; + + /** + * Protected constructor as we create through factory method. + */ + protected Controller() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Controller object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Controller create(Session aSession) throws PushletException { + Controller controller; + try { + controller = (Controller) Config.getClass(CONTROLLER_CLASS, "nl.justobjects.pushlet.core.Controller").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Controller from config", t); + } + controller.session = aSession; + return controller; + } + + /** + * Handle command. + */ + public void doCommand(Command aCommand) { + try { + // Update lease time to live + session.kick(); + + // Set remote IP address of client + session.setAddress(aCommand.httpReq.getRemoteAddr()); + + debug("doCommand() event=" + aCommand.reqEvent); + + // Get event type + String eventType = aCommand.reqEvent.getEventType(); + + // Determine action based on event type + if (eventType.equals(Protocol.E_REFRESH)) { + // Pull/poll mode clients that refresh + doRefresh(aCommand); + } else if (eventType.equals(Protocol.E_SUBSCRIBE)) { + // Subscribe + doSubscribe(aCommand); + } else if (eventType.equals(Protocol.E_UNSUBSCRIBE)) { + // Unsubscribe + doUnsubscribe(aCommand); + } else if (eventType.equals(Protocol.E_JOIN)) { + // Join + doJoin(aCommand); + } else if (eventType.equals(Protocol.E_JOIN_LISTEN)) { + // Join and listen (for simple and e.g. REST apps) + doJoinListen(aCommand); + } else if (eventType.equals(Protocol.E_LEAVE)) { + // Leave + doLeave(aCommand); + } else if (eventType.equals(Protocol.E_HEARTBEAT)) { + // Heartbeat mainly to do away with browser "busy" cursor + doHeartbeat(aCommand); + } else if (eventType.equals(Protocol.E_PUBLISH)) { + // Publish event + doPublish(aCommand); + } else if (eventType.equals(Protocol.E_LISTEN)) { + // Listen to pushed events + doListen(aCommand); + } + + // Handle response back to client + if (eventType.endsWith(Protocol.E_LISTEN) || + eventType.equals(Protocol.E_REFRESH)) { + // Data channel events + // Loops until refresh or connection closed + getSubscriber().fetchEvents(aCommand); + + } else { + // Send response for control commands + sendControlResponse(aCommand); + } + + } catch (Throwable t) { + warn("Exception in doCommand(): " + t); + t.printStackTrace(); + } + } + + public String toString() { + return session.toString(); + } + + /** + * Handle heartbeat event. + */ + protected void doHeartbeat(Command aCommand) { + + // Set heartbeat acknowledgement to client + aCommand.setResponseEvent(new Event(E_HEARTBEAT_ACK)); + } + + /** + * Handle Join request. + */ + protected void doJoin(Command aCommand) throws PushletException { + + Event responseEvent = null; + + try { + + session.start(); + + // Determine format for encoding Events to client. + // Default assume a userAgent window on the other end. + String format = aCommand.reqEvent.getField(P_FORMAT, FORMAT_JAVASCRIPT); + + session.setFormat(format); + responseEvent = new Event(E_JOIN_ACK); + + // Set unique subscriber id and encoding format + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_FORMAT, format); + info("joined"); + } catch (Throwable t) { + session.stop(); + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doJoin() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle JoinListen request. + */ + protected void doJoinListen(Command aCommand) throws PushletException { + + // Basically bundles a join and a listen + // This request is handly for simple apps that + // need to do a single request to get events immediately + // For example in RESTful apps. + + // First do regular join + doJoin(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If successful do the listen + doListen(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If still ok do the listen ack + aCommand.getResponseEvent().setField(P_EVENT, E_JOIN_LISTEN_ACK); + } + } + } + + /** + * Handle Leave request. + */ + protected void doLeave(Command aCommand) throws IOException { + + Event responseEvent = null; + + try { + // Also removes all subscriptions + session.stop(); + + // Prepare acknowledgement + responseEvent = new Event(E_LEAVE_ACK); + + // Set unique subscriber id + responseEvent.setField(P_ID, session.getId()); + info("left"); + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doLeave() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle Listen request. + */ + protected void doListen(Command aCommand) throws PushletException { + + + String mode = MODE_STREAM; + // Should we always force "pull" mode ? + if (Config.getBoolProperty(LISTEN_FORCE_PULL_ALL)) { + mode = MODE_PULL; + } else { + // Determine optimal mode determined by parameter and/or user agent + // Mode param determines how events are transfered to the client + + // In "stream" mode, a stream of events is sent, i.e. the document + // is neverending. In "pull" or "poll" mode a complete document is returned + // ending with a request to refresh. + mode = aCommand.reqEvent.getField(P_MODE, MODE_STREAM); + + String userAgent = aCommand.httpReq.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + for (int i = 0; i < session.FORCED_PULL_AGENTS.length; i++) { + if ((userAgent.indexOf(session.FORCED_PULL_AGENTS[i]) != -1)) { + info("Forcing pull mode for agent=" + userAgent); + mode = MODE_PULL; + break; + } + } + } else { + userAgent = "unknown"; + } + } + + getSubscriber().setMode(mode); + + // Prepare acknowledgement + Event listenAckEvent = new Event(E_LISTEN_ACK); + + // Add subscription(s) if subject(s) specified + String subject = aCommand.reqEvent.getField(P_SUBJECT); + if (subject != null) { + // Optional label for subscription + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + + // Add a subscription + Subscription subscription = getSubscriber().addSubscription(subject, label); + + // Add subscription id and optional label to listen-ack event + listenAckEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + listenAckEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + } + + // Set unique subscriber id, push mode and encoding format + listenAckEvent.setField(P_ID, session.getId()); + listenAckEvent.setField(P_MODE, mode); + listenAckEvent.setField(P_FORMAT, session.getFormat()); + + // Activate the subscriber + getSubscriber().start(); + + // Enqueue listen ack event on data channel + aCommand.setResponseEvent(listenAckEvent); + + info("Listening mode=" + mode + " userAgent=" + session.getUserAgent()); + + } + + /** + * Handle Publish request. + */ + protected void doPublish(Command aCommand) { + Event responseEvent = null; + + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + aCommand.reqEvent.setField(P_FROM, session.getId()); + aCommand.reqEvent.setField(P_EVENT, E_DATA); + + // Event may be targeted to specific user (p_to field) + String to = aCommand.reqEvent.getField(P_TO); + if (to != null) { + Dispatcher.getInstance().unicast(aCommand.reqEvent, to); + } else { + // No to: multicast + debug("doPublish() event=" + aCommand.reqEvent); + Dispatcher.getInstance().multicast(aCommand.reqEvent); + } + + // Acknowledge + responseEvent = new Event(E_PUBLISH_ACK); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doPublish() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle refresh event. + */ + protected void doRefresh(Command aCommand) { + // Set ack + aCommand.setResponseEvent(new Event(E_REFRESH_ACK)); + } + + /** + * Handle Subscribe request. + */ + protected void doSubscribe(Command aCommand) throws IOException { + + Event responseEvent = null; + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + Subscription subscription = null; + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + subscription = getSubscriber().addSubscription(subject, label); + + // Acknowledge + responseEvent = new Event(E_SUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBJECT, subject); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + info("subscribed to " + subject + " sid=" + subscription.getId()); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doSubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle Unsubscribe request. + */ + protected void doUnsubscribe(Command aCommand) throws IOException { + + + Event responseEvent = null; + try { + String subscriptionId = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_ID); + if (subscriptionId == null) { + // Unsuscbribe all + getSubscriber().removeSubscriptions(); + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + info("unsubscribed all"); + } else { + // Subscription id provided: remove Subscription + Subscription subscription = getSubscriber().removeSubscription(subscriptionId); + if (subscription == null) { + // Unknown subscription id: return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subscription for sid=" + subscriptionId); + warn("unsubscribe: no subscription for sid=" + subscriptionId); + } else { + // OK return ack + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + responseEvent.setField(P_SUBJECT, subscription.getSubject()); + if (subscription.getLabel() != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + info("unsubscribed sid= " + subscriptionId); + } + } + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doUnsubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + public Subscriber getSubscriber() { + return session.getSubscriber(); + } + + /** + * Send response on the control channel. + */ + protected void sendControlResponse(Command aCommand) { + try { + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + aCommand.getClientAdapter().start(); + + // Push to client through client adapter + aCommand.getClientAdapter().push(aCommand.getResponseEvent()); + + // One shot response + aCommand.getClientAdapter().stop(); + } catch (Throwable t) { + session.stop(); + } + } + + + /** + * Info. + */ + protected void info(String s) { + session.info("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Controller] " + s); + } + + +} + +/* + * $Log: Controller.java,v $ + * Revision 1.9 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.8 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.7 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:00 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Dispatcher.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Dispatcher.java new file mode 100755 index 0000000000..5cd739d5bd --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Dispatcher.java @@ -0,0 +1,265 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Routes Events to Subscribers. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Dispatcher.java,v 1.9 2007/12/04 13:55:53 justb Exp $ + */ +public class Dispatcher implements Protocol, ConfigDefs { + /** + * Singleton pattern: single instance. + */ + private static Dispatcher instance; + protected SessionManagerVisitor sessionManagerVisitor; + + static { + try { + instance = (Dispatcher) Config.getClass(DISPATCHER_CLASS, "nl.justobjects.pushlet.core.Dispatcher").newInstance(); + Log.info("Dispatcher created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate Dispatcher from config", t); + } + } + + /** + * Singleton pattern with factory method: protected constructor. + */ + protected Dispatcher() { + + } + + /** + * Singleton pattern: get single instance. + */ + public static Dispatcher getInstance() { + return instance; + } + + /** + * Send event to all subscribers. + */ + public synchronized void broadcast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Object[] args = new Object[2]; + args[1] = anEvent; + Method method = sessionManagerVisitor.getMethod("visitBroadcast"); + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + /** + * Send event to subscribers matching Event subject. + */ + public synchronized void multicast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Method method = sessionManagerVisitor.getMethod("visitMulticast"); + Object[] args = new Object[2]; + args[1] = anEvent; + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + + /** + * Send event to specific subscriber. + */ + public synchronized void unicast(Event event, String aSessionId) { + // Get subscriber to send event to + Session session = SessionManager.getInstance().getSession(aSessionId); + if (session == null) { + Log.warn("unicast: session with id=" + aSessionId + " does not exist"); + return; + } + + // Send Event to subscriber. + session.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Start Dispatcher. + */ + public void start() throws PushletException { + Log.info("Dispatcher started"); + + // Create callback for SessionManager visits. + sessionManagerVisitor = new SessionManagerVisitor(); + } + + /** + * Stop Dispatcher. + */ + public void stop() { + // Send abort control event to all subscribers. + Log.info("Dispatcher stopped: broadcast abort to all subscribers"); + broadcast(new Event(E_ABORT)); + } + + /** + * Supplies Visitor methods for callbacks from SessionManager. + */ + private class SessionManagerVisitor { + private final Map visitorMethods = new HashMap(2); + + SessionManagerVisitor() throws PushletException { + + try { + // Setup Visitor Methods for callback from SessionManager + // This is a slight opitmization over creating Method objects + // on each invokation. + Class[] argsClasses = {Session.class, Event.class}; + visitorMethods.put("visitMulticast", this.getClass().getMethod("visitMulticast", argsClasses)); + visitorMethods.put("visitBroadcast", this.getClass().getMethod("visitBroadcast", argsClasses)); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup SessionManagerVisitor", e); + } + } + + /** + * Return Visitor Method by name. + */ + public Method getMethod(String aName) { + return (Method) visitorMethods.get(aName); + + } + + /** + * Visitor method called by SessionManager. + */ + public void visitBroadcast(Session aSession, Event event) { + aSession.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Visitor method called by SessionManager. + */ + public void visitMulticast(Session aSession, Event event) { + Subscriber subscriber = aSession.getSubscriber(); + Event clonedEvent; + Subscription subscription; + + // Send only if the subscriber's criteria + // match the event. + if ((subscription = subscriber.match(event)) != null) { + // Personalize event + clonedEvent = (Event) event.clone(); + + // Set subscription id and optional label + clonedEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (subscription.getLabel() != null) { + event.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + + subscriber.onEvent(clonedEvent); + } + } + } +} + +/* + * $Log: Dispatcher.java,v $ + * Revision 1.9 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.5 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.4 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.3 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.2 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.1 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.14 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.13 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.12 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.11 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.10 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.9 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.8 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.7 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.6 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.5 2004/03/10 13:59:28 justb + * rewrite using Collection classes and finer synchronization + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 08:54:40 justb + * added getSubscriberCount() and use Log + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Event.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Event.java new file mode 100755 index 0000000000..e9a0aaa48b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Event.java @@ -0,0 +1,184 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Sys; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Represents the event data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Event.java,v 1.13 2007/11/23 14:33:07 justb Exp $ + */ +public class Event implements Protocol, Serializable { + + protected Map attributes = new HashMap(3); + + public Event(String anEventType) { + this(anEventType, null); + } + + public Event(String anEventType, Map theAttributes) { + + if (theAttributes != null) { + setAttrs(theAttributes); + } + + // Set required field event type + setField(P_EVENT, anEventType); + + // Set time in seconds since 1970 + setField(P_TIME, System.currentTimeMillis() / 1000); + } + + public Event(Map theAttributes) { + if (!theAttributes.containsKey(P_EVENT)) { + throw new IllegalArgumentException(P_EVENT + " not found in attributes"); + } + setAttrs(theAttributes); + } + + public static Event createDataEvent(String aSubject) { + return createDataEvent(aSubject, null); + } + + public static Event createDataEvent(String aSubject, Map theAttributes) { + Event dataEvent = new Event(E_DATA, theAttributes); + dataEvent.setField(P_SUBJECT, aSubject); + return dataEvent; + } + + public String getEventType() { + return getField(P_EVENT); + } + + public String getSubject() { + return getField(P_SUBJECT); + } + + public void setField(String name, String value) { + attributes.put(name, value); + } + + public void setField(String name, int value) { + attributes.put(name, value + ""); + } + + public void setField(String name, long value) { + attributes.put(name, value + ""); + } + + public String getField(String name) { + return (String) attributes.get(name); + } + + /** + * Return field; if null return default. + */ + public String getField(String name, String aDefault) { + String result = getField(name); + return result == null ? aDefault : result; + } + + public Iterator getFieldNames() { + return attributes.keySet().iterator(); + } + + public String toString() { + return attributes.toString(); + } + + /** + * Convert to HTTP query string. + */ + public String toQueryString() { + String queryString = ""; + String amp = ""; + for (Iterator iter = getFieldNames(); iter.hasNext();) { + String nextAttrName = (String) iter.next(); + String nextAttrValue = getField(nextAttrName); + queryString = queryString + amp + nextAttrName + "=" + nextAttrValue; + // After first add "&". + amp = "&"; + } + + return queryString; + } + + public String toXML(boolean strict) { + String xmlString = " +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.*; +import java.util.HashMap; + +/** + * Parses XML into Event objects. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventParser.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventParser { + + + private EventParser() { + } + + /** + * Parse Event from a File. + */ + public static Event parse(File aFile) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(aFile)); + return parse(br); + } + + /** + * Parse Event from input Reader. + */ + public static Event parse(Reader aReader) throws IOException { + StringBuffer preparsedString = new StringBuffer(24); + + // First find the opening tag ('<') + char nextChar; + while ((nextChar = (char) aReader.read()) != '<') ; + + // Append '<' + preparsedString.append(nextChar); + + // Then find end-tag ('>'), appending all chars to preparsed string. + do { + nextChar = (char) aReader.read(); + preparsedString.append(nextChar); + } while (nextChar != '>'); + + return parse(preparsedString.toString()); + } + + /** + * Parse Event from a String. + */ + public static Event parse(String aString) throws IOException { + aString = aString.trim(); + + if (!aString.startsWith("<") || !aString.endsWith("/>")) { + throw new IOException("No start or end tag found while parsing event [" + aString + "]"); + } + + // Create the attributes object. + HashMap properties = new HashMap(3); + + // Remove the start and end (< ... />) from the string + aString = aString.substring(1, aString.length() - 2).trim(); + + int index = 0; + + // Parse the tag + while (!Character.isWhitespace(aString.charAt(index)) + && (index < aString.length())) { + index++; + } + + // We don't use the tag: remove from string + aString = aString.substring(index).trim(); + index = 0; + + String attrName; + String attrValue; + + while (index < aString.length()) { + + // Parse attribute name + while ((aString.charAt(index) != '=') + && (index < aString.length())) { + index++; + } + + // Create attr name string + attrName = aString.substring(0, index).trim(); + + // remove the attributeName and the '=' from the string + aString = aString.substring(index + 1).trim(); + index = 1; // read past the first wrapping "\"" + + // Parse attribute value + while ((aString.charAt(index) != '\"') + && (index < aString.length())) { + + // bypass the special characters '\' and '"' inside the + // attributevalue itself which are deliniated with a preceding + // '\' + if (aString.charAt(index) == '\\') { + aString = aString.substring(0, index) + + aString.substring(index + 1); // remove the '\' + } + + index++; + } + + // create the attribute value; exclude the wrapping quote-characters + attrValue = aString.substring(1, index); + + // Set the attribute N/V + properties.put(attrName, attrValue); + + aString = aString.substring(index + 1).trim(); + index = 0; + } + + return new Event(properties); + } + + /** + * Test method: use files to test. + */ + public static void main(String[] args) { + try { + Event event = parse(new File(args[0])); + System.out.println("OK parsed Event file " + args[0]); + System.out.println(event.toXML()); + + event = parse(event.toXML()); + System.out.println("OK parsed Event string"); + System.out.println(event.toXML()); + } catch (Throwable t) { + System.out.println("Error parsing event file: " + args[0]); + t.printStackTrace(); + } + } +} + +/* + * $Log: EventParser.java,v $ + * Revision 1.3 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.3 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/05/18 16:12:27 justb + * adding support for XML encoded Events + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventPullSource.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventPullSource.java new file mode 100755 index 0000000000..cf63d98389 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventPullSource.java @@ -0,0 +1,185 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventPullSource.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * ABC for specifc EventPullSources. + */ +abstract public class EventPullSource implements EventSource, Runnable { + private volatile boolean alive = false; + private volatile boolean active = false; + private static int threadNum = 0; + private Thread thread; + + public EventPullSource() { + } + + abstract protected long getSleepTime(); + + abstract protected Event pullEvent(); + + public void start() { + thread = new Thread(this, "EventPullSource-" + (++threadNum)); + thread.setDaemon(true); + thread.start(); + } + + public boolean isAlive() { + return alive; + } + + /** + * Stop the event generator thread. + */ + public void stop() { + alive = false; + + if (thread != null) { + thread.interrupt(); + thread = null; + } + + } + + /** + * Activate the event generator thread. + */ + synchronized public void activate() { + if (active) { + return; + } + active = true; + if (!alive) { + start(); + return; + } + Log.debug(getClass().getName() + ": notifying..."); + notifyAll(); + } + + /** + * Deactivate the event generator thread. + */ + public void passivate() { + if (!active) { + return; + } + active = false; + } + + /** + * Main loop: sleep, generate event and publish. + */ + public void run() { + Log.debug(getClass().getName() + ": starting..."); + alive = true; + while (alive) { + try { + + Thread.sleep(getSleepTime()); + + // Stopped during sleep: end loop. + if (!alive) { + break; + } + + // If passivated wait until we get + // get notify()-ied. If there are no subscribers + // it wasts CPU to remain producing events... + synchronized (this) { + while (!active) { + Log.debug(getClass().getName() + ": waiting..."); + wait(); + } + } + + } catch (InterruptedException e) { + break; + } + + try { + // Derived class should produce an event. + Event event = pullEvent(); + + // Let the publisher push it to subscribers. + Dispatcher.getInstance().multicast(event); + } catch (Throwable t) { + Log.warn("EventPullSource exception while multicasting ", t); + t.printStackTrace(); + } + } + Log.debug(getClass().getName() + ": stopped"); + } +} + +/* + * $Log: EventPullSource.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.13 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.12 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventQueue.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventQueue.java new file mode 100755 index 0000000000..85c730e2d7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventQueue.java @@ -0,0 +1,269 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +/** + * FIFO queue with guarded suspension. + * Purpose
    + *

    + * Implementation
    + * FIFO queue class implemented with circular array. The enQueue() and + * deQueue() methods use guarded suspension according to a readers/writers + * pattern, implemented with java.lang.Object.wait()/notify(). + *

    + * Examples
    + *

    + *
    + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventQueue.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventQueue { + /** + * Defines maximum queue size + */ + private int capacity = 8; + private Event[] queue = null; + private int front, rear; + + /** + * Construct queue with default (8) capacity. + */ + public EventQueue() { + this(8); + } + + /** + * Construct queue with specified capacity. + */ + public EventQueue(int capacity) { + this.capacity = capacity; + queue = new Event[capacity]; + front = rear = 0; + } + + /** + * Put item in queue; waits() indefinitely if queue is full. + */ + public synchronized boolean enQueue(Event item) throws InterruptedException { + return enQueue(item, -1); + } + + /** + * Put item in queue; if full wait maxtime. + */ + public synchronized boolean enQueue(Event item, long maxWaitTime) throws InterruptedException { + + // Wait (optional maxtime) as long as the queue is full + while (isFull()) { + if (maxWaitTime > 0) { + // Wait at most maximum time + wait(maxWaitTime); + + // Timed out or woken; if still full we + // had bad luck and return failure. + if (isFull()) { + return false; + } + } else { + wait(); + } + } + + // Put item in queue + queue[rear] = item; + rear = next(rear); + + // Wake up waiters; NOTE: first waiter will eat item + notifyAll(); + return true; + } + + /** + * Get head; if empty wait until something in queue. + */ + public synchronized Event deQueue() throws InterruptedException { + return deQueue(-1); + } + + /** + * Get head; if empty wait for specified time at max. + */ + public synchronized Event deQueue(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue item + Event result = fetchNext(); + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return result; + } + + /** + * Get all queued Events. + */ + public synchronized Event[] deQueueAll(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue all items item + Event[] events = new Event[getSize()]; + for (int i = 0; i < events.length; i++) { + events[i] = fetchNext(); + } + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return events; + } + + public synchronized int getSize() { + return (rear >= front) ? (rear - front) : (capacity - front + rear); + } + + /** + * Is the queue empty ? + */ + public synchronized boolean isEmpty() { + return front == rear; + } + + /** + * Is the queue full ? + */ + public synchronized boolean isFull() { + return (next(rear) == front); + } + + /** + * Circular counter. + */ + private int next(int index) { + return (index + 1 < capacity ? index + 1 : 0); + } + + /** + * Circular counter. + */ + private Event fetchNext() { + Event temp = queue[front]; + queue[front] = null; + front = next(front); + return temp; + } + + public static void p(String s) { + System.out.println(s); + } + + public static void main(String[] args) { + EventQueue q = new EventQueue(8); + Event event = new Event("t"); + try { + q.enQueue(event); + p("(1) size = " + q.getSize()); + q.enQueue(event); + p("(2) size = " + q.getSize()); + q.deQueue(); + p("(1) size = " + q.getSize()); + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(3) size = " + q.getSize()); + q.deQueue(); + p("(2) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + p("(7) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + p("(4) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(1) size = " + q.getSize()); + } catch (InterruptedException ie) { + } + } +} + +/* +* $Log: EventQueue.java,v $ +* Revision 1.3 2007/11/23 14:33:07 justb +* core classes now configurable through factory +* +* Revision 1.2 2005/02/21 11:50:46 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.6 2005/02/16 12:16:16 justb +* added support for "poll" mode +* +* Revision 1.5 2005/01/13 14:47:15 justb +* control evt: send response on same (control) connection +* +* Revision 1.4 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSource.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSource.java new file mode 100755 index 0000000000..afd34ed365 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSource.java @@ -0,0 +1,70 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventSource.java,v 1.7 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * Interface for specifc Event(Pull/Push)Sources. + */ +public interface EventSource { + /** + * Activate the event source. + */ + public void activate(); + + /** + * Deactivate the event source. + */ + public void passivate(); + + /** + * Halt the event source. + */ + public void stop(); +} + +/* + * $Log: EventSource.java,v $ + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSourceManager.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSourceManager.java new file mode 100755 index 0000000000..b6b496637a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/EventSourceManager.java @@ -0,0 +1,169 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; +import java.io.File; + +/** + * Maintains lifecycle of event sources. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventSourceManager.java,v 1.14 2007/11/10 13:44:02 justb Exp $ + */ +public class EventSourceManager { + private static Vector eventSources = new Vector(0); + private static final String PROPERTIES_FILE = "sources.properties"; + + /** + * Initialize event sources from properties file. + */ + public static void start(String aDirPath) { + // Load Event sources using properties file. + Log.info("EventSourceManager: start"); + + Properties properties = null; + + try { + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("EventSourceManager: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("EventSourceManager: cannot load properties file from " + filePath, t); + + // Give up + Log.warn("EventSourceManager: not starting local event sources (maybe that is what you want)"); + return; + } + } + + // Create event source collection + eventSources = new Vector(properties.size()); + + // Add the configured sources + for (Enumeration e = properties.keys(); e.hasMoreElements();) { + String nextKey = (String) e.nextElement(); + String nextClass = properties.getProperty(nextKey); + EventSource nextEventSource = null; + try { + nextEventSource = (EventSource) Class.forName(nextClass).newInstance(); + Log.info("created EventSource: key=" + nextKey + " class=" + nextClass); + eventSources.addElement(nextEventSource); + } catch (Exception ex) { + Log.warn("Cannot create EventSource: class=" + nextClass, ex); + } + } + + activate(); + } + + /** + * Activate all event sources. + */ + public static void activate() { + Log.info("Activating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).activate(); + } + Log.info("EventSources activated"); + } + + /** + * Deactivate all event sources. + */ + public static void passivate() { + Log.info("Passivating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).passivate(); + } + Log.info("EventSources passivated"); + } + + /** + * Halt event sources. + */ + public static void stop() { + Log.info("Stopping " + eventSources.size() + " EventSources..."); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).stop(); + } + Log.info("EventSources stopped"); + } + +} + +/* + * $Log: EventSourceManager.java,v $ + * Revision 1.14 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.13 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.12 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/15 13:29:49 justb + * use Sys.loadPropertiesResource() + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:41:35 justb + * replace static initalizer with explicit init() + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/10/30 14:15:47 just + * no message + * + * Revision 1.3 2000/08/31 08:26:54 just + * Changed classloader that loads eventsources.properties to use EventSourceManager's classloader + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Protocol.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Protocol.java new file mode 100755 index 0000000000..79c265f62f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Protocol.java @@ -0,0 +1,294 @@ +// Copyright (c) 2004 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Constants for Pushlet protocols. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Protocol.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + */ +public interface Protocol { + /** + * Default URI . + */ + public static final String DEFAULT_SERVLET_URI = "/pushlet/pushlet.srv"; + + // + // Common protocol header/parameter names + // + + /** + * Event type (join, leave, data, subscribe etc) . + */ + public static final String P_EVENT = "p_event"; + + /** + * Time in seconds since 1970 + */ + public static final String P_TIME = "p_time"; + + /** + * Event sequence number, numbers per-client. + */ + public static final String P_SEQ = "p_seq"; + + /** + * Subject (topic) of data event. + */ + public static final String P_SUBJECT = "p_subject"; + + /** + * Originator of Event. + */ + public static final String P_FROM = "p_from"; + + /** + * Addressee of Event, subject or client p_id. + */ + public static final String P_TO = "p_to"; + + /** + * Identifier for client instance within server. + */ + public static final String P_ID = "p_id"; + + /** + * Subscription id, identifies single subscription. + */ + public static final String P_SUBSCRIPTION_ID = "p_sid"; + + /** + * Format to receive events + */ + public static final String P_FORMAT = "p_format"; + + /** + * Protocol mode. + */ + public static final String P_MODE = "p_mode"; + + /** + * Reason for errors. + */ + public static final String P_REASON = "p_reason"; + + /** + * URL attribute. + */ + public static final String P_URL = "p_url"; + + /** + * Wait attribute. + */ + public static final String P_WAIT = "p_wait"; + + /** + * Subscription label, may be used to return user-specific + * token with a data event, e.g. the name of a function for a callback. + */ + public static final String P_SUBSCRIPTION_LABEL = "p_label"; + + // + // Event values with direction for P_EVENT (C=client, S=server) + // + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN = "join"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_ACK = "join-ack"; + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN_LISTEN = "join-listen"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_LISTEN_ACK = "join-listen-ack"; + + /** + * C-->S Client starts listening. + */ + public static final String E_LISTEN = "listen"; + + /** + * S-->C Ack of listen. + */ + public static final String E_LISTEN_ACK = "listen-ack"; + + /** + * C-->S Client leaves server. + */ + public static final String E_LEAVE = "leave"; + + /** + * S-->C Ack of leave. + */ + public static final String E_LEAVE_ACK = "leave-ack"; + + /** + * C-->S Publish to subject. + */ + public static final String E_PUBLISH = "publish"; + + /** + * S-->C Publish to subject acknowledge. + */ + public static final String E_PUBLISH_ACK = "publish-ack"; + + /** + * C-->S Subscribe to subject request. + */ + public static final String E_SUBSCRIBE = "subscribe"; + + /** + * S-->C Subscribe to subject acknowledge. + */ + public static final String E_SUBSCRIBE_ACK = "subscribe-ack"; + + /** + * C-->S Unsubscribe from subject request. + */ + public static final String E_UNSUBSCRIBE = "unsubscribe"; + + /** + * S--C Unsubscribe from subject acknowledge. + */ + public static final String E_UNSUBSCRIBE_ACK = "unsubscribe-ack"; + + /** + * S-->C Client error response, transitional error. + */ + public static final String E_NACK = "nack"; + + /** + * S-->C Client should abort, permanent error. + */ + public static final String E_ABORT = "abort"; + + /** + * S-->C Data. + */ + public static final String E_DATA = "data"; + + /** + * S-->C or C-->S Heartbeat. + */ + public static final String E_HEARTBEAT = "hb"; + + /** + * S-->C S-->C or C-->S Heartbeat confirmed. + */ + public static final String E_HEARTBEAT_ACK = "hb-ack"; + + /** + * S-->C or C-->S client refresh of data channel. + */ + public static final String E_REFRESH = "refresh"; + + /** + * S-->C client should refresh data channel. + */ + public static final String E_REFRESH_ACK = "refresh-ack"; + + // + // Values for P_FORMAT parameter + // + + /** + * JavaScript callback. + */ + public static String FORMAT_JAVASCRIPT = "js"; + + /** + * Java serialized object. + */ + public static String FORMAT_SERIALIZED_JAVA_OBJECT = "ser"; + + /** + * Stream of XML documents. + */ + public static String FORMAT_XML = "xml"; + + /** + * Single XML document containing zero or more events. + */ + public static String FORMAT_XML_STRICT = "xml-strict"; + + // + // Values for P_MODE parameter + // + public static final String MODE_STREAM = "stream"; + public static final String MODE_PULL = "pull"; + public static final String MODE_POLL = "poll"; + + // + // Values for special/reserved subjects + // TODO: use these to publish events when clients do these actions + // TODO: Dispatcher may intercept these subjects to send cached events + // + public static final String SUBJECT_META = "/meta"; + public static final String SUBJECT_META_SUBS = SUBJECT_META + "/subs"; + public static final String SUBJECT_META_JOINS = SUBJECT_META + "/joins"; + + +} + +/* + * $Log: Protocol.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.13 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.12 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.11 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.10 2005/02/16 12:16:17 justb + * added support for "poll" mode + * + * Revision 1.9 2005/01/24 22:46:02 justb + * getting safari to work + * + * Revision 1.8 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.7 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.6 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.5 2004/10/24 13:52:52 justb + * small fixes in client lib + * + * Revision 1.4 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.3 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/09/03 21:02:20 justb + * make more formalized protocol + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SerializedAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SerializedAdapter.java new file mode 100755 index 0000000000..462a4dd5c2 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SerializedAdapter.java @@ -0,0 +1,99 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.ObjectOutputStream; + +/** + * Implementation of ClientAdapter that sends Events as serialized objects. + *

    + * NOTE: You are discouraged to use this adapter, since it is Java-only + * and may have JVM-specific problems. Far better choice is to use XML + * and the XMLAdapter. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SerializedAdapter.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +class SerializedAdapter implements ClientAdapter { + private ObjectOutputStream out = null; + public static final String CONTENT_TYPE = "application/x-java-serialized-object"; + private HttpServletResponse servletRsp; + + /** + * Initialize. + */ + public SerializedAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + public void start() throws IOException { + + servletRsp.setContentType(CONTENT_TYPE); + + // Use a serialized object output stream + out = new ObjectOutputStream(servletRsp.getOutputStream()); + + // Don't need this further + servletRsp = null; + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + out.writeObject(anEvent); + + out.flush(); + } + + + public void stop() throws IOException { + } +} + +/* + * $Log: SerializedAdapter.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:13:48 justb + * fixed blocking for java.net.URL with HTTP/1.1 (JVMs > 1.1) + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Session.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Session.java new file mode 100755 index 0000000000..8adf9ba6f4 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Session.java @@ -0,0 +1,205 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +/** + * Represents client pushlet session state. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Session.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public class Session implements Protocol, ConfigDefs { + private Controller controller; + private Subscriber subscriber; + + private String userAgent; + private long LEASE_TIME_MILLIS = Config.getLongProperty(SESSION_TIMEOUT_MINS) * 60 * 1000; + private volatile long timeToLive = LEASE_TIME_MILLIS; + + public static String[] FORCED_PULL_AGENTS = Config.getProperty(LISTEN_FORCE_PULL_AGENTS).split(","); + + private String address = "unknown"; + private String format = FORMAT_XML; + + private String id; + + /** + * Protected constructor as we create through factory method. + */ + protected Session() { + } + + /** + * Create instance through factory method. + * + * @param anId a session id + * @return a Session object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Session create(String anId) throws PushletException { + Session session; + try { + session = (Session) Config.getClass(SESSION_CLASS, "nl.justobjects.pushlet.core.Session").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Session from config", t); + } + + // Init session + session.id = anId; + session.controller = Controller.create(session); + session.subscriber = Subscriber.create(session); + return session; + } + + /** + * Return (remote) Subscriber client's IP address. + */ + public String getAddress() { + return address; + } + + /** + * Return command controller. + */ + public Controller getController() { + return controller; + } + + /** + * Return Event format to send to client. + */ + public String getFormat() { + return format; + } + + /** + * Return (remote) Subscriber client's unique id. + */ + public String getId() { + return id; + } + + /** + * Return subscriber. + */ + public Subscriber getSubscriber() { + return subscriber; + } + + /** + * Return remote HTTP User-Agent. + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Set address. + */ + protected void setAddress(String anAddress) { + address = anAddress; + } + + /** + * Set event format to encode. + */ + protected void setFormat(String aFormat) { + format = aFormat; + } + + /** + * Set client HTTP UserAgent. + */ + public void setUserAgent(String aUserAgent) { + userAgent = aUserAgent; + } + + /** + * Decrease time to live. + */ + public void age(long aDeltaMillis) { + timeToLive -= aDeltaMillis; + } + + /** + * Has session timed out? + */ + public boolean isExpired() { + return timeToLive <= 0; + } + + /** + * Keep alive by resetting TTL. + */ + public void kick() { + timeToLive = LEASE_TIME_MILLIS; + } + + public void start() { + SessionManager.getInstance().addSession(this); + } + + public void stop() { + subscriber.stop(); + SessionManager.getInstance().removeSession(this); + } + + /** + * Info. + */ + public void info(String s) { + Log.info("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void warn(String s) { + Log.warn("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void debug(String s) { + Log.debug("S-" + this + ": " + s); + } + + public String toString() { + return getAddress() + "[" + getId() + "]"; + } +} + +/* + * $Log: Session.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SessionManager.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SessionManager.java new file mode 100755 index 0000000000..7d3441dc7b --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/SessionManager.java @@ -0,0 +1,386 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.rmi.server.UID; +import java.util.*; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * Manages lifecycle of Sessions. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SessionManager.java,v 1.12 2007/12/04 13:55:53 justb Exp $ + */ +public class SessionManager implements ConfigDefs { + + /** + * Singleton pattern: single instance. + */ + private static SessionManager instance; + + static { + // Singleton + factory pattern: create single instance + // from configured class name + try { + instance = (SessionManager) Config.getClass(SESSION_MANAGER_CLASS, "nl.justobjects.pushlet.core.SessionManager").newInstance(); + Log.info("SessionManager created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate SessionManager from config", t); + } + } + + /** + * Timer to schedule session leasing TimerTasks. + */ + private Timer timer; + private final long TIMER_INTERVAL_MILLIS = 60000; + + /** + * Map of active sessions, keyed by their id, all access is through mutex. + */ + private Map sessions = new HashMap(13); + + /** + * Cache of Sessions for iteration and to allow concurrent modification. + */ + private Session[] sessionCache = new Session[0]; + + /** + * State of SessionCache, becomes true whenever sessionCache out of sync with sessions Map. + */ + private boolean sessionCacheDirty = false; + + /** + * Lock for any operation on Sessions (Session Map and/or -cache). + */ + private final Object mutex = new Object(); + + /** + * Singleton pattern: protected constructor needed for derived classes. + */ + protected SessionManager() { + } + + /** + * Visitor pattern implementation for Session iteration. + *

    + * This method can be used to iterate over all Sessions in a threadsafe way. + * See Dispatcher.multicast and broadcast methods for examples. + * + * @param visitor the object that should implement method parm + * @param method the method to be called from visitor + * @param args arguments to be passed in visit method, args[0] will always be Session object + */ + public void apply(Object visitor, Method method, Object[] args) { + + synchronized (mutex) { + + // Refresh Session cache if required + // We use a cache for two reasons: + // 1. to prevent concurrent modification from within visitor method + // 2. some optimization (vs setting up Iterator for each apply() + if (sessionCacheDirty) { + // Clear out existing cache + for (int i = 0; i < sessionCache.length; i++) { + sessionCache[i] = null; + } + + // Refill cache and update state + sessionCache = (Session[]) sessions.values().toArray(sessionCache); + sessionCacheDirty = false; + } + + // Valid session cache: loop and call supplied Visitor method + Session nextSession; + for (int i = 0; i < sessionCache.length; i++) { + nextSession = sessionCache[i]; + + // Session cache may not be entirely filled + if (nextSession == null) { + break; + } + + try { + // First argument is always a Session object + args[0] = nextSession; + + // Use Java reflection to call the method passed by the Visitor + method.invoke(visitor, args); + } catch (IllegalAccessException e) { + Log.warn("apply: illegal method access: ", e); + } catch (InvocationTargetException e) { + Log.warn("apply: method invoke: ", e); + } + } + } + } + + /** + * Create new Session (but add later). + */ + public Session createSession(Event anEvent) throws PushletException { + // Trivial + return Session.create(createSessionId()); + } + + + /** + * Singleton pattern: get single instance. + */ + public static SessionManager getInstance() { + return instance; + } + + /** + * Get Session by session id. + */ + public Session getSession(String anId) { + synchronized (mutex) { + return (Session) sessions.get(anId); + } + } + + /** + * Get copy of listening Sessions. + */ + public Session[] getSessions() { + synchronized (mutex) { + return (Session[]) sessions.values().toArray(new Session[0]); + } + } + + /** + * Get number of listening Sessions. + */ + public int getSessionCount() { + synchronized (mutex) { + return sessions.size(); + } + } + + /** + * Get status info. + */ + public String getStatus() { + Session[] sessions = getSessions(); + StringBuffer statusBuffer = new StringBuffer(); + statusBuffer.append("SessionMgr: " + sessions.length + " sessions \\n"); + for (int i = 0; i < sessions.length; i++) { + statusBuffer.append(sessions[i] + "\\n"); + } + return statusBuffer.toString(); + } + + /** + * Is Session present?. + */ + public boolean hasSession(String anId) { + synchronized (mutex) { + return sessions.containsKey(anId); + } + } + + /** + * Add session. + */ + public void addSession(Session session) { + synchronized (mutex) { + sessions.put(session.getId(), session); + sessionCacheDirty = true; + } + // log(session.getId() + " at " + session.getAddress() + " adding "); + info(session.getId() + " at " + session.getAddress() + " added "); + } + + /** + * Register session for removal. + */ + public Session removeSession(Session aSession) { + synchronized (mutex) { + Session session = (Session) sessions.remove(aSession.getId()); + if (session != null) { + info(session.getId() + " at " + session.getAddress() + " removed "); + } + sessionCacheDirty = true; + return session; + } + } + + + /** + * Starts us. + */ + public void start() throws PushletException { + if (timer != null) { + stop(); + } + timer = new Timer(false); + timer.schedule(new AgingTimerTask(), TIMER_INTERVAL_MILLIS, TIMER_INTERVAL_MILLIS); + info("started; interval=" + TIMER_INTERVAL_MILLIS + "ms"); + } + + /** + * Stopis us. + */ + public void stop() { + if (timer != null) { + timer.cancel(); + timer = null; + } + synchronized (mutex) { + sessions.clear(); + } + info("stopped"); + } + + /** + * Create unique Session id. + */ + protected String createSessionId() { + // Use UUID if specified in config (thanks Uli Romahn) + if (Config.hasProperty(SESSION_ID_GENERATION) && Config.getProperty(SESSION_ID_GENERATION).equals(SESSION_ID_GENERATION_UUID)) { + // We want to be Java 1.4 compatible so use UID class (1.5+ we may use java.util.UUID). + return new UID().toString(); + } + + // Other cases use random name + + // Create a unique session id + // In 99.9999 % of the cases this should be generated at once + // We need the mutext to prevent the chance of creating + // same-valued ids (thanks Uli Romahn) + synchronized (mutex) { + String id; + while (true) { + id = Rand.randomName(Config.getIntProperty(SESSION_ID_SIZE)); + if (!hasSession(id)) { + // Created unique session id + break; + } + } + return id; + } + } + + /** + * Util: stdout printing. + */ + protected void info(String s) { + Log.info("SessionManager: " + new Date() + " " + s); + } + + /** + * Util: stdout printing. + */ + protected void warn(String s) { + Log.warn("SessionManager: " + s); + } + + /** + * Util: stdout printing. + */ + protected void debug(String s) { + Log.debug("SessionManager: " + s); + } + + /** + * Manages Session timeouts. + */ + private class AgingTimerTask extends TimerTask { + private long lastRun = Sys.now(); + private long delta; + private Method visitMethod; + + public AgingTimerTask() throws PushletException { + try { + // Setup Visitor Methods for callback from SessionManager + Class[] argsClasses = {Session.class}; + visitMethod = this.getClass().getMethod("visit", argsClasses); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup AgingTimerTask", e); + } + } + + /** + * Clock tick callback from Timer. + */ + public void run() { + long now = Sys.now(); + delta = now - lastRun; + lastRun = now; + debug("AgingTimerTask: tick"); + + // Use Visitor pattern to loop through Session objects (see visit() below) + getInstance().apply(this, visitMethod, new Object[1]); + } + + /** + * Callback from SessionManager during apply() + */ + public void visit(Session aSession) { + try { + // Age the lease + aSession.age(delta); + debug("AgingTimerTask: visit: " + aSession); + + // Stop session if lease expired + if (aSession.isExpired()) { + info("AgingTimerTask: Session expired: " + aSession); + aSession.stop(); + } + } catch (Throwable t) { + warn("AgingTimerTask: Error in timer task : " + t); + } + } + } +} + +/* + * $Log: SessionManager.java,v $ + * Revision 1.12 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.11 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.10 2007/11/10 14:47:45 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.9 2007/11/10 14:17:18 justb + * minor cosmetic changes just commit now + * + * Revision 1.8 2007/07/02 08:12:16 justb + * redo to original version of session cache (with break, but nullify array first) + * + * Revision 1.7 2007/07/02 07:33:02 justb + * small fix in sessionmgr for holes in sessioncache array (continue i.s.o. break) + * + * Revision 1.6 2006/11/18 12:13:47 justb + * made SessionManager constructor protected to allow constructing derived classes + * + * Revision 1.5 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.4 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.3 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.2 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.1 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscriber.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscriber.java new file mode 100755 index 0000000000..39f5ba0198 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscriber.java @@ -0,0 +1,469 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.net.URLEncoder; + +/** + * Handles data channel between dispatcher and client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscriber.java,v 1.26 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscriber implements Protocol, ConfigDefs { + private Session session; + + /** + * Blocking queue. + */ + private EventQueue eventQueue = new EventQueue(Config.getIntProperty(QUEUE_SIZE)); + + /** + * URL to be used in refresh requests in pull/poll modes. + */ + private long queueReadTimeoutMillis = Config.getLongProperty(QUEUE_READ_TIMEOUT_MILLIS); + private long queueWriteTimeoutMillis = Config.getLongProperty(QUEUE_WRITE_TIMEOUT_MILLIS); + private long refreshTimeoutMillis = Config.getLongProperty(PULL_REFRESH_TIMEOUT_MILLIS); + volatile long lastAlive = Sys.now(); + + /** + * Map of active subscriptions, keyed by their subscription id. + */ + private Map subscriptions = Collections.synchronizedMap(new HashMap(3)); + + /** + * Are we able to accept/send events ?. + */ + private volatile boolean active; + + /** + * Transfer mode (stream, pull, poll). + */ + private String mode; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscriber() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Subscriber object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Subscriber create(Session aSession) throws PushletException { + Subscriber subscriber; + try { + subscriber = (Subscriber) Config.getClass(SUBSCRIBER_CLASS, "nl.justobjects.pushlet.core.Subscriber").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + subscriber.session = aSession; + return subscriber; + } + + public void start() { + active = true; + } + + public void stop() { + removeSubscriptions(); + active = false; + } + + public void bailout() { + session.stop(); + } + + /** + * Are we still active to handle events. + */ + public boolean isActive() { + return active; + } + + /** + * Return client session. + */ + public Session getSession() { + return session; + } + + /** + * Get (session) id. + */ + public String getId() { + return session.getId(); + } + + /** + * Return subscriptions. + */ + public Subscription[] getSubscriptions() { + // todo: Optimize + return (Subscription[]) subscriptions.values().toArray(new Subscription[0]); + } + + /** + * Add a subscription. + */ + public Subscription addSubscription(String aSubject, String aLabel) throws PushletException { + Subscription subscription = Subscription.create(aSubject, aLabel); + subscriptions.put(subscription.getId(), subscription); + info("Subscription added subject=" + aSubject + " sid=" + subscription.getId() + " label=" + aLabel); + return subscription; + } + + /** + * Remove a subscription. + */ + public Subscription removeSubscription(String aSubscriptionId) { + Subscription subscription = (Subscription) subscriptions.remove(aSubscriptionId); + if (subscription == null) { + warn("No subscription found sid=" + aSubscriptionId); + return null; + } + info("Subscription removed subject=" + subscription.getSubject() + " sid=" + subscription.getId() + " label=" + subscription.getLabel()); + return subscription; + } + + /** + * Remove all subscriptions. + */ + public void removeSubscriptions() { + subscriptions.clear(); + } + + public String getMode() { + return mode; + } + + public void setMode(String aMode) { + mode = aMode; + } + + public long getRefreshTimeMillis() { + String minWaitProperty = PULL_REFRESH_WAIT_MIN_MILLIS; + String maxWaitProperty = PULL_REFRESH_WAIT_MAX_MILLIS; + if (mode.equals((MODE_POLL))) { + minWaitProperty = POLL_REFRESH_WAIT_MIN_MILLIS; + maxWaitProperty = POLL_REFRESH_WAIT_MAX_MILLIS; + + } + return Rand.randomLong(Config.getLongProperty(minWaitProperty), + Config.getLongProperty(maxWaitProperty)); + } + + /** + * Get events from queue and push to client. + */ + public void fetchEvents(Command aCommand) throws PushletException { + + String refreshURL = aCommand.httpReq.getRequestURI() + "?" + P_ID + "=" + session.getId() + "&" + P_EVENT + "=" + E_REFRESH; + + // This is the only thing required to support "poll" mode + if (mode.equals(MODE_POLL)) { + queueReadTimeoutMillis = 0; + refreshTimeoutMillis = Config.getLongProperty(POLL_REFRESH_TIMEOUT_MILLIS); + } + + // Required for fast bailout (tomcat) + aCommand.httpRsp.setBufferSize(128); + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + ClientAdapter clientAdapter = aCommand.getClientAdapter(); + Event responseEvent = aCommand.getResponseEvent(); + try { + clientAdapter.start(); + + // Send first event (usually hb-ack or listen-ack) + clientAdapter.push(responseEvent); + + // In pull/poll mode and when response is listen-ack or join-listen-ack, + // return and force refresh immediately + // such that the client recieves response immediately over this channel. + // This is usually when loading the browser app for the first time + if ((mode.equals(MODE_POLL) || mode.equals(MODE_PULL)) + && responseEvent.getEventType().endsWith(Protocol.E_LISTEN_ACK)) { + sendRefresh(clientAdapter, refreshURL); + + // We should come back later with refresh event... + return; + } + } catch (Throwable t) { + bailout(); + return; + } + + + Event[] events = null; + + // Main loop: as long as connected, get events and push to client + long eventSeqNr = 1; + while (isActive()) { + // Indicate we are still alive + lastAlive = Sys.now(); + + // Update session time to live + session.kick(); + + // Get next events; blocks until timeout or entire contents + // of event queue is returned. Note that "poll" mode + // will return immediately when queue is empty. + try { + // Put heartbeat in queue when starting to listen in stream mode + // This speeds up the return of *_LISTEN_ACK + if (mode.equals(MODE_STREAM) && eventSeqNr == 1) { + eventQueue.enQueue(new Event(E_HEARTBEAT)); + } + + events = eventQueue.deQueueAll(queueReadTimeoutMillis); + } catch (InterruptedException ie) { + warn("interrupted"); + bailout(); + } + + // Send heartbeat when no events received + if (events == null) { + events = new Event[1]; + events[0] = new Event(E_HEARTBEAT); + } + + // ASSERT: one or more events available + + // Send events to client using adapter + // debug("received event count=" + events.length); + for (int i = 0; i < events.length; i++) { + // Check for abort event + if (events[i].getEventType().equals(E_ABORT)) { + warn("Aborting Subscriber"); + bailout(); + } + + // Push next Event to client + try { + // Set sequence number + events[i].setField(P_SEQ, eventSeqNr++); + + // Push to client through client adapter + clientAdapter.push(events[i]); + } catch (Throwable t) { + bailout(); + return; + } + } + + // Force client refresh request in pull or poll modes + if (mode.equals(MODE_PULL) || mode.equals(MODE_POLL)) { + sendRefresh(clientAdapter, refreshURL); + + // Always leave loop in pull/poll mode + break; + } + } + } + + /** + * Determine if we should receive event. + */ + public Subscription match(Event event) { + Subscription[] subscriptions = getSubscriptions(); + for (int i = 0; i < subscriptions.length; i++) { + if (subscriptions[i].match(event)) { + return subscriptions[i]; + } + } + return null; + } + + /** + * Event from Dispatcher: enqueue it. + */ + public void onEvent(Event theEvent) { + if (!isActive()) { + return; + } + + // p("send: queue event: "+theEvent.getSubject()); + + // Check if we had any active continuation for at + // least 'timeOut' millisecs. If the client has left this + // instance there would be no way of knowing otherwise. + long now = Sys.now(); + if (now - lastAlive > refreshTimeoutMillis) { + warn("not alive for at least: " + refreshTimeoutMillis + "ms, leaving..."); + bailout(); + return; + } + + // Put event in queue; leave if queue full + try { + if (!eventQueue.enQueue(theEvent, queueWriteTimeoutMillis)) { + warn("queue full, bailing out..."); + bailout(); + } + + // ASSERTION : Event in queue. + // see fetchEvents() where Events are dequeued and pushed to the client. + } catch (InterruptedException ie) { + bailout(); + } + + } + + /** + * Send refresh command to pull/poll clients. + */ + protected void sendRefresh(ClientAdapter aClientAdapter, String aRefreshURL) { + Event refreshEvent = new Event(E_REFRESH); + + // Set wait time and url for refresh + refreshEvent.setField(P_WAIT, "" + getRefreshTimeMillis()); + refreshEvent.setField(P_URL, aRefreshURL); + + try { + // Push to client through client adapter + aClientAdapter.push(refreshEvent); + + // Stop this round until refresh event + aClientAdapter.stop(); + } catch (Throwable t) { + // Leave on any exception + bailout(); + } + } + + /** + * Info. + */ + protected void info(String s) { + session.info("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Subscriber] " + s); + } + + + public String toString() { + return session.toString(); + } +} + +/* + * $Log: Subscriber.java,v $ + * Revision 1.26 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.25 2007/11/10 15:53:15 justb + * put heartbeat in queue when start fetching events in stream-mode + * + * Revision 1.24 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.22 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.21 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.20 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + * Revision 1.19 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.18 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.17 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.16 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.15 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.14 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.13 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.12 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.11 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.10 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.7 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.6 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscription.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscription.java new file mode 100755 index 0000000000..c6f88bd597 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/Subscription.java @@ -0,0 +1,133 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.PushletException; + + +/** + * Represents single subject subscription + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscription.java,v 1.5 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscription implements ConfigDefs { + public static final int ID_SIZE = 5; + public static final String SUBJECT_SEPARATOR = ","; + private String id = Rand.randomName(ID_SIZE); + private String subject; + private String[] subjects; + + /** + * Optional label, a user supplied token. + */ + private String label; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscription() { + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject) throws PushletException { + return create(aSubject, null); + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @param aLabel the subject label (optional). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject, String aLabel) throws PushletException { + if (aSubject == null || aSubject.length() == 0) { + throw new IllegalArgumentException("Null or emtpy subject"); + } + + Subscription subscription; + try { + subscription = (Subscription) Config.getClass(SUBSCRIPTION_CLASS, "nl.justobjects.pushlet.core.Subscription").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + // Init + subscription.subject = aSubject; + + // We may subscribe to multiple subjects by separating + // them with SUBJECT_SEPARATOR, e.g. "/stocks/aex,/system/memory,.."). + subscription.subjects = aSubject.split(SUBJECT_SEPARATOR); + + subscription.label = aLabel; + return subscription; + } + + + public String getId() { + return id; + } + + public String getLabel() { + return label; + } + + public String getSubject() { + return subject; + } + + /** + * Determine if Event matches subscription. + */ + public boolean match(Event event) { + String eventSubject = event.getSubject(); + + // Silly case but check anyway + if (eventSubject == null || eventSubject.length() == 0) { + return false; + } + + // Test if one of the subjects matches + for (int i = 0; i < subjects.length; i++) { + if (eventSubject.startsWith(subjects[i])) { + return true; + } + } + + // No match + return false; + } +} + +/* + * $Log: Subscription.java,v $ + * Revision 1.5 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/16 15:23:10 justb + * multiple subject (, separated) support + * + * Revision 1.2 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.1 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/XMLAdapter.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/XMLAdapter.java new file mode 100755 index 0000000000..15d7096e59 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/core/XMLAdapter.java @@ -0,0 +1,137 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * ClientAdapter that sends Events as XML. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: XMLAdapter.java,v 1.7 2007/11/09 13:15:35 justb Exp $ + */ +class XMLAdapter implements ClientAdapter { + /** + * Header for strict XML + */ + // public static final String XML_HEAD = "\n"; + private String contentType = "text/plain;charset=UTF-8"; + private ServletOutputStream out = null; + private HttpServletResponse servletRsp; + private boolean strictXML; + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse) { + this(aServletResponse, false); + } + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse, boolean useStrictXML) { + servletRsp = aServletResponse; + + // Strict XML implies returning a complete XML document + strictXML = useStrictXML; + if (strictXML) { + contentType = "text/xml;charset=UTF-8"; + } + } + + public void start() throws IOException { + + // If content type is plain text + // then this is not a complete XML document, but rather + // a stream of XML documents where each document is + // an Event. In strict XML mode a complete document is returned. + servletRsp.setContentType(contentType); + + out = servletRsp.getOutputStream(); + + // Don't need this further + servletRsp = null; + + // Start XML document if strict XML mode + if (strictXML) { + out.print(""); + } + } + + /** + * Force client to refresh the request. + */ + public void push(Event anEvent) throws IOException { + debug("event=" + anEvent); + + // Send the event as XML to the client and flush. + out.print(anEvent.toXML(strictXML)); + out.flush(); + } + + /** + * No action. + */ + public void stop() throws IOException { + // Close XML document if strict XML mode + if (strictXML) { + out.print(""); + out.flush(); + } + } + + private void debug(String s) { + Log.debug("[XMLAdapter]" + s); + } +} + +/* + * $Log: XMLAdapter.java,v $ + * Revision 1.7 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.6 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.5 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.4 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.5 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.4 2003/08/13 14:00:00 justb + * some testing for applets; no real change + * + * Revision 1.3 2003/08/12 09:57:06 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/19 21:56:29 justb + * various fixes for applet clients + * + * Revision 1.1 2003/05/18 16:12:28 justb + * adding support for XML encoded Events + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/servlet/Pushlet.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/servlet/Pushlet.java new file mode 100755 index 0000000000..5488733c8d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/servlet/Pushlet.java @@ -0,0 +1,293 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.servlet; + +import nl.justobjects.pushlet.core.*; +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Servlets; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.Version; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Enumeration; + +/** + * Servlet runs a Subscriber per request. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Pushlet.java,v 1.23 2007/12/04 13:55:53 justb Exp $ + */ +public class Pushlet extends HttpServlet implements Protocol { + + public void init() throws ServletException { + try { + // Load configuration (from classpath or WEB-INF root path) + String webInfPath = getServletContext().getRealPath("/") + "/WEB-INF"; + Config.load(webInfPath); + + Log.init(); + + // Start + Log.info("init() Pushlet Webapp - version=" + Version.SOFTWARE_VERSION + " built=" + Version.BUILD_DATE); + + // Start session manager + SessionManager.getInstance().start(); + + // Start event Dispatcher + Dispatcher.getInstance().start(); + + + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + EventSourceManager.start(webInfPath); + } else { + Log.info("Not starting local event sources"); + } + } catch (Throwable t) { + throw new ServletException("Failed to initialize Pushlet framework " + t, t); + } + } + + public void destroy() { + Log.info("destroy(): Exit Pushlet webapp"); + + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + // Stop local event sources + EventSourceManager.stop(); + } else { + Log.info("No local event sources to stop"); + } + + // Should abort all subscribers + Dispatcher.getInstance().stop(); + + // Should stop all sessions + SessionManager.getInstance().stop(); + } + + /** + * Servlet GET request: handles event requests. + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + + try { + // Event parm identifies event type from the client + String eventType = Servlets.getParameter(request, P_EVENT); + + // Always must have an event type + if (eventType == null) { + Log.warn("Pushlet.doGet(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + // Create Event and set attributes from parameters + event = new Event(eventType); + for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) { + String nextAttribute = (String) e.nextElement(); + event.setField(nextAttribute, request.getParameter(nextAttribute)); + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doGet(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Servlet POST request: extracts event data from body. + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + try { + // Create Event by parsing XML from input stream. + event = EventParser.parse(new InputStreamReader(request.getInputStream())); + + // Always must have an event type + if (event.getEventType() == null) { + Log.warn("Pushlet.doPost(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doPost(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Generic request handler (GET+POST). + */ + protected void doRequest(Event anEvent, HttpServletRequest request, HttpServletResponse response) { + // Must have valid event type. + String eventType = anEvent.getEventType(); + try { + + // Get Session: either by creating (on Join eventType) + // or by id (any other eventType, since client is supposed to have joined). + Session session = null; + if (eventType.startsWith(Protocol.E_JOIN)) { + // Join request: create new subscriber + session = SessionManager.getInstance().createSession(anEvent); + + String userAgent = request.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + } else { + userAgent = "unknown"; + } + session.setUserAgent(userAgent); + + } else { + // Must be a request for existing Session + + // Get id + String id = anEvent.getField(P_ID); + + // We must have an id value + if (id == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No id specified"); + Log.warn("Pushlet: bad request, no id specified event=" + eventType); + return; + } + + // We have an id: get the session object + session = SessionManager.getInstance().getSession(id); + + // Check for invalid id + if (session == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid or expired id: " + id); + Log.warn("Pushlet: bad request, no session found id=" + id + " event=" + eventType); + return; + } + } + + // ASSERTION: we have a valid Session + + // Let Controller handle request further + // including exceptions + Command command = Command.create(session, anEvent, request, response); + session.getController().doCommand(command); + } catch (Throwable t) { + // Hmm we should never ever get here + Log.warn("Pushlet: Exception in doRequest() event=" + eventType, t); + t.printStackTrace(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + } +} + +/* + * $Log: Pushlet.java,v $ + * Revision 1.23 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.22 2007/11/24 10:29:36 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.21 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.20 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.19 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.18 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.17 2005/02/28 13:06:01 justb + * introduced join-listen protocol service + * + * Revision 1.16 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.15 2005/02/28 09:14:56 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.14 2005/02/25 15:13:04 justb + * session id generation more robust + * + * Revision 1.13 2005/02/21 17:19:21 justb + * move init()/destroy() to Pushlet servlet + * + * Revision 1.12 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.11 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.7 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.6 2004/09/26 21:39:44 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.5 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2004/08/13 23:36:06 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/13 13:26:57 justb + * moved all servlets to servlet package + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletApplet.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletApplet.java new file mode 100755 index 0000000000..23fcc44671 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletApplet.java @@ -0,0 +1,178 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.client.PushletClient; +import nl.justobjects.pushlet.client.PushletClientListener; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.applet.Applet; +import java.awt.*; + +/** + * Tester for applet clients; displays incoming events in text area. + * + * @version $Id: PushletApplet.java,v 1.16 2005/02/18 09:54:15 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public class PushletApplet extends Applet implements PushletClientListener, Protocol { + private TextArea textArea; + private String host = "localhost"; + private int port = 8080; + private String subject; + private PushletClient pushletClient; + private String VERSION = "15.feb.05 #5"; + private String PUSH_MODE = Protocol.MODE_PULL; + + /** One-time setup. */ + public void init() { + // Subject to subscribe to + subject = getParameter(P_SUBJECT); + + host = getDocumentBase().getHost(); + port = getDocumentBase().getPort(); + + // Hmm sometimes this value is -1...(Mozilla with Java 1.3.0 on Win) + if (port == -1) { + port = 80; + } + + setLayout(new GridLayout(1, 1)); + textArea = new TextArea(15, 40); + textArea.setForeground(Color.yellow); + textArea.setBackground(Color.gray); + textArea.setEditable(false); + add(textArea); + p("PushletApplet - " + VERSION); + } + + public void start() { + dbg("start()"); + bailout(); + + try { + pushletClient = new PushletClient(host, port); + p("Created PushletClient"); + + pushletClient.join(); + p("Joined server"); + + pushletClient.listen(this, PUSH_MODE); + p("Listening in mode=" + PUSH_MODE); + + pushletClient.subscribe(subject); + p("Subscribed to=" + subject); + } catch (PushletException pe) { + p("Error exception=" + pe); + bailout(); + } + } + + public void stop() { + dbg("stop()"); + bailout(); + } + + /** Abort event from server. */ + public void onAbort(Event theEvent) { + p(theEvent.toXML()); + bailout(); + } + + /** Data event from server. */ + public void onData(Event theEvent) { + p(theEvent.toXML()); + } + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent) { + p(theEvent.toXML()); + } + + /** Error occurred. */ + public void onError(String message) { + p(message); + bailout(); + } + + private void bailout() { + if (pushletClient != null) { + p("Stopping PushletClient"); + try { + pushletClient.leave(); + } catch (PushletException ignore) { + p("Error during leave pe=" + ignore); + + } + pushletClient = null; + } + } + + /** Generic print. */ + private void p(String s) { + dbg("event: " + s); + synchronized (textArea) { + textArea.append(s + "\n"); + } + } + + /** Generic print. */ + private void dbg(String s) { + System.out.println("[PushletApplet] " + s); + } +} + +/* + * $Log: PushletApplet.java,v $ + * Revision 1.16 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.15 2005/02/15 15:46:36 justb + * client API improves + * + * Revision 1.14 2005/02/15 13:28:33 justb + * use new PushletClient lib + * + * Revision 1.13 2004/10/25 21:22:26 justb + * *** empty log message *** + * + * Revision 1.12 2004/10/24 13:52:52 justb + * small fixes in client lib + * + * Revision 1.11 2004/10/24 12:58:19 justb + * revised client and test classes for new protocol + * + * Revision 1.10 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.9 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.8 2003/08/17 21:06:37 justb + * version info change + * + * Revision 1.7 2003/08/15 08:37:41 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.6 2003/08/14 21:43:10 justb + * improved Java client lifecycle; notably stopping listener thread + * + * Revision 1.5 2003/08/13 14:00:00 justb + * some testing for applets; no real change + * + * Revision 1.4 2003/05/19 22:53:33 justb + * more fixes for applets + * + * Revision 1.3 2003/05/19 21:56:29 justb + * various fixes for applet clients + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:33 justb + * import to sourceforge + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletPingApplication.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletPingApplication.java new file mode 100755 index 0000000000..72f3dff0d9 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/PushletPingApplication.java @@ -0,0 +1,179 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.client.PushletClient; +import nl.justobjects.pushlet.client.PushletClientListener; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.util.HashMap; +import java.util.Map; + +/** + * Tester to demonstrate Pushlet use in Java applications. + * + * This program does two things: + * (1) it subscribes to the subject "test/ping" + * (2) it publishes an Event with subject "/test/ping" every few seconds. + * + * @version $Id: PushletPingApplication.java,v 1.15 2005/02/21 16:59:17 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public class PushletPingApplication extends Thread implements PushletClientListener, Protocol { + private PushletClient pushletClient; + private String host; + private int port; + private static final String SUBJECT = "/test/ping"; + private static final long PUBLISH_INTERVAL_MILLIS = 3000; + + public PushletPingApplication(String aHost, int aPort) { + host = aHost; + port = aPort; + } + + public void run() { + // Create and start a Pushlet client; we receive callbacks + // through onHeartbeat() and onData(). + try { + pushletClient = new PushletClient(host, port); + pushletClient.setDebug(true); + pushletClient.join(); + pushletClient.listen(this, Protocol.MODE_STREAM); + + // Test subscribe/unsubscribe + String subscriptionId = pushletClient.subscribe(SUBJECT); + pushletClient.unsubscribe(subscriptionId); + + // The real subscribe + pushletClient.subscribe(SUBJECT); + p("pushletClient started"); + } catch (PushletException pe) { + p("Error in setting up pushlet session pe=" + pe); + return; + } + + // Publish an event to the server every N seconds. + Map eventData = new HashMap(2); + int seqNr = 1; + while (true) { + try { + // Create event data + eventData.put("seqNr", "" + seqNr++); + eventData.put("time", "" + System.currentTimeMillis()); + + // POST event to pushlet server + pushletClient.publish(SUBJECT, eventData); + + p("published ping # " + (seqNr - 1) + " - sleeping..."); + Thread.sleep(PUBLISH_INTERVAL_MILLIS); + } catch (Exception e) { + p("Postlet exception: " + e); + System.exit(-1); + } + } + } + + /** Error occurred. */ + public void onError(String message) { + p(message); + } + + /** Abort event from server. */ + public void onAbort(Event theEvent) { + p("onAbort received: " + theEvent); + } + + /** Data event from server. */ + public void onData(Event theEvent) { + // Calculate round trip delay + long then = Long.parseLong(theEvent.getField("time")); + long delay = System.currentTimeMillis() - then; + p("onData: ping #" + theEvent.getField("seqNr") + " in " + delay + " ms"); + } + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent) { + p("onHeartbeat received: " + theEvent); + } + + /** Generic print. */ + public void p(String s) { + System.out.println("[PushletPing] " + s); + } + + /** Main program. */ + public static void main(String args[]) { + for (int i = 0; i < 1; i++) { + if (args.length == 0) { + new PushletPingApplication("localhost", 8080).start(); + } else { + // Supply a host and port + new PushletPingApplication(args[0], Integer.parseInt(args[1])).start(); + } + } + + } +} + + +/* + * $Log: PushletPingApplication.java,v $ + * Revision 1.15 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.14 2005/02/21 11:50:48 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.13 2005/02/20 13:05:33 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.12 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.11 2005/02/15 15:46:37 justb + * client API improves + * + * Revision 1.10 2005/02/15 13:28:08 justb + * use new protocol lib and publish with PushletClient + * + * Revision 1.9 2004/10/24 13:52:52 justb + * small fixes in client lib + * + * Revision 1.8 2004/10/24 12:58:19 justb + * revised client and test classes for new protocol + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.5 2004/03/10 14:53:10 justb + * new + * + * Revision 1.4 2003/08/17 20:30:20 justb + * cosmetic changes + * + * Revision 1.3 2003/08/15 08:37:41 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:33 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:19 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:02 justb + * first import into SF + * + * Revision 1.3 2000/08/31 12:49:50 just + * added CVS comment tags for log and copyright + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/SimpleListener.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/SimpleListener.java new file mode 100755 index 0000000000..b42c38818e --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/SimpleListener.java @@ -0,0 +1,98 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.client.PushletClient; +import nl.justobjects.pushlet.client.PushletClientListener; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.util.HashMap; +import java.util.Map; + +/** + * Demonstrates join-listen service. + * + * The pushlet protocol supports the "join-listen" service + * which allows stateless (e.g. RESTful) clients to join/subscribe/listen + * using a single HTTP request. + * + * @version $Id: SimpleListener.java,v 1.3 2005/03/14 14:07:23 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public class SimpleListener implements PushletClientListener, Protocol { + private static String SUBJECT = "/temperature"; + private static final String MODE = MODE_STREAM; + + public SimpleListener(String aHost, int aPort) { + // Create and start a Pushlet client; we receive callbacks + // through onHeartbeat() and onData(). + try { + PushletClient pushletClient = new PushletClient(aHost, aPort); + pushletClient.setDebug(false); + pushletClient.join(); + pushletClient.listen(this, MODE, SUBJECT); + p("pushletClient started"); + } catch (PushletException pe) { + p("Error in setting up pushlet session pe=" + pe); + } + } + + /** Error occurred. */ + public void onError(String message) { + p(message); + } + + /** Abort event from server. */ + public void onAbort(Event theEvent) { + p("onAbort received: " + theEvent); + } + + /** Data event from server. */ + public void onData(Event theEvent) { + // Calculate round trip delay + System.out.println(theEvent.toXML()); + } + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent) { + p("onHeartbeat received: " + theEvent); + } + + /** Generic print. */ + public void p(String s) { + System.out.println("[SimpleListener] " + s); + } + + /** Main program. */ + public static void main(String args[]) { + if (args.length == 0) { + new SimpleListener("localhost", 8080); + } + else if (args.length == 1) { + SUBJECT = args[0]; + new SimpleListener("localhost", 8080); + } else { + SUBJECT = args[0]; + // args[1] and [2] should be host and port + new SimpleListener(args[1], Integer.parseInt(args[2])); + } + } +} + + +/* + * $Log: SimpleListener.java,v $ + * Revision 1.3 2005/03/14 14:07:23 justb + * addded subject arg + * + * Revision 1.2 2005/02/28 21:21:32 justb + * no chg + * + * Revision 1.1 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/StressTester.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/StressTester.java new file mode 100755 index 0000000000..616e06fe09 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/StressTester.java @@ -0,0 +1,192 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.client.PushletClient; +import nl.justobjects.pushlet.client.PushletClientListener; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; + +import java.util.HashMap; +import java.util.Map; + +/** + * Tester to demonstrate Pushlet use in Java applications. + *

    + * This program does two things: + * (1) it subscribes to the subject "test/ping" + * (2) it publishes an Event with subject "/test/ping" every few seconds. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: StressTester.java,v 1.2 2007/11/09 13:16:57 justb Exp $ + */ +public class StressTester implements Protocol { + static private String host = "localhost"; + static private int port = 8080; + static private int TESTER_COUNT = 10; + private static final String SUBJECT = "/test/ping"; + private static final long MIN_PUBLISH_INTERVAL_MILLIS = 200; + private static final long MAX_PUBLISH_INTERVAL_MILLIS = 1000; + private static final long MIN_SUBSCRIBER_INTERVAL_MILLIS = 500; + private static final long MAX_SUBSCRIBER_INTERVAL_MILLIS = 1000; + + public StressTester() { + } + + public void run() { + new EventPublisher().start(); + new EventSubscriber().start(); + } + + /** + * Generic print. + */ + public void err(String s) { + System.out.println("[StressTester] ERROR" + s); + } + + /** + * Generic print. + */ + public void p(String s) { + System.out.println("[StressTester] " + s); + } + + private class EventSubscriber extends Thread implements PushletClientListener { + private PushletClient pushletClient; + + public void run() { + while (true) { + // Create and start a Pushlet client; we receive callbacks + // through onHeartbeat() and onData(). + try { + pushletClient = new PushletClient(host, port); + // pushletClient.setDebug(true); + pushletClient.join(); + pushletClient.listen(this, Protocol.MODE_STREAM); + //p("listening"); + // Test subscribe/unsubscribe + String subscriptionId = pushletClient.subscribe(SUBJECT); + pushletClient.unsubscribe(subscriptionId); + + // The real subscribe + subscriptionId = pushletClient.subscribe(SUBJECT); + //p("sleeping"); + sleepRandom(); + //p("leaving"); + pushletClient.unsubscribe(subscriptionId); + pushletClient.leave(); + + } catch (Throwable t) { + err("Error in EventSubscriber t=" + t); + return; + } + } + } + + /** + * Error occurred. + */ + public void onError(String message) { + // p(message); + } + + /** + * Abort event from server. + */ + public void onAbort(Event theEvent) { + //p("onAbort received: " + theEvent); + } + + /** + * Data event from server. + */ + public void onData(Event theEvent) { + // Calculate round trip delay + long then = Long.parseLong(theEvent.getField("time")); + long delay = System.currentTimeMillis() - then; + //p("onData: ping #" + theEvent.getField("seqNr") + " in " + delay + " ms"); + } + + /** + * Heartbeat event from server. + */ + public void onHeartbeat(Event theEvent) { + //p("onHeartbeat received: " + theEvent); + } + + private void sleepRandom() throws InterruptedException { + Thread.sleep(Rand.randomLong(MIN_SUBSCRIBER_INTERVAL_MILLIS, MAX_SUBSCRIBER_INTERVAL_MILLIS)); + } + } + + private class EventPublisher extends Thread { + private PushletClient pushletClient; + + public void run() { + // Create and start a Pushlet client; we receive callbacks + // through onHeartbeat() and onData(). + try { + pushletClient = new PushletClient(host, port); + pushletClient.join(); + + // p("pushletClient started"); + } catch (PushletException pe) { + err("Error in EventPublisher pe=" + pe); + return; + } + + // Publish an event to the server every N seconds. + Map eventData = new HashMap(2); + int seqNr = 1; + while (true) { + try { + // Create event data + eventData.put("seqNr", "" + seqNr++); + eventData.put("time", "" + System.currentTimeMillis()); + + // POST event to pushlet server + pushletClient.publish(SUBJECT, eventData); + + Thread.sleep(Rand.randomLong(MIN_PUBLISH_INTERVAL_MILLIS, MAX_PUBLISH_INTERVAL_MILLIS)); + } catch (Exception e) { + p("EventPublisher exception: " + e); + return; + } + } + } + + } + + /** + * Main program. + */ + public static void main(String args[]) { + if (args.length > 0) { + TESTER_COUNT = Integer.parseInt(args[0]); + } + if (args.length == 3) { + host = args[1]; + port = Integer.parseInt(args[2]); + } + + for (int i = 0; i < TESTER_COUNT; i++) { + new StressTester().run(); + } + + } +} + +/* + * $Log: StressTester.java,v $ + * Revision 1.2 2007/11/09 13:16:57 justb + * use Rand from util package (and and Rand.java to pushlet client jar + * + * Revision 1.1 2005/02/28 17:16:58 justb + * simple stress tester + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPullSources.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPullSources.java new file mode 100755 index 0000000000..319c95550d --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPullSources.java @@ -0,0 +1,273 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventPullSource; +import nl.justobjects.pushlet.core.SessionManager; +import nl.justobjects.pushlet.util.Rand; + + +/** + * Event sources for testing. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: TestEventPullSources.java,v 1.10 2007/11/09 13:16:57 justb Exp $ + */ +public class TestEventPullSources { + + /** + * Produces a fake temparature event. + */ + static public class TemperatureEventPullSource extends EventPullSource { + String[] cities = {"amsterdam", null, "rotterdam", null, + "leeuwarden", null, "twente", null, "limburg", null}; + + public long getSleepTime() { + return Rand.randomLong(3000, 5000); + } + + public Event pullEvent() { + int cityNumber = Rand.randomInt(0, (cities.length) / 2 - 1); + int nextCityIndex = 2 * cityNumber; + + Event event = Event.createDataEvent("/temperature"); + + event.setField("number", "" + cityNumber); + event.setField("city", cities[nextCityIndex]); + if (cities[nextCityIndex + 1] == null) { + cities[nextCityIndex + 1] = "" + Rand.randomInt(5, 10); + } + int currentCityValue = new Integer(cities[nextCityIndex + 1]).intValue(); + int newCityValue = currentCityValue + Rand.randomInt(-2, 2); + + event.setField("value", "" + newCityValue); + return event; + } + } + + /** + * Produces a ping event. + */ + static public class PingEventPullSource extends EventPullSource { + public long getSleepTime() { + return 3000; + } + + public Event pullEvent() { + + return Event.createDataEvent("/pushlet/ping"); + } + } + + /** + * Produces an event related to the JVM status. + */ + static public class SystemStatusEventPullSource extends EventPullSource { + Runtime runtime = Runtime.getRuntime(); + + public long getSleepTime() { + return 4000; + } + + public Event pullEvent() { + Event event = Event.createDataEvent("/system/jvm"); + event.setField("totalMemory", "" + runtime.totalMemory()); + event.setField("freeMemory", "" + runtime.freeMemory()); + event.setField("maxMemory", "" + runtime.maxMemory()); + int activeCount = Thread.activeCount(); + event.setField("threads", "" + activeCount); + + return event; + } + } + + /** + * Produces an event related to the Dispatcher.getInstance(). status. + */ + static public class PushletStatusEventPullSource extends EventPullSource { + + public long getSleepTime() { + return 5000; + } + + public Event pullEvent() { + Event event = Event.createDataEvent("/system/pushlet"); + // p(Dispatcher.getStatus()); + event.setField("publisher", "" + SessionManager.getInstance().getStatus()); + return event; + } + } + + + /** + * Produces events simulating stocks from the AEX. + */ + static public class AEXStocksEventPullSource extends EventPullSource { + + String[] stocks = {"abn amro", "26", + "aegon", "38", + "ahold", "34", + "akzo nobel", "51", + "asm lith h", "26", + "corus plc", "2", + "dsm", "40", + "elsevier", "14", + "fortis (nl)", "32", + "getronics", "6", + "gucci", "94", + "hagemeyer", "25", + "heineken", "61", + "ing c", "78", + "klm", "66", + "kon olie", "66", + "kpn", "13", + "numico c", "44", + "philips, kon", "38", + "tnt", "26", + "unilever c", "62", + "vendex kbb", "16", + "vnu", "49", + "wolt-kluw c", "25"}; + + public long getSleepTime() { + return Rand.randomLong(2000, 4000); + } + + public Event pullEvent() { + Event event = Event.createDataEvent("/stocks/aex"); + int stockNumber = Rand.randomInt(0, (stocks.length) / 2 - 1); + int nextStockIndex = 2 * stockNumber; + + event.setField("number", "" + stockNumber); + event.setField("name", stocks[nextStockIndex]); + if (stocks[nextStockIndex + 1] == null) { + stocks[nextStockIndex + 1] = "" + Rand.randomInt(50, 150); + } + int currentStockValue = new Integer(stocks[nextStockIndex + 1]).intValue(); + int newStockValue = currentStockValue + Rand.randomInt(-2, 2); + + event.setField("rate", "" + newStockValue + "." + Rand.randomInt(0, 99)); + return event; + } + + } + + /** + * Produces an URL event for automatic webpresentation. + */ + static public class WebPresentationEventPullSource extends EventPullSource { + String slideRootDir = "http://www.justobjects.org/cowcatcher/browse/j2ee/slides/"; + String[] slideURLs = { + "ejb/j2ee/ejbover/slide.0.0.html", + "ejb/j2ee/ejbover/slide.0.1.html", + "ejb/j2ee/ejbover/slide.0.2.html", + "ejb/j2ee/ejbover/slide.0.3.html", + "ejb/j2ee/ejbover/slide.0.4.html" + }; + + int nextSlideNumber = 0; + + public long getSleepTime() { + return 5000; + } + + public Event pullEvent() { + Event event = Event.createDataEvent("/webpres/auto"); + event.setField("url", slideRootDir + slideURLs[nextSlideNumber++]); + if (nextSlideNumber == slideURLs.length) { + nextSlideNumber = 0; + } + // Log.debug("Sending next slide url=" + event.getField("url")); + return event; + } + } + + /** + * Produces an event related to the Dispatcher.getInstance(). status. + */ + static public class TestEventPullSource extends EventPullSource { + private int number = 0; + + public long getSleepTime() { + return 2000; + } + + public Event pullEvent() { + Event event = Event.createDataEvent("/system/test"); + // p(Dispatcher.getInstance()..getStatus()); + event.setField("nr", "" + (number++)); + event.setField("time", "" + System.currentTimeMillis()); + return event; + } + + } + + /** + * Util: stderr print method. + */ + public static void e(String s) { + System.out.println(s); + } + + /** + * Util: stdout print method. + */ + public static void p(String s) { + // System.out.println(s); + } +} + +/* + * $Log: TestEventPullSources.java,v $ + * Revision 1.10 2007/11/09 13:16:57 justb + * use Rand from util package (and and Rand.java to pushlet client jar + * + * Revision 1.9 2005/02/28 09:14:56 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.8 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.7 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.6 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher.getInstance(). and single Subscriber class + * + * Revision 1.5 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.4 2003/12/03 21:16:58 justb + * *** empty log message *** + * + * Revision 1.3 2003/08/15 08:37:41 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:33 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:19 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:01 justb + * first import into SF + * + * Revision 1.6 2002/07/29 10:17:22 just + * no message + * + * Revision 1.5 2001/02/18 23:45:13 just + * fixes for AEX + * + * Revision 1.4 2000/10/30 14:16:09 just + * no message + * + * Revision 1.3 2000/08/31 12:49:50 just + * added CVS comment tags for log and copyright + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPushSources.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPushSources.java new file mode 100755 index 0000000000..2130dd82a8 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/test/TestEventPushSources.java @@ -0,0 +1,336 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.test; + +import nl.justobjects.pushlet.core.Dispatcher; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventSource; +import nl.justobjects.pushlet.util.Rand; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.StringTokenizer; +import java.util.Vector; + +/** + * Event sources that push events (for testing). + * + * @author Just van den Broecke - Just Objects © + * @version $Id: TestEventPushSources.java,v 1.10 2007/11/09 13:16:57 justb Exp $ + */ +public class TestEventPushSources { + + static public class AEXStocksEventPushSourceABN { + String pageURL = "http://ri2.rois.com/E36msPtnZC0e15CVb4KT97JAGfGSfCcrvv6*FcyZIoNyh/CTIB/RI2APISNAP?RIC=0%23.AEX&FORMAT=XML"; + // This could be further expanded: getting the Reuters AEX stocks + // as XML from ABN with this URL, but we may get into legal problems... + } + + /** + * Produces events from REAL stocks from the AEX. + */ + static public class AEXStocksEventPushSource implements EventSource, Runnable { + /** + * Here we get our stocks from. + */ + String pageURL = "http://www.debeurs.nl/koersen/aex.asp"; + Thread thread = null; + volatile boolean active = false; + + // Since Baan has been thrown out... + public final static int NR_OF_STOCKS = 24; + + public final static String EMPTY = "wait..."; + private int restarts = 1; + + class Stock { + public String name = EMPTY; + public String rate = EMPTY; + volatile public boolean modified = false; + } + + Vector stocksCache = new Vector(NR_OF_STOCKS); + + public AEXStocksEventPushSource() { + for (int i = 0; i < NR_OF_STOCKS; i++) { + stocksCache.addElement(new Stock()); + } + // updateCache(); + } + + /** + * Activate the event source. + */ + synchronized public void activate() { + e("activating..."); + // Stop a possibly running thread + stopThread(); + + // Start new thread and + thread = new Thread(this, "AEXStocksPublisher-" + (restarts++)); + active = true; + thread.start(); + e("activated"); + } + + /** + * Deactivate the event source. + */ + synchronized public void passivate() { + e("passivating..."); + active = false; + stopThread(); + + // Mark the cache modified so we'll send the contents + // on the next activation. + for (int i = 0; i < NR_OF_STOCKS; i++) { + ((Stock) stocksCache.elementAt(i)).modified = true; + } + + e("passivated"); + } + + + /** + * Deactivate the event source. + */ + synchronized public void stop() { + } + + public void run() { + // Publish cache content (if any) first. + publishStocks(); + + int count = 5; // enforce update first + while (active) { + + // Only do work if active + // Update cache every 10 secs. + if (count == 5) { + updateCache(); + count = 0; + } + count++; + + // Do updates for changed stock rates + sendUpdates(); + + // If we were interrupted just return. + if (thread == null || thread.isInterrupted()) { + break; + } + + // Sleep 2 secs before sending next updates + try { + thread.sleep(2000); + } catch (InterruptedException ie) { + break; + } + } + + // Loop terminated: reset vars + thread = null; + active = false; + } + + private String getStocksLine() { + BufferedReader br = null; + InputStream is = null; + String nextLine = ""; + + // Read line from server + try { + is = new URL(pageURL).openStream(); + br = new BufferedReader(new InputStreamReader(is)); + boolean foundLine = false; + while (!foundLine) { + nextLine = br.readLine(); + if (nextLine == null) { + return ""; + } + foundLine = (nextLine.indexOf("details.asp?iid=14053&parent=aex") != -1); + } + } catch (Exception e) { + e("could not open or read URL pageURL=" + pageURL + " ex=" + e); + return ""; + } finally { + try { + if (is != null) is.close(); + } catch (IOException ignore) { + } + } + return nextLine; + } + + private void publishStocks() { + // Publish only modified stocks from the cache + for (int i = 0; i < NR_OF_STOCKS; i++) { + Stock nextStock = (Stock) stocksCache.elementAt(i); + + // Publish modified stocks + if (nextStock.modified) { + publishStock(i, nextStock.name, nextStock.rate); + nextStock.modified = false; + try { + Thread.sleep(400); + } catch (InterruptedException ie) { + return; + } + } + } + } + + private void publishStock(int index, String name, String rate) { + Event event = Event.createDataEvent("/stocks/aex"); + event.setField("number", index + ""); + event.setField("name", name); + event.setField("rate", rate); + p("publish: nr=" + index + " name=" + name + " rate=" + rate); + Dispatcher.getInstance().multicast(event); + } + + private void sendUpdates() { + p("sending updates"); + // In any case send a random stock value by + // making it modified, just to see something moving... + int randomIndex = Rand.randomInt(0, NR_OF_STOCKS - 1); + Stock randomStock = (Stock) stocksCache.elementAt(randomIndex); + randomStock.modified = true; + + publishStocks(); + } + + private void stopThread() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + + private void updateCache() { + p("updating Cache"); + + // Get the line with all stocks from HTML page + String stocksLine = getStocksLine(); + if ("".equals(stocksLine)) { + e("updateCache: stocksLine == null"); + return; + } + + // Parse the stocksline and put in cache. + // Beware: this is the messy part!! + // We assume that stock/names and rates are located at + // regular positions in the line. + String delim = "<>"; + StringTokenizer st = new StringTokenizer(stocksLine, delim); + String nextToken = ""; + int count = 0; + String nextStock = ""; + String nextQuote = ""; + String currentQuote = null; + int index = -1; + while (st.hasMoreTokens()) { + nextToken = st.nextToken(); + count++; + // The with the stock name + if ((count - 5) % 57 == 0) { + p("c=" + count + " s=" + nextToken); + nextStock = nextToken; + } + + // The with the stock rate + if ((count - 10) % 57 == 0) { + nextQuote = nextToken; + index++; + p("c=" + count + " val=" + nextQuote); + Stock currentStock = (Stock) stocksCache.elementAt(index); + + // Only update new or modified stocks + if (EMPTY.equals(currentStock.rate) || !currentStock.rate.equals(nextQuote)) { + p("modified: " + nextStock); + currentStock.name = nextStock; + currentStock.rate = nextQuote; + currentStock.modified = true; + } + } + } + } + } + + + /** + * Util: stderr print method. + */ + public static void e(String s) { + System.out.println("AEXStocksEventPushSource: " + s); + } + + /** + * Util: stdout print method. + */ + public static void p(String s) { + // System.out.println(s); + } + + + public static void main(String[] args) { + // new TestEventPushSources$AEXStocksEventPushSource(); + } +} + +/* + * $Log: TestEventPushSources.java,v $ + * Revision 1.10 2007/11/09 13:16:57 justb + * use Rand from util package (and and Rand.java to pushlet client jar + * + * Revision 1.9 2005/02/28 09:14:56 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.8 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.7 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.6 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.5 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.4 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.3 2003/08/15 08:37:41 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:33 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:20 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:02 justb + * first import into SF + * + * Revision 1.6 2001/02/18 23:45:13 just + * fixes for AEX + * + * Revision 1.5 2000/10/30 14:16:09 just + * no message + * + * Revision 1.4 2000/09/24 21:02:43 just + * chnages due to changed webpage in debeurs.nl + * + * Revision 1.3 2000/08/31 12:49:50 just + * added CVS comment tags for log and copyright + * + * + */ diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/DefaultLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/DefaultLogger.java new file mode 100755 index 0000000000..bec2d94f34 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/DefaultLogger.java @@ -0,0 +1,164 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Default logger. + *

    + * Logs to stdout. Override this class by setting "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: DefaultLogger.java,v 1.2 2007/12/07 12:57:40 justb Exp $ + */ +public class DefaultLogger implements PushletLogger { + + + /** + * Level intialized with default. + */ + private int level = LOG_LEVEL_INFO; + + public DefaultLogger() { + } + + public void init() { + + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage) { + if (level < LOG_LEVEL_TRACE) { + return; + } + print("TRACE", aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage) { + if (level < LOG_LEVEL_DEBUG) { + return; + } + print("DEBUG", aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage) { + if (level < LOG_LEVEL_INFO) { + return; + } + print("INFO", aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage) { + if (level < LOG_LEVEL_WARN) { + return; + } + print("WARN", aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable) { + warn(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage) { + if (level < LOG_LEVEL_ERROR) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable) { + error(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage) { + if (level < LOG_LEVEL_FATAL) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable) { + fatal(aMessage + " exception=" + aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + public void setLevel(int aLevel) { + level = aLevel; + } + + /** + * Print message. + * + * @param aTag the log type + * @param aMessage the message to be logged + */ + private void print(String aTag, String aMessage) { + // SImple std out e.g. to catalina.out in Tomcat + System.out.println("Pushlet[" + aTag + "] " + aMessage); + } + +} + +/* +* $Log: DefaultLogger.java,v $ +* Revision 1.2 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.1 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log.java new file mode 100755 index 0000000000..3ce40153e7 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log.java @@ -0,0 +1,178 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.Config; +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logging wrapper. + *

    + * Provides a hook to direct logging to your own logging library. Override the DefaultLogger class by setting + * "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: Log.java,v 1.5 2007/12/07 12:57:40 justb Exp $ + */ +public class Log implements ConfigDefs { + /** + * Init with default to have at least some logging. + */ + private static PushletLogger logger = new DefaultLogger(); + + /** + * General purpose initialization. + */ + static public void init() { + try { + logger = (PushletLogger) Config.getClass(LOGGER_CLASS, "nl.justobjects.pushlet.util.DefaultLogger").newInstance(); + } catch (Throwable t) { + // Hmmm cannot log this since we don't have a log... + System.out.println("Cannot instantiate Logger from config ex=" + t); + return; + } + + logger.init(); + + // Set log level + logger.setLevel(Config.getIntProperty(Config.LOG_LEVEL)); + + logger.info("Logging intialized logger class=" + logger.getClass()); + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + static public void trace(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + static public void debug(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + static public void info(String aMessage) { + logger.info(aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + static public void warn(String aMessage) { + logger.warn(aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + static public void error(String aMessage) { + logger.error(aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + static public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + static public void setLevel(int aLevel) { + logger.setLevel(aLevel); + } +} + +/* +* $Log: Log.java,v $ +* Revision 1.5 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.4 2007/11/23 21:29:43 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.3 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.2 2005/02/21 11:15:59 justb +* support log levels +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.7 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.6 2004/08/12 13:16:08 justb +* make debug flag false +* +* Revision 1.5 2004/03/10 14:01:55 justb +* formatting and *Subscriber refactoring +* +* Revision 1.4 2003/08/15 09:54:46 justb +* fix javadoc warnings +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* Revision 1.2 2003/08/12 09:42:47 justb +* enhancements +* +* Revision 1.1 2003/08/12 08:46:00 justb +* cvs comment tags added +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log4jLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log4jLogger.java new file mode 100755 index 0000000000..d7ee1df832 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Log4jLogger.java @@ -0,0 +1,134 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +/** + * Logger to use Log4j for logging. + *

    + * Logs using Log4j. + * This class will require a log4j library in the classpath of the Pushlet. + * + * @author Uli Romahn + * @version $Id: Log4jLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public class Log4jLogger implements PushletLogger { + + /** + * Level intialized with default. + */ + private Logger logger = LogManager.getLogger("pushlet"); + + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#init() + */ + public void init() { + setLevel(LOG_LEVEL_INFO); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#debug(java.lang.String) + */ + public void debug(String aMessage) { + if (!logger.isDebugEnabled()) { + return; + } + logger.debug(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String) + */ + public void error(String aMessage) { + logger.error(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String, java.lang.Throwable) + */ + public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String) + */ + public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String, java.lang.Throwable) + */ + public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#info(java.lang.String) + */ + public void info(String aMessage) { + if (!logger.isInfoEnabled()) { + return; + } + logger.info(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#trace(java.lang.String) + */ + public void trace(String aMessage) { + logger.trace(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String) + */ + public void warn(String aMessage) { + logger.warn(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String, java.lang.Throwable) + */ + public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#setLevel(int) + */ + public void setLevel(int aLevel) { + if (aLevel < LOG_LEVEL_FATAL) { + logger.setLevel(Level.OFF); + } else { + switch (aLevel) { + case LOG_LEVEL_FATAL: + logger.setLevel(Level.FATAL); + break; + case LOG_LEVEL_ERROR: + logger.setLevel(Level.ERROR); + break; + case LOG_LEVEL_WARN: + logger.setLevel(Level.WARN); + break; + case LOG_LEVEL_INFO: + logger.setLevel(Level.INFO); + break; + case LOG_LEVEL_DEBUG: + logger.setLevel(Level.DEBUG); + break; + case LOG_LEVEL_TRACE: + logger.setLevel(Level.TRACE); + break; + default: + logger.setLevel(Level.INFO); + } + } + } +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletException.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletException.java new file mode 100755 index 0000000000..09ecd3176c --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletException.java @@ -0,0 +1,41 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Generic exception wrapper. + * + * @author Just van den Broecke + * @version $Id: PushletException.java,v 1.1 2005/02/15 15:14:34 justb Exp $ + */ +public class PushletException extends Exception { + + private PushletException() { + } + + public PushletException(String aMessage, Throwable t) { + super(aMessage + "\n embedded exception=" + t.toString()); + } + + public PushletException(String aMessage) { + super(aMessage); + } + + public PushletException(Throwable t) { + this("PushletException: ", t); + } + + public String toString() { + return "PushletException: " + getMessage(); + } +} + +/* + * $Log: PushletException.java,v $ + * Revision 1.1 2005/02/15 15:14:34 justb + * *** empty log message *** + * + + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletLogger.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletLogger.java new file mode 100755 index 0000000000..c3853369ba --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/PushletLogger.java @@ -0,0 +1,94 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logger interface to allow different logging providers. + *

    + * + * @author Ulrich Romahn + * @version $Id: PushletLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public interface PushletLogger extends ConfigDefs { + + /** + * Method allowing to initialize our logger + */ + public void init(); + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage); + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage); + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage); + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage); + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable); + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage); + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable); + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage); + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable); + + /** + * Set log level + * + * @param aLevel a valid Level from ConfigDefs + */ + public void setLevel(int aLevel); +} diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Rand.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Rand.java new file mode 100755 index 0000000000..041970941f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Rand.java @@ -0,0 +1,147 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. +package nl.justobjects.pushlet.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.Random; + +/** + * Randomizing routines. + * + * @author Just van den Broecke + * @version $Id: Rand.java,v 1.4 2007/12/07 12:57:40 justb Exp $ + */ +public class Rand { + private static char CHARS[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'v', 'w', 'y', 'z'}; + private static char NON_VOWELS[] = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'z'}; + private static char VOWELS[] = {'a', 'e', 'i', 'o', 'u', 'y'}; + private static Random random = new Random(); + + public static char randomChar() { + return CHARS[randomInt(0, CHARS.length - 1)]; + } + + public static char randomVowel() { + return VOWELS[randomInt(0, VOWELS.length - 1)]; + } + + public static char randomNonVowel() { + return NON_VOWELS[randomInt(0, NON_VOWELS.length - 1)]; + } + + public static File randomTempDir() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oasetest" + File.separator + randomString(12)); + file.mkdirs(); + file.deleteOnExit(); + return file; + } + + public static File randomTempFile() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oase-" + randomString(6)); + file.createNewFile(); + file.deleteOnExit(); + return file; + } + + public static File randomBinaryFile(int aSize) throws Exception { + File file = randomTempFile(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(randomBytes(aSize)); + fos.close(); + return file; + } + + public static File randomTextFile(int aSize) throws Exception { + File file = randomTempFile(); + PrintWriter pw = new PrintWriter(new FileOutputStream(file)); + pw.write(randomString(aSize)); + pw.close(); + return file; + } + + public static byte[] randomBytes(int aSize) { + return randomBlob(aSize); + } + + public static byte[] randomBlob(int aSize) { + byte[] retval = new byte[aSize]; + for (int i = 0; i < retval.length; i++) { + retval[i] = randomByte(); + } + return retval; + } + + public static byte randomByte() { + return (byte) random.nextInt(); + } + + public static double randomDouble() { + return random.nextLong(); + } + + + public static int randomInt() { + return random.nextInt(); + } + + public static int randomInt(int min, int max) { + return (int) ((Math.random() * (double) (max + 1 - min)) + min); + } + + public static long randomLong() { + return random.nextLong(); + } + + public static long randomLong(long min, long max) { + return (long) ((Math.random() * (double) (max + 1L - min)) + min); + } + + public static String randomName(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(i % 2 == 0 ? randomNonVowel() : randomVowel()); + } + return sb.toString(); + } + + public static void randomSleep(long min, long max) { + try { + Thread.sleep(randomLong(min, max)); + } catch (InterruptedException ie) { + + } + } + + public static String randomString(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(randomChar()); + } + return sb.toString(); + } + + public static String randomString() { + return "" + randomLong(); + } + + +} + +/* + * $Log: Rand.java,v $ + * Revision 1.4 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.3 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.2 2004/09/03 22:35:38 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 12:21:27 justb + * *** empty log message *** + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Servlets.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Servlets.java new file mode 100755 index 0000000000..3b0f20c89f --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Servlets.java @@ -0,0 +1,67 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Servlet utilities. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Servlets.java,v 1.2 2007/11/23 21:10:17 justb Exp $ + */ +public class Servlets { + + /** + * Get parameter; if not set or empty return null. + */ + public static String getParameter(HttpServletRequest aRequest, String aName) { + return getParameter(aRequest, aName, null); + } + + /** + * Get parameter; if not set or empty return specified default value. + */ + public static String getParameter(HttpServletRequest aRequest, String aName, String aDefault) { + String value = aRequest.getParameter(aName); + if (value == null || value.length() == 0) { + value = aDefault; + } + return value; + } + + /** + * Set HTTP headers to prevent caching. + */ + public static void setNoCacheHeaders(HttpServletResponse aResponse) { + // Set to expire far in the past. + aResponse.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); + + // Set standard HTTP/1.1 no-cache headers. + aResponse.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + + // Set IE extended HTTP/1.1 no-cache headers (use addHeader). + aResponse.addHeader("Cache-Control", "post-check=0, pre-check=0"); + + // Set standard HTTP/1.0 no-cache header. + aResponse.setHeader("Pragma", "no-cache"); + + } + +} + +/* + * $Log: Servlets.java,v $ + * Revision 1.2 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.1 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * + */ + + diff --git a/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Sys.java b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Sys.java new file mode 100755 index 0000000000..2b72ab55e1 --- /dev/null +++ b/sw/in_progress/pow/ServletPow/eclipse ServletPow/users/genin/pushlet-2.0.4/src/nl/justobjects/pushlet/util/Sys.java @@ -0,0 +1,113 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + + +import java.io.FileInputStream; +import java.io.IOException; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Properties; + +/** + * Utilities that interact with the underlying OS/JVM. + * + * @author Just van den Broecke + * @version $Id: Sys.java,v 1.4 2007/11/10 14:17:18 justb Exp $ + */ +public class Sys { + + /** + * Replace characters having special meaning inside HTML tags + * with their escaped equivalents, using character entities such as '&'. + *

    + *

    The escaped characters are : + *

      + *
    • < + *
    • > + *
    • " + *
    • ' + *
    • \ + *
    • & + *
    + *

    + *

    This method ensures that arbitrary text appearing inside a tag does not "confuse" + * the tag. For example, HREF='Blah.do?Page=1&Sort=ASC' + * does not comply with strict HTML because of the ampersand, and should be changed to + * HREF='Blah.do?Page=1&Sort=ASC'. This is commonly seen in building + * query strings. (In JSTL, the c:url tag performs this task automatically.) + */ + static public String forHTMLTag(String aTagFragment) { + final StringBuffer result = new StringBuffer(); + + final StringCharacterIterator iterator = new StringCharacterIterator(aTagFragment); + char character = iterator.current(); + while (character != CharacterIterator.DONE) { + if (character == '<') { + result.append("<"); + } else if (character == '>') { + result.append(">"); + } else if (character == '\"') { + result.append("""); + } else if (character == '\'') { + result.append("'"); + } else if (character == '\\') { + result.append("\"); + } else if (character == '&') { + result.append("&"); + } else { + //the char is not a special one + //add it to the result as is + result.append(character); + } + character = iterator.next(); + } + return result.toString(); + } + + /** + * Load properties file from classpath. + */ + static public Properties loadPropertiesResource(String aResourcePath) throws IOException { + try { + // Use the class loader that loaded our class. + // This is required where for reasons like security + // multiple class loaders exist, e.g. BEA WebLogic. + // Thanks to Lutz Lennemann 29-aug-2000. + ClassLoader classLoader = Sys.class.getClassLoader(); + + Properties properties = new Properties(); + + // Try loading it. + properties.load(classLoader.getResourceAsStream(aResourcePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties resource from " + aResourcePath); + } + } + + /** + * Load properties file from file path. + */ + static public Properties loadPropertiesFile(String aFilePath) throws IOException { + try { + + Properties properties = new Properties(); + + // Try loading it. + properties.load(new FileInputStream(aFilePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties file from " + aFilePath); + } + } + + /** + * Shorthand for current time. + */ + static public long now() { + return System.currentTimeMillis(); + } + +} diff --git a/sw/in_progress/pow/ServletPow/pow_sql_maker.sql b/sw/in_progress/pow/ServletPow/pow_sql_maker.sql new file mode 100755 index 0000000000..7886a2515a --- /dev/null +++ b/sw/in_progress/pow/ServletPow/pow_sql_maker.sql @@ -0,0 +1,49 @@ + + +SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; + + +-- +-- Base de données: `pow_sql` +-- +CREATE DATABASE pow_sql; +-- -------------------------------------------------------- + +GRANT ALL PRIVILEGES ON pow_sql.* TO pow_user@localhost IDENTIFIED BY 'pwdpow_user'; + +use pow_sql; +-- +-- Structure de la table `connexion` +-- + +CREATE TABLE IF NOT EXISTS `connexion` ( + `webId` int(11) NOT NULL AUTO_INCREMENT, + `login` varchar(50) NOT NULL, + `start` date NOT NULL, + `end` date DEFAULT NULL, + PRIMARY KEY (`webId`) +) TYPE=INNODB AUTO_INCREMENT=1 ; + +-- +-- Contenu de la table `connexion` +-- + + +-- -------------------------------------------------------- + +-- +-- Structure de la table `log` +-- + +CREATE TABLE IF NOT EXISTS `log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `msg` varchar(300) DEFAULT NULL, + `webId` int(11) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`webId`) REFERENCES connexion(webId) ON DELETE CASCADE +) TYPE=INNODB AUTO_INCREMENT=1 ; + +-- +-- Contenu de la table `log` +-- + diff --git a/sw/in_progress/pow/ivy-1.2.13.jar b/sw/in_progress/pow/ivy-1.2.13.jar new file mode 100644 index 0000000000..be51c0e1f0 Binary files /dev/null and b/sw/in_progress/pow/ivy-1.2.13.jar differ diff --git a/sw/in_progress/pow/jssecacerts b/sw/in_progress/pow/jssecacerts new file mode 100644 index 0000000000..d646d45830 Binary files /dev/null and b/sw/in_progress/pow/jssecacerts differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/design.css b/sw/in_progress/pow/pow/WebContent/CSS/design.css new file mode 100644 index 0000000000..124c98ec46 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/design.css @@ -0,0 +1,210 @@ +body +{ + background-color: #CCFFCC; + margin: 0%; + padding: 0%; + outline: 0%; + height: 100%; + overflow:hidden; + max-width:2048px; + font-size : 11; +} + +select{ + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + vertical-align: middle; + background-color: #F5F5DC; +} +input { + background-color:#F5F5DC; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 10px; +} + +label { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#welcome +{ + position:absolute; + top:0; + left:0; + height:3%; + width: 100%; + background-color: #EEEEEE; + text-align: center; + font-weight:bold; + font-size : 12; +} +#usr +{ + position:absolute; + top:0; + right:6%; + height:3%; + width:25%; + background-color: #EEEEEE; + text-align: right; + white-space:nowrap; +} +#page +{ +position:absolute; +top:3%; +left:0; +height:97%; +width: 100%; +} + + +#choicePanel{ + position:absolute; + top:0%; + left:0%; + height: 13%; + width : 15%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#aircraftSelector +{ + text-align: center; + background-color: #EEEEEE; +} + +#trackdiv +{ + text-align: center; + background-color: #EEEEEE; +} + +#active_block +{ + font-size:11; + text-align: center; +} + +#FlightPlan +{ + overflow:auto; + position:absolute; + top:0%; + left:15%; + height: 40%; + width : 14.9%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#FlightParams +{ + position:absolute; + top:13%; + left :0% + text-align: center; + height: 27%; + width : 14.9%; + border: 1px solid black; + background-color: #EEEEEE; +} + +#map_canvas +{ + position:absolute; + top:0; + left:30%; + width:70%; + height: 95%; + border:1px solid black; +} + + +#Settings +{ + overflow:auto; + position:absolute; + left:0%; + top:40%; + text-align: left; + height: 55%; + width: 29.9%; + background-color: #EEEEEE; + border: 1px solid black; +} + +#page_setting { + +} + +#setting { + width: 400px; + height: 250px; + padding: 0.5em; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 8; +} +#param +{ + overflow:auto; +} + +#NewsDiv +{ + position:absolute; + overflow:auto; + left:0%; + top:95%; + height: 5%; + width: 100%; + text-align: left; + vertical-align:top; + background-color: #EEEEEE; + border: 1px solid black; +} + +#info +{ + text-align: left; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#Debug +{ + overflow:auto; + position:absolute; + left:65%; + top:50%; + text-align: center; + height: 50%; + width: 35%; + background-color: #EEEEEE; + border: 1px solid black; + padding-top:20px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#title{ + font-weight:bold; + font-size:18; + text-align:center; +} + +table.param { +border:3px solid #6495ed; +border-collapse:collapse; +width:90%; +margin:auto; +} +td.param { +font-family:sans-serif; +font-size:11px; +border:1px solid #6495ed; +padding:5px; +text-align:left; +} diff --git a/sw/in_progress/pow/pow/WebContent/CSS/design2.css b/sw/in_progress/pow/pow/WebContent/CSS/design2.css new file mode 100644 index 0000000000..893a523f96 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/design2.css @@ -0,0 +1,50 @@ +body { + background-color: #EEEEEE; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +select{ + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + vertical-align: middle; + background-color: #F5F5DC; +} +input { + border:1px solid black; + background-color:#F5F5DC; + font-size: 11px; +} + + +#modifImmat { + position : absolute; + top : 0; +} + + +#modifPwd { + position : absolute; + top : 0; +} + + +#modifRight { + position : absolute; + top : 0; +} + +#modifyUser { + position : absolute; + top : 0; +} + +#createUser { + position : absolute; + top : 0; +} + +#mainForm { + position : absolute; + top : 0; +} diff --git a/sw/in_progress/pow/pow/WebContent/CSS/designHelp.css b/sw/in_progress/pow/pow/WebContent/CSS/designHelp.css new file mode 100644 index 0000000000..df08745f31 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/designHelp.css @@ -0,0 +1,21 @@ +body +{ + width: 90%; + margin-top: 5px; + margin-bottom: 5px; + margin-left:5%; + margin-reight:5%; + background-color: #CCFFCC; + text-align:justify; +} + +h3,h2 +{ + color : navy; + text-align:center; + text-decoration:underline; +} +#problem +{ + color:red; +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/CSS/designLogOut.css b/sw/in_progress/pow/pow/WebContent/CSS/designLogOut.css new file mode 100644 index 0000000000..02a1a63f3f --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/designLogOut.css @@ -0,0 +1,12 @@ +body +{ + background-color: #CCFFCC; + margin-top: 2%; + padding: 0%; + outline: 0%; + height: 100%; + overflow:hidden; + max-width:2048px; + text-align:center; + font-size:24px; +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/CSS/designWelcome.css b/sw/in_progress/pow/pow/WebContent/CSS/designWelcome.css new file mode 100644 index 0000000000..e6cd8076f0 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/designWelcome.css @@ -0,0 +1,30 @@ +body +{ + width: 960px; + margin-top: 100px; + margin-bottom: 5px; + background-image: url("Icons/logo.png"); + background-repeat:no-repeat; + background-color: #CCFFCC; + +} + +#signIn +{ + margin: auto; + width: 300px; + height: 140px; + border: 1px solid black; +} + +#log +{ + margin-left: 30px; +} + +a +{ + position:absolute; + right:1%; + top:80%; +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/CSS/design_admin.css b/sw/in_progress/pow/pow/WebContent/CSS/design_admin.css new file mode 100644 index 0000000000..867056a7a6 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/design_admin.css @@ -0,0 +1,99 @@ +body { + background-color: #EEEEEE; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +select{ + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + vertical-align: middle; + background-color: #F5F5DC; +} +input { + border:1px solid black; + background-color:#F5F5DC; + font-size: 11px; +} + +label { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +span { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +td { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +#title { + position : absolute; + top : 0%; + left : 0%; + height : 5%; + width : 100%; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + text-align : right; + font-size : 11px; + background-color: #BC8F8F; + border: 1px solid black; +} + +#page { + position : absolute; + top : 15%; + left : 15%; + width : 70%; + height : 65%; + border: 1px solid black; + background-color: #EEEEEE; +} + + +#modifImmat { + position : absolute; + top : 15%; +} + + +#modifPwd { + position : absolute; + top : 15%; +} + + +#modifRight { + position : absolute; + top : 15%; +} + +#modifyUser { + position : absolute; + top : 15%; +} + +#createUser { + position : absolute; + top : 15%; +} + +#mainForm { + position : absolute; + top : 15%; +} + + +#createIvyUser { + position : absolute; + top : 15%; +} + +#listIvyUser { + position : absolute; + top : 15%; +} diff --git a/sw/in_progress/pow/pow/WebContent/CSS/designbackup.css b/sw/in_progress/pow/pow/WebContent/CSS/designbackup.css new file mode 100644 index 0000000000..b9ea91607d --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/designbackup.css @@ -0,0 +1,87 @@ +body +{ + background-color: #CCFFCC; + margin: 0%; + padding: 0%; + outline: 0%; + height: 95%; +} +#page +{ + width: 100%; + height: 95%; +} + +#logo +{ + width: 960px; + height: 100px; + background-image: url("banniere.jpg"); + background-repeat: repeat-x; + margin-bottom: 10px; +} + +#leftmenu +{ + /* float: left; /* Le menu flottera à gauche */ + /* width: 120px; *//* Très important : donner une taille au menu */ +} +#welcome +{ + text-align: center; + background-color: #EEEEEE; + border: 2px solid black; + margin-bottom: 10px; /* Pour éviter que les éléments du menu ne soient trop collés */ +} +#choice +{ +float: left; + text-align: center; + background-color: #EEEEEE; + border: 2px solid black; + height: 190px; + width: 20px; +} +#map_canvas +{ + width: 690px; + height: 350px; + margin-left: 125px; +} + +#FlightPlan +{ + float: right; + width: 135px; /* Très important : donner une taille au menu */ + height: 345px; + border: 2px solid black; + background-color: #EEEEEE; +} + + + +#ControlPanel +{ + float: left; + text-align: center; + height: 150px; + width: 600px; + border: 2px solid black; + background-color: #EEEEEE; +} +#FlightParams +{ + text-align: center; + float: right; + height: 150px; + width: 350px; + border: 2px solid black; + background-color: #EEEEEE; +} +table +{ + margin-left: 20px; + margin-bottom: 20px; +} + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/CSS/dtree.css b/sw/in_progress/pow/pow/WebContent/CSS/dtree.css new file mode 100644 index 0000000000..ccc20f8c35 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/dtree.css @@ -0,0 +1,34 @@ +/*--------------------------------------------------| +| dTree 2.05 | www.destroydrop.com/javascript/tree/ | +|---------------------------------------------------| +| Copyright (c) 2002-2003 Geir Landrö | +|--------------------------------------------------*/ + +.dtree { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + color: #666; + white-space: nowrap; +} +.dtree img { + border: 0px; + vertical-align: middle; +} +.dtree a { + color: #333; + text-decoration: none; +} +.dtree a.node, .dtree a.nodeSel { + white-space: nowrap; + padding: 1px 2px 1px 2px; +} +.dtree a.node:hover, .dtree a.nodeSel:hover { + color: #333; + text-decoration: underline; +} +.dtree a.nodeSel { + background-color: #c0d2ec; +} +.dtree .clip { + overflow: hidden; +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/CSS/tab.css b/sw/in_progress/pow/pow/WebContent/CSS/tab.css new file mode 100644 index 0000000000..2e9043ed76 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/tab.css @@ -0,0 +1,110 @@ +/* $Id: example.css,v 1.5 2006/03/27 02:44:36 pat Exp $ */ + +/*-------------------------------------------------- + REQUIRED to hide the non-active tab content. + But do not hide them in the print stylesheet! + --------------------------------------------------*/ +.tabberlive .tabbertabhide { + display:none; +} + +/*-------------------------------------------------- + .tabber = before the tabber interface is set up + .tabberlive = after the tabber interface is set up + --------------------------------------------------*/ +.tabber { +} +.tabberlive { + margin-top:1em; +} + +/*-------------------------------------------------- + ul.tabbernav = the tab navigation list + li.tabberactive = the active tab + --------------------------------------------------*/ +ul.tabbernav +{ + margin:0; + padding: 3px 0; + border-bottom: 1px solid #778; + font: bold 12px Verdana, sans-serif; +} + +ul.tabbernav li +{ + list-style: none; + margin: 0; + display: inline; +} + +ul.tabbernav li a +{ + padding: 3px 0.5em; + margin-left: 3px; + border: 1px solid #778; + border-bottom: none; + background: #DDE; + text-decoration: none; +} + +ul.tabbernav li a:link { color: #448; } +ul.tabbernav li a:visited { color: #667; } + +ul.tabbernav li a:hover +{ + color: #000; + background: #AAE; + border-color: #227; +} + +ul.tabbernav li.tabberactive a +{ + background-color: #fff; + border-bottom: 1px solid #fff; +} + +ul.tabbernav li.tabberactive a:hover +{ + color: #000; + background: white; + border-bottom: 1px solid white; +} + +/*-------------------------------------------------- + .tabbertab = the tab content + Add style only after the tabber interface is set up (.tabberlive) + --------------------------------------------------*/ +.tabberlive .tabbertab { + padding:5px; + border:1px solid #aaa; + border-top:0; + + /* If you don't want the tab size changing whenever a tab is changed + you can set a fixed height */ + + /* height:200px; */ + + /* If you set a fix height set overflow to auto and you will get a + scrollbar when necessary */ + + /* overflow:auto; */ +} + +/* If desired, hide the heading since a heading is provided by the tab */ +.tabberlive .tabbertab h2 { + display:none; +} +.tabberlive .tabbertab h3 { + display:none; +} + +/* Example of using an ID to set different styles for the tabs on the page */ +.tabberlive#tab1 { +} +.tabberlive#tab2 { +} +.tabberlive#tab2 .tabbertab { + height:200px; + overflow:auto; +} + diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif new file mode 100644 index 0000000000..085ccaecaf Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-anim_basic_16x16.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000000..954e22dbd9 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000000..64ece5707d Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000000..abdc01082b Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100644 index 0000000000..9b383f4d2e Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png new file mode 100644 index 0000000000..a23baad25b Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000..42ccba269b Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100644 index 0000000000..39d5824d6a Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000000..f1273672d2 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png new file mode 100644 index 0000000000..359397acff Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000..b273ff111d Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_222222_256x240.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png new file mode 100644 index 0000000000..c357355aa7 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_228ef1_256x240.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png new file mode 100644 index 0000000000..85e63e9f60 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ef8c08_256x240.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000000..e117effa3d Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffd27a_256x240.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000..42f8f992c7 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/images/ui-icons_ffffff_256x240.png differ diff --git a/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css new file mode 100644 index 0000000000..312dd8043e --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/CSS/ui-lightness/jquery-ui-1.8.2.custom.css @@ -0,0 +1,489 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } +.ui-widget-content a { color: #333333; } +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable +----------------------------------*/ +.ui-selectable-helper { border:1px dotted black } +/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +/* IE7-/Win - Fix extra vertical space in lists */ +.ui-accordion a { zoom: 1; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete +----------------------------------*/ +.ui-autocomplete { position: absolute; cursor: default; } +.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* Menu +----------------------------------*/ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* Button +----------------------------------*/ + +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ + + + + + +/* Dialog +----------------------------------*/ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 0.8em; height: 0.8em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/Icons/E.png b/sw/in_progress/pow/pow/WebContent/Icons/E.png new file mode 100644 index 0000000000..c54150820a Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/E.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/N (copie).png b/sw/in_progress/pow/pow/WebContent/Icons/N (copie).png new file mode 100644 index 0000000000..b7a747cd39 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/N (copie).png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/N.png b/sw/in_progress/pow/pow/WebContent/Icons/N.png new file mode 100644 index 0000000000..b7a747cd39 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/N.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/NE.png b/sw/in_progress/pow/pow/WebContent/Icons/NE.png new file mode 100644 index 0000000000..14d39ae0f0 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/NE.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/NW.png b/sw/in_progress/pow/pow/WebContent/Icons/NW.png new file mode 100644 index 0000000000..e57382d0d4 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/NW.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/S.png b/sw/in_progress/pow/pow/WebContent/Icons/S.png new file mode 100644 index 0000000000..edeabb494d Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/S.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/SE.png b/sw/in_progress/pow/pow/WebContent/Icons/SE.png new file mode 100644 index 0000000000..e2e35ba552 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/SE.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/SW.png b/sw/in_progress/pow/pow/WebContent/Icons/SW.png new file mode 100644 index 0000000000..71f3be47ae Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/SW.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/W.png b/sw/in_progress/pow/pow/WebContent/Icons/W.png new file mode 100644 index 0000000000..baa74b59ad Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/W.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/arrow.png b/sw/in_progress/pow/pow/WebContent/Icons/arrow.png new file mode 100644 index 0000000000..3a004f60b5 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/arrow.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/arrow2.png b/sw/in_progress/pow/pow/WebContent/Icons/arrow2.png new file mode 100644 index 0000000000..d2cae73712 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/arrow2.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/blue-dot.png b/sw/in_progress/pow/pow/WebContent/Icons/blue-dot.png new file mode 100644 index 0000000000..98b280d301 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/blue-dot.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/favicon.ico b/sw/in_progress/pow/pow/WebContent/Icons/favicon.ico new file mode 100644 index 0000000000..7cd42a2755 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/favicon.ico differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/logo.png b/sw/in_progress/pow/pow/WebContent/Icons/logo.png new file mode 100644 index 0000000000..032f6d16e7 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/logo.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/losange.gif b/sw/in_progress/pow/pow/WebContent/Icons/losange.gif new file mode 100644 index 0000000000..dfadf2d823 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/losange.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/losange.png b/sw/in_progress/pow/pow/WebContent/Icons/losange.png new file mode 100644 index 0000000000..0786209c39 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/losange.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Icons/red-dot.png b/sw/in_progress/pow/pow/WebContent/Icons/red-dot.png new file mode 100644 index 0000000000..b0f3f0e928 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/Icons/red-dot.png differ diff --git a/sw/in_progress/pow/pow/WebContent/Interface.jsp b/sw/in_progress/pow/pow/WebContent/Interface.jsp new file mode 100644 index 0000000000..25e31cdd09 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/Interface.jsp @@ -0,0 +1,2015 @@ +<%@page import="pow.ConfJSP,java.util.StringTokenizer,java.util.NoSuchElementException" %> + +<% + if (session.getAttribute("login")==null) { + out.println(""); + } +%> + + + + + + + + POW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "); + } + else { + String login = ((String) (session.getAttribute("login"))).toString(); + String right = ((String) (session.getAttribute("rights"))).toString(); + if (right.equals("visitor")) + { out.println("var usr_right=\"visitor\";"); + out.println("var usr_login=\"nologged\";"); + } + else if (right.equals("admin")) + { + out.println("var usr_right=\"admin\";"); + out.println("var usr_login=\""+login+"\";"); + } + else if (right.equals("user")){ // gestion de la liste des drones controlables + out.println("var usr_right=\"user\";"); + out.println("var usr_login=\""+login+"\";"); + out.println("var drone_ctl=new Array();"); + String droneCtl = ((String) (session.getAttribute("dronectl"))).toString(); + StringTokenizer st = new StringTokenizer(droneCtl,";"); + String d; + for(int i = 0 ; i< st.countTokens() ;i++){ + d=st.nextToken(); + out.println("drone_ctl[\""+ d +"\"]=1;"); + } + try{ + while (st.hasMoreTokens()) { + d=st.nextToken(); + } + } + catch (NoSuchElementException ex){} + + } + } + %> + var noPlaneBefore=true; // pour initialiser au premier push flight param + var ajax_url = "ajaxRqst.srv"; +/* ********** drone state timeout ******** */ + var droneStateDieEvent = new Array(); // timeout en cas d'event die + var droneStateDataEvent = new Array(); // timeout en cas de non evenement data + var dieEventTimeoutTime = 10000; //10sec after plane_die event remove drone + var dataEventTimeoutTime = 5000; //5sec without any position data about a drone remove drone + var waypoint_modif = new Array(); // + var block_jump_timeout=-1; + var setting_change_timeout=-1; + var order_response_timeout = 30000; // 30 secondes + var setting_to_change_id=-1; +/* *************************************************************************** Global variables *************************************************************************************** */ + var map; + + var planes = new Array(); + var nb_planes =0; + var markers = new Array(); + var markers_color = new Array(); // stock les balises de couleurs de chaque drone + var diametre_drone_balise = 50; //50m de base + var selected_plane = ""; + var selected_plane_id = 0; + var selected_index=0; + var tracking = false; + +/* *******************Flight Plan variables :******************** */ + var waypoints = new Array(); + var waypoint_tmp = null; + var index_wpt = 0; + var blocks= new Array(); + var index_block = 0; + var active_block_id=0; + var active_block_name=""; + var fpl_name=""; + var lat0=0; + var lon0=0; + var fpl_alt=0; + var security_height=0; + var fpl_ground_alt=0; + var max_dist=0; + + +/* ********************Planes and waypoints icons******************** */ + var plane_icons = new Array(); + for (var i=0;i<8;i++){ + plane_icons[i] = new GIcon(); + plane_icons[i].shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + plane_icons[i].iconSize = new GSize(60,60); + plane_icons[i].shadowSize = new GSize(22, 20); + plane_icons[i].infoWindowAnchor = new GPoint(50, 1); + plane_icons[i].iconAnchor = new GPoint(30, 30); + } + plane_icons[0].image="Icons/N.png"; + plane_icons[1].image="Icons/NE.png"; + plane_icons[2].image="Icons/E.png"; + plane_icons[3].image="Icons/SE.png"; + plane_icons[4].image="Icons/S.png"; + plane_icons[5].image="Icons/SW.png"; + plane_icons[6].image="Icons/W.png"; + plane_icons[7].image="Icons/NW.png"; + + var wpt_icon=new GIcon(); + wpt_icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + wpt_icon.iconSize = new GSize(20,20); + wpt_icon.shadowSize = new GSize(22, 20); + wpt_icon.infoWindowAnchor = new GPoint(8, 1); + wpt_icon.iconAnchor = new GPoint(6, 20); + //wpt_icon.image="Icons/losange.png"; + wpt_icon.image="Icons/blue-dot.png"; + + var iconMarkerTemp=new GIcon(); + iconMarkerTemp.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"; + iconMarkerTemp.iconSize = new GSize(20,20); + iconMarkerTemp.shadowSize = new GSize(22, 20); + iconMarkerTemp.infoWindowAnchor = new GPoint(8, 1); + iconMarkerTemp.iconAnchor = new GPoint(6, 20); + iconMarkerTemp.image="Icons/red-dot.png"; +/* *************************************************************************** Functions **************************************************************************************************** */ + +/* ************ prevent user from going back to this page by browser's forward button****************************** */ + +function backButtonOverride() +{ + // Work around a Safari bug + // that sometimes produces a blank page + setTimeout("backButtonOverrideBody()", 1); + +} + +function backButtonOverrideBody() +{ + // Works if we backed up to get here + try { + history.forward(); + } catch (e) { + // OK to ignore + } + // Every quarter-second, try again. The only + // guaranteed method for Opera, Firefox, + // and Safari, which don't always call + // onLoad but *do* resume any timers when + // returning to a page + setTimeout("backButtonOverrideBody()", 500); +} +/* ******************* Useful functions ******************** */ +// Gets an element of the html document by its class name + function getElementsByClass(tag, className){ + var elements = document.getElementsByTagName(tag); + var results = new Array(); + for(var i=0; i< elements.length; i++){ + if(elements[i].className == className){ + results[results.length] = elements[i]; + } + } + return results; + } + + + function pause(time){ + d=new Date(); + diff=0; + while(diff < time){ + n=new Date(); + diff=n-d; + } + } + + + //Creates a GoogleMaps marker + + + + + function createMarker(point, legend, icon){ + var marker = new GMarker(point, icon); + GEvent.addListener(marker, 'click', function() { + marker.openInfoWindowHtml(legend); + }); + return marker; + } + + var old_lat; + var old_lon; + //Creates a draggable marker with an EventListener + function createDraggableMarker(point,namewpt,wpt_icon,index_wpt, bool){ + var fpl_file_name="upload/"+planes[selected_index]["id"]+"/flight_plan.xml"; + var marker = new GMarker(point,{legend: namewpt,icon: wpt_icon,draggable: bool,bouncy:true}); + //var marker = new GMarker(point,{title: name,draggable: bool}); + //var marker = new GMarker(point,{draggable: bool}); + GEvent.addListener(marker, 'click', function() { + marker.openInfoWindowHtml(namewpt); + }); + if (bool){ + GEvent.addListener(marker, 'dragend', function(latlng) { + if (latlng){ + //alert("id wpt="+index_wpt+" name=" +namewpt+" lat="+latlng.lat()+" lon="+latlng.lng()); + var lat = latlng.lat(); + var lon = latlng.lng(); + moveWpt(selected_plane_id,namewpt,lat,lon,false,true,index_wpt); + } + }); + + GEvent.addListener(marker, 'dragstart', function(latlng) { + if (latlng){ + old_lat=latlng.lat(); + old_lon=latlng.lng(); + } + }); + } + + return marker; + } + + + + + +//Converts ditances from (lat0,lon0) given in meters into latitudes or longitudes, and vice versa + function xMetersToDegrees(x,lat0){ + return (x/1852/60+parseFloat(lat0)); + } + function yMetersToDegrees(y,lat,lon0){ + return (y/1852/60*Math.cos(lat)+parseFloat(lon0)); + } + + function xDegreesToMeters(lat,lat0){ + return((lat-lat0)*1852*60); + } + function yDegreesToMeters(lat,lon,lon0){ + return(lat!=0?(lon-lon0)/Math.cos(lat)*1852*60:0); + } + + + function name_from_id(id){ + var match=false; + for (var i=0;i< planes.length;i++){ + if(planes[i]["id"]==id){match=true;break;} + } + if (match){ + return (planes[i]["name"]); + }else{ + return (null); + } + } + /* *************** JQUERY stuffs ***************************** */ + $(function(){ + //init(); + //$("#Settings").draggable();$("#Settings").resizable(); + //$("#map_canvas").draggable();$("#map_canvas").resizable(); + //$("#Debug").draggable();$("#Debug").resizable(); + //$("#choicePanel").draggable();$("#choicePanel").resizable(); + //$("#FlightPlan").draggable();$("#FlightPlan").resizable(); + //$("#FlightParams").draggable();$("#FlightParams").resizable(); + }); +/* ********************* Fonctions de Push ******************** */ + + function initialize_push() { + // alert('go'); + p_join_listen(null, 'stream'); + // TODO il faudra gerer le cas ou cela bloque !!!! et passer en pull + // p_join_listen(null, 'pull'); + p_subscribe('/data/drone/iskill', 'msg from serveur'); + p_subscribe('/data/drones_maj', 'msg from serveur'); + p_subscribe('/data/order/waypoint_moved', 'msg from serveur'); + p_subscribe('/data/order/change_setting', 'msg from serveur'); + p_subscribe('/data/order/plane_die', 'msg from serveur'); + p_subscribe('/data/order/plane_resurect', 'msg from serveur'); + p_subscribe('/data/order/new_plane', 'msg from serveur'); + p_subscribe('/data/order/block_changed', 'msg from serveur'); + p_subscribe('/data/order/other', 'msg from serveur'); + p_subscribe('/data/order/settings', 'msg from serveur'); + + p_subscribe('/chat','msg from web client'); + p_subscribe('/client_action','action from web client'); + } + + function initialize_push_pullmode() { + + p_join_listen(null, 'pull'); + p_subscribe('/data/drone/iskill', 'msg from serveur'); + p_subscribe('/data/drones_maj', 'msg from serveur'); + p_subscribe('/data/order/waypoint_moved', 'msg from serveur'); + p_subscribe('/data/order/change_setting', 'msg from serveur'); + p_subscribe('/data/order/plane_die', 'msg from serveur'); + p_subscribe('/data/order/plane_resurect', 'msg from serveur'); + p_subscribe('/data/order/new_plane', 'msg from serveur'); + p_subscribe('/data/order/block_changed', 'msg from serveur'); + p_subscribe('/data/order/other', 'msg from serveur'); + p_subscribe('/data/order/settings', 'msg from serveur'); + + p_subscribe('/chat','msg from web client'); + p_subscribe('/client_action','action from web client'); + } + + function displayControl(aString) { + document.debugEventDisplay.event.value = aString; + } + // callback on data Events + // call apropirate function according to the received event + + function onData(event) { + var subject = event.get('p_subject'); + + // displayControl(""+ event.toString()); + + if (subject=="/data/drones_maj") { handleDronePositionUpsate(event);} + else if (subject =="/data/order/waypoint_moved") {orderprocessing_waypoint(event);} + else if (subject =="/data/order/block_changed") {orderprocessing_jump2block(event);} + else if (subject =="/data/order/change_setting") {orderprocessing_setting(event);} + else if (subject =="/data/order/plane_die") {orderprocessing_planedie(event);} + else if (subject =="/data/order/plane_resurect"){orderprocessing_planeressurect(event);} + else if (subject =="/data/order/new_plane") {orderprocessing_newplane(event);} + else if (subject =="/data/drone/iskill") {orderprocessing_planekilled(event);} + else if (subject =="/data/order/settings") {orderprocessing_csv_settings(event);} + else if (subject =="/chat") {orderprocessing_chat(event);} + else if (subject =="/client_action") {orderprocessing_client_action(event);} + } + + // callback on all other kind of Events + + <%--function onEvent(event) { + var subject = event.get('p_subject'); + displayControl("EVENT CALLBACK "+subject+"\n" + event.toString()); + + + } + --%> +/* ********************* initilization de l'interface ******************* */ + function initialize_display(){ + var aircraftList = document.getElementById("aircraftForm").aircraftList; + if (nb_planes ==0)//If there is no active aircraft, the list only has one option : No aircraft + {aircraftList.options[0]=new Option("No aircraft");} +} + +/* *********************functions to check airplanes ******************* */ + +/* *********************Processing events ******************* */ + // recherche si l'id de l'avion est deja present dans le tableau des drones deja + function handleDronePositionUpsate(event){ + if (planes.length==0) {noPlaneBefore=true;} + var id = parseInt(event.get('aircraftId')); + var match=false; + var insert=false; + var aircraftList = document.getElementById("aircraftForm").aircraftList; + nb_planes=planes.length; + for (var i=0;i< nb_planes;i++){ + if(planes[i]["id"]> id){insert=true;break;} // on garde le tableau trié + if (planes[i]["id"]==id){match=true;break;} // on recupere en i le drone correspondant à id + } + if(!match){ + var k=0; + if(insert){ // on insert au milieu + k=i; + planes.splice(i,0,new Array()); + markers.splice(i,0,null); + markers_color.splice(i,0,null); + // on insere l'aircraft dan sla liste deroulante + //see http://www.mredkj.com/tutorials/tutorial005.html + var elOptNew = document.createElement('option'); + elOptNew.text = event.get('dbName') + var elOptOld = aircraftList.options[i]; + try { + aircraftList.add(elOptNew, elOptOld); // standards compliant; doesn't work in IE + } + catch(ex) { + aircraftList.add(elOptNew, i); // IE only + } + }else{ // on met à la fin du tableau + k=planes.length; + planes[k] = new Array(); + markers[k]= null; // inutile + markers_color[k]=null; + aircraftList.options[k]=new Option(event.get('dbName')); + } + droneStateDieEvent[k] = -1; // init un timeout vide + + //alert('new plane !!!!'); + // on ajoute l'aircraft à la liste des drones selectionnables + + //aircraftList.options[k]=new Option(event.get('dbName')); + // + planes[k]["id"]=id; + planes[k]["name"] =event.get('dbName'); + planes[k]["lat"] = event.get('dbLatitude'); + planes[k]["lon"] = event.get('dbLongitude'); + planes[k]["heading"]= event.get('dbCourse'); + // maj des param pour selected acrf + planes[k]["speed"]= event.get('dbSpeed'); + planes[k]["altitude"]= event.get('dbAmsl'); + planes[k]["vspeed"]= event.get('dbVert_speed'); + planes[k]["height"]= event.get('dbAgl'); + planes[k]["battery"]= event.get('dbStat_battery'); + planes[k]["GPS"]= event.get('dbStat_gps'); + planes[k]["activeBlock"]= event.get('dbActive_block'); + planes[k]["engine"]= event.get('dbEngine_status'); + planes[k]["setting_id"]= event.get('dbId_Setting'); + planes[k]["setting_value"]= event.get('dbSetting_Value'); + planes[k]["drone_color"]= event.get('drone_color'); + // gere si le drone peut etre controlé ou non + if ((usr_right=="admin")||((usr_right=="user")&&(drone_ctl[event.get('dbName')]!=null))){ + planes[k]["rights"]= 1; + } + else + {planes[k]["rights"]=0;} + + var icon; + if (planes[k]["heading"]>=338 || planes[i]["heading"]< 23){ + icon = plane_icons[0]; + }else if (planes[k]["heading"]>=23 && planes[i]["heading"]<68){ + icon = plane_icons[1]; + }else if (planes[k]["heading"]>=68 && planes[i]["heading"]<113){ + icon = plane_icons[2]; + }else if (planes[k]["heading"]>=113 && planes[i]["heading"]<158){ + icon = plane_icons[3]; + }else if (planes[k]["heading"]>=158 && planes[i]["heading"]<203){ + icon = plane_icons[4]; + }else if (planes[k]["heading"]>=203 && planes[i]["heading"]<248){ + icon = plane_icons[5]; + }else if (planes[k]["heading"]>=248 && planes[i]["heading"]<293){ + icon = plane_icons[6]; + }else if (planes[k]["heading"]>=293 && planes[i]["heading"]<337){ + icon = plane_icons[7]; + } + //A marker is created and added on the map + var pos = new GLatLng(planes[k]["lat"],planes[k]["lon"]); + markers[k]=createMarker(pos,planes[k]["name"],icon); + markers_color[k] = GPolygon.Circle(pos,diametre_drone_balise,"#000000",1,1,planes[i]["drone_color"],0.5) + map.addOverlay(markers[k]); + map.addOverlay(markers_color[k]); + droneStateDataEvent[k] = setTimeout("nodataEventCallBack("+id+")",dataEventTimeoutTime); + } + else // l event envoyé correspond à un drone deja dans le tableau + { + if (droneStateDataEvent[i]!=-1) {clearTimeout(droneStateDataEvent[i]);} + var heading_changed; + //Update of the planes array + planes[i]["lat"] = event.get('dbLatitude'); + planes[i]["lon"] = event.get('dbLongitude'); + // maj des param pour selected acrf + planes[i]["speed"]= event.get('dbSpeed'); + planes[i]["altitude"]= event.get('dbAmsl'); + planes[i]["vspeed"]= event.get('dbVert_speed'); + planes[i]["height"]= event.get('dbAgl'); + planes[i]["battery"]= event.get('dbStat_battery'); + planes[i]["GPS"]= event.get('dbStat_gps'); + planes[i]["activeBlock"]= event.get('dbActive_block'); + planes[i]["engine"]= event.get('dbEngine_status'); + planes[i]["setting_id"]= event.get('dbId_Setting'); + planes[i]["setting_value"]= event.get('dbSetting_Value'); + planes[i]["drone_color"]= event.get('drone_color'); + // + var new_heading = event.get('dbCourse'); + var old_heading = planes[i]["heading"]; + //Update of the icons if the heading has changed + if (Math.abs(new_heading-old_heading)>2){ + var image; + if (new_heading>=338 || new_heading< 23){ + image = plane_icons[0].image; + }else if (new_heading>=23 && new_heading<68){ + image = plane_icons[1].image; + }else if (new_heading>=68 && new_heading<113){ + image = plane_icons[2].image; + }else if (new_heading>=113 && new_heading<158){ + image = plane_icons[3].image; + }else if (new_heading>=158 && new_heading<203){ + image = plane_icons[4].image; + }else if (new_heading>=203 && new_heading<248){ + image = plane_icons[5].image; + }else if (new_heading>=248 && new_heading<293){ + image = plane_icons[6].image; + }else if (new_heading>=293 && new_heading<337){ + image = plane_icons[7].image; + } + markers[i].setImage(image); + } + planes[i]["heading"] = new_heading; + //Setting the marker to its new position + var new_pos = new GLatLng(planes[i]["lat"],planes[i]["lon"]); + markers[i].setLatLng(new_pos); + //see http://econym.org.uk/gmap/eshapes.htm + map.removeOverlay(markers_color[i]); + markers_color[i] = GPolygon.Circle(new_pos,diametre_drone_balise,"#000000",1,1,planes[i]["drone_color"],0.5); + map.addOverlay(markers_color[i]); + droneStateDataEvent[i] = setTimeout("nodataEventCallBack("+id+")",dataEventTimeoutTime); + } + nb_planes=planes.length; + + document.getElementById("aircraftList").options.length=planes.length; + if (tracking&&nb_planes!=0){//If tracking is activated, the map is centered on the aircraft + var zoom = map.getZoom(); + var plane_number = aircraftList.selectedIndex; + map.setCenter(new GLatLng(planes[plane_number]["lat"],planes[plane_number]["lon"]),zoom); + } + + if (noPlaneBefore==true){ + noPlaneBefore=false;// !!! interruption possible + active_block_id=planes[0]["activeBlock"]; + aircraftList.options[0].selected=true; + selected_plane = planes[0]["name"]; + selected_plane_id = planes[0]["id"]; + DOMImplementation("upload/"+planes[0]["id"]+"/flight_plan.xml",fplDisplay); + DOMImplementation("upload/"+planes[0]["id"]+"/settings.xml",settingsDisplay); + } + selected_plane_update(selected_plane_id); + } + + +/* ******************** affichage log ******************* */ + +var coloryellow = true; +function addMsgLog(msg) +{ + var element = document.getElementById("info"); + //var element = document.getElementsByTagName("info"); + var newinfodiv = document.createElement("div"); + var newinfotxt = document.createTextNode(msg); + if (coloryellow) {newinfodiv.style.background = '#FFE4B5';coloryellow=false;} + else {newinfodiv.style.background = '#D2B48C';coloryellow=true;} + newinfodiv.appendChild(newinfotxt); + //element[0].appendChild(newinfodiv); + element.appendChild(newinfodiv); +} +/* ******************** Initialization of the page ******************* */ + +/* Initialization of the page : map, markers, aircraft list... */ + + + function initialize() { + + if (GBrowserIsCompatible()) { + // initialize_planes_data(); + initialize_display(); + initialize_push(); + map = new GMap2(document.getElementById("map_canvas"));//Map creation + // map.setZoom(8); + map.setMapType(G_HYBRID_MAP); + var point= new GLatLng(43.46223, 1.27289); + map.setCenter(point,15);//Center the map on a temporary point + map.setUIToDefault(); + // + GEvent.addListener(map, "zoomend", function(oldlevel,newlevel) { + var d = newlevel-oldlevel; + if (d<0) { + diametre_drone_balise=diametre_drone_balise*(-2*d); + } + else + { + diametre_drone_balise=diametre_drone_balise/(2*d); + } + //addMsgLog("d="+diametre_drone_balise+" oldz="+oldlevel+" newz=" +newlevel); + }); + }else{ + alert("Your browser is not compatible with Google Maps !"); + } + } + + + +/* Updating of the selected aircraft flight parameters */ +// recherche la place de l'avion dans le tableau + function seekIndex(plane_id) + { + var i = 0; + var trouve = false; + var res=-1; + while ((ilat y->lon !'); + x = parseFloat(childXML.getAttribute("x")); + y = parseFloat(childXML.getAttribute("y")); + lat=xMetersToDegrees(x,lat0); + lon=yMetersToDegrees(y,lat,lon0); + } + else + { + lat=parseFloat(childXML.getAttribute("lat")); + lon=parseFloat(childXML.getAttribute("long")); + } + var right=planes[selected_index]["rights"]; + waypoints[index_wpt]["marker"]=null; + + if (right==1){ + waypoints[index_wpt]["marker"]=createDraggableMarker(new GLatLng(lat,lon),nameWpt,wpt_icon,index_wpt, true); + }else { + waypoints[index_wpt]["marker"]=createDraggableMarker(new GLatLng(lat,lon),nameWpt,wpt_icon,index_wpt, false); + } + map.addOverlay(waypoints[index_wpt]["marker"]); + + var alt=false; + if (childXML.getAttribute("alt")!=null){ + alt=childXML.getAttribute("alt"); + waypoints[index_wpt]["alt"]=parseFloat(childXML.getAttribute("alt")); + } + var node_url=""; + if (right==1){ + node_url = "javascript:moveWpt("+selected_index+",'"+nameWpt+"',"+lat+","+lon+","+alt+",false,"+(index_wpt)+")"; + } + ///// + index_wpt++; + var newindex = index++; + fpl_tree.add(newindex,index_pere,nameWpt,node_url); + for(var k =0;k< nbr_attrib;k++){ + var newindex_attrib_name = index++; + var newindex_attrib_value = index++; + fpl_tree.add(newindex_attrib_name,newindex,childXML.attributes[k].nodeName); + fpl_tree.add(newindex_attrib_value,newindex_attrib_name,childXML.attributes[k].nodeValue); + //txt = txt + childXML.attributes[k].nodeName + "=" + childXML.attributes[k].nodeValue +" "; + } + } + } + else if (childXML.nodeName=="block") + { var node_url="";var txt_block_name=""; + if(childXML.attributes!=null){ + var block_name=childXML.getAttribute("name");//.replace(/ /g, '_'); + blocks[index_block]=new Array(); + blocks[index_block]["name"]=block_name; + if (active_block_id==index_block){ + active_block_name=block_name; + txt_block_name = ""+block_name+""; + } + else + { + txt_block_name = block_name; + } + var right=planes[selected_index]["rights"]; + + if (right==1){ + node_url="javascript:activateBlock("+selected_index+",'"+block_name+"',"+index_block+")"; + } + index_block++; + var txt = txt_block_name+ " : "; + var nbr_attrib = childXML.attributes.length; + for(var k =0;k< nbr_attrib;k++){ + if (childXML.attributes[k].nodeName!="name"){ + var newindex_attrib_name = index++; + var newindex_attrib_value = index++; + //d.add(newindex_attrib_name,newindex,childXML.attributes[k].nodeName); + //d.add(newindex_attrib_value,newindex_attrib_name,childXML.attributes[k].nodeValue); + txt = txt + childXML.attributes[k].nodeName + "=" + childXML.attributes[k].nodeValue +" "; + } + } + } + var newindex = index++; + fpl_tree.add(newindex,index_pere,txt,node_url); + } + // recursion + if(childXML.hasChildNodes()) { + var nodes=childXML.childNodes.length; + for(var i=0; i90.0)||(l<-90.0)||isNaN(new_lat)) { + alert('wrong format for a latitude... should be within [-90:+90]'); + return; + } + new_lon=prompt("longitude=",mylon); + if ((new_lon==null)){ + return; + } + l = parseFloat(new_lon); + if ((l>180.0)||(l<-180.0)||isNaN(new_lon)) { + alert('wrong format for a longitude... should be within [-180:+180]'); + return; + } + if (alt){ + new_alt=prompt("altitude=",alt); + if ((new_alt==null)){ + return; + } + l = parseFloat(new_alt); + if ((l<=0.0)||isNaN(new_alt)) { + alert('wrong format for an altitude... should be positive'); + return; + } + } + // + old_lat = waypoints[idwpt]["lat"]; + old_lon = waypoints[idwpt]["lon"]; + }else{ + new_lat=mylat; + new_lon=mylon; + //alert("acid="+ac_webid+" wptid="+idwpt+" lat="+mylat+"lon="+mylon+"alt="+alt); + //new_lat = waypoints[idwpt]["marker"].getLatLng().lat(); + //new_lon = waypoints[idwpt]["marker"].getLatLng().lat(); + } + + + //Ajax request to edit the flight plan xml file + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + // maj de l'affichage fpl + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("waypoint_to_move")[0]; + var idwpt_requested = parseInt(rep.getAttribute("idwpt"))-1;// cf waypoint fictif ivy + var acid_requested = parseInt(rep.getAttribute("acid")); + var lat_requested = parseFloat(rep.getAttribute("newlat")); + var lon_requested = parseFloat(rep.getAttribute("newlon")); + var was_dragged = rep.getAttribute("dragged"); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + // on ne met à jour visuellement que si le focus est sur le drone selecté + if (acid_requested==selected_plane_id){ + // mettre le waypoint dans un etat intermediaire + // en attendant l'accuse de reception + var right=planes[selected_index]["rights"]; + var marker_tmp; + if (right==1){ + marker_tmp=createDraggableMarker(new GLatLng(old_lat,old_lon),waypoints[idwpt_requested]["name"],wpt_icon,idwpt_requested, true); + }else { + marker_tmp=createDraggableMarker(new GLatLng(old_lat,old_lon),waypoints[idwpt_requested]["name"],wpt_icon,idwpt_requested, false); + } + var name_wpt = waypoints[idwpt_requested]["name"]; + var timer=setTimeout("callback_waypoint("+acid_requested+","+idwpt_requested+")",order_response_timeout); + waypoint_modif[idwpt_requested] = new createWaypoint(acid_requested,idwpt_requested,name_wpt,marker_tmp,timer); + // on efface le marker courant + // meme si elle a ete deplacé par drag & drop + // on cree un marker non draggable avec une icone temporaire + map.removeOverlay(waypoints[idwpt_requested]["marker"]); + waypoints[idwpt_requested]["marker"] = createMarker(new GLatLng(lat_requested,lon_requested),name_wpt,iconMarkerTemp); + if (waypoints[idwpt_requested]["marker"]!=null) map.addOverlay(waypoints[idwpt_requested]["marker"]); + else alert('echec creation wpt tmp'); + addMsgLog("waypoint "+ name_wpt +" for drone " + name_drone +" will be moved"); + } + else + { + addMsgLog("waypoint "+ idwpt_requested +" for drone " + name_drone +" will be moved"); + } + + } + }; + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + // on informe les autres clients de ne pas modifier le waypoint en cours (via pushlet) + p_publish('/client_action', 'login',usr_login,'action', 'lock', 'type_obj', 'waypoint', 'id_obj',idwpt,'webiddrone',selected_plane_id); + // on passe en parametre le index_wpt+1 car dans paparazzi il y a un wpt predefini a zero + + if(alt!=false){ + xhr.send("order=fpl_update&wpt_name="+name+"&aircraft_id=" +selected_plane_id+"&wpt_id="+(idwpt+1)+"&new_lat="+new_lat+"&new_lon="+new_lon+"&new_alt="+new_alt+"&dragged="+dragged+"&new_alt_for_fpl=1"); + //alert("wptid="+i+" lat="+new_lat+"lon="+new_lon+"alt="+new_alt); + }else{ + var alti=document.getElementById("altitude");var h=parseFloat(alti.innerHTML); + xhr.send("order=fpl_update&wpt_name="+name+"&aircraft_id=" +selected_plane_id+"&wpt_id="+(idwpt+1)+"&new_lat="+new_lat+"&new_lon="+new_lon+"&new_alt="+parseFloat(alti.innerHTML)+"&dragged="+dragged+"&new_alt_for_fpl=0"); + //alert("wptid="+i+" lat="+new_lat+"lon="+new_lon+"alt="+h); + } +} + + +/* ******** Activate a flight plan block ******** */ + + + + function activateBlock(ac_webid,blockname,block_id){ + // verifie qu'il n'y pas pas un verrou sur le block posé par un autre client + var k=0; + var trouve = false; + while ((!trouve)&&(k= parseFloat(min)) ){ + correct=true; + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("setting_to_change")[0]; + var idsetting_requested = parseInt(rep.getAttribute("setting_id")); + var acid_requested = parseInt(rep.getAttribute("acid")); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + addMsgLog("request change setting "+ idsetting_requested +" for drone " + name_drone +" has been sent"); + // mise en place d'un timer d'accusé reception + if(acid_requested==planes[selected_index]["id"]){ + setting_change_timeout=setTimeout("callback_setting("+acid_requested+","+idsetting_requested+")",order_response_timeout); + setting_to_change_id = idsetting_requested; + } + } + }; + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + //Send the parameters to the php page : + xhr.send("order=modif_setting&aircraft_id=" +selected_plane_id+"&setting_id="+idsetting+"&value="+new_value); + + }else{ + new_value=prompt("Wrong value, please enter a value between "+min+" and "+max+" with a step of "+step+" :"); + if (new_value==null){return;} + } + } + } + + function changeSetting2(idsetting,new_value){ + + var xhr = getXMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var xmlResponse = xhr.responseXML.documentElement; + var rep = xmlResponse.getElementsByTagName("setting_to_change")[0]; + var idsetting_requested = parseInt(rep.getAttribute("setting_id")); + var acid_requested = parseInt(rep.getAttribute("acid")); + var name_drone = planes[seekIndex(acid_requested)]["name"]; + addMsgLog("request change setting "+ idsetting_requested +" for drone " + name_drone +" has been sent"); + // mise en place d'un timer d'accusé reception + if(acid_requested==planes[selected_index]["id"]){ + setting_change_timeout=setTimeout("callback_setting("+acid_requested+","+idsetting_requested+")",order_response_timeout); + setting_to_change_id = idsetting_requested; + } + } + }; + // on informe les autres clients de ne pas modifier le setting en cours (via pushlet) + p_publish('/client_action', 'login',usr_login,'action', 'lock', 'type_obj', 'setting', 'id_obj',idsetting,'webiddrone',selected_plane_id); + // + xhr.open("POST",ajax_url,true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + //Send the parameters to the servlet : + xhr.send("order=modif_setting&aircraft_id=" +selected_plane_id+"&setting_id="+idsetting+"&value="+new_value); + + } + +/* ************************* handle event orders from server ********************************************* */ + + function orderprocessing_waypoint(event){ + + var acft_id = parseInt(event.get('aircraftId')); + var wpt_id = parseInt(event.get('waypointId'))-1; // cf indentation des waypoint sous ivy + var lat = event.get('latitude'); + var lon = event.get('longitude'); + var alt = event.get('altitude'); + var name=name_from_id(acft_id); + //alert('drone=' +name+' wpt = '+wpt_id); + if ((wpt_id>=0)&&(acft_id==selected_plane_id)) { + //alert('drone=' +name+' wpt = '+wpt_id); + if (waypoint_modif[wpt_id]!=null) + { + addMsgLog('waypoint ' + wpt_id+' for drone '+name+ ' has been moved to '+lat+"//"+lon+' !'); + clearTimeout(waypoint_modif[wpt_id].timer) + waypoint_modif[wpt_id] = null; + DOMImplementation("upload/"+planes[selected_index]["id"]+"/flight_plan.xml",fplDisplay); + // inform other web client that waypoint can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'waypoint', 'id_obj',wpt_id,'webiddrone',acft_id); + } + } + //document.getElementById("info").innerHTML='waypoint' + wpt_id+' for drone '+name+ ' has been moved !'; + //addMsgLog('waypoint' + wpt_id+' for drone '+name+ ' has been moved !'); + //alert('
    waypoint' + wpt_id+' for drone '+name+ ' has been moved !'); + } + + function orderprocessing_jump2block(event) { + var acft_id = event.get('aircraftId'); + var current_block_id = event.get('currentBlockId'); + if (acft_id==selected_plane_id){ + /// maj de l'affichage fpl + var name_block=blocks[current_block_id]["name"]; + var name_drone=name_from_id(acft_id); + clearTimeout(block_jump_timeout); + active_block_id = current_block_id; + active_block_name =name_block; + // inform other web client that block can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'block', 'id_obj',current_block_id,'webiddrone',acft_id); + addMsgLog('drone '+ name_drone + ' has jump to block '+ name_block +' !'); + DOMImplementation("upload/"+planes[selected_index]["id"]+"/flight_plan.xml",fplDisplay); + } + } + + function orderprocessing_setting(event) { + var acft_id = event.get('aircraftId'); + var setting_id = parseInt(event.get('settingId')); + var value = event.get('settingValue'); + if ((acft_id==selected_plane_id)&&(setting_to_change_id==setting_id)){ + clearTimeout(setting_change_timeout); + setting_to_change_id = -1; // reset + var name=name_from_id(acft_id); + //DOMImplementation("upload/"+planes[selected_index]["id"]+"/settings.xml",settingsDisplay); + selected_plane_update(acft_id); + addMsgLog('setting ' + setting_id +' for drone '+ name + ' has been changed to value '+ value +' !'); + // inform other web client that block can be changed + p_publish('/client_action', 'login',usr_login,'action', 'unlock', 'type_obj', 'setting', 'id_obj',setting_id,'webiddrone',acft_id); + } + } + + + function orderprocessing_planedie(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + var name=name_from_id(acft_id); + //document.getElementById('info').innerHTML='drone ' + name+' is not alive !'; + addMsgLog('drone ' + name+' is not alive !'); + var drone_index = seekIndex(acft_id); + if(drone_index!=-1) + { + droneStateDieEvent[drone_index] = setTimeout ( "droneDieCallback("+acft_id+")", dieEventTimeoutTime ); + // on grise l'aircraft sur l'interface + } + } + + function orderprocessing_planeressurect(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + var name=name_from_id(acft_id); + //document.getElementById('info').innerHTML='drone ' +name+' has been resurrected !'; + addMsgLog('drone ' +name+' has been resurrected !'); + var drone_index = seekIndex(acft_id); + if(drone_index!=-1) + { + clearTimeout ( droneStateDieEvent[drone_index] ); + // on remet l'aircraft en couleur + } + } + + function orderprocessing_newplane(event){ + var acft_id = event.get('aircraftId'); + var order_string = event.get('order'); + var name= event.get('aircraftName'); + //document.getElementById('info').innerHTML='drone ' +name+' has been connected !'; + addMsgLog('drone ' +name+' has been connected !'); + } + + + function orderprocessing_planekilled(event){ + var acft_id = event.get('aircraftId'); + var name=name_from_id(acft_id); + addMsgLog("drone " + name + " deconnection caused by death of ivy bus..."); + //document.getElementById('info').innerHTML="drone " + name + " deconnection caused by death of ivy bus..."; + // remove drone...markers.... + removeDroneDisplay(acft_id); + } + + function orderprocessing_csv_settings(event){ + var acft_id = event.get('aircraftId'); + var csv = event.get('csv'); + var index_drone = seekIndex(acft_id); + var name=name_from_id(acft_id); + if (index_drone!=-1) { + planes[index_drone]["csv"]= csv; + //addMsgLog("settings updated for drone " + name); + if(index_drone==selected_index) + { + DOMImplementation("upload/"+planes[selected_index]["id"]+"/settings.xml",settingsDisplay); + } + } + } + + function orderprocessing_chat(event){ + } + + function createLock(id_drone,typ_obj,id_obj,login){ + this.id_drone = id_drone; + this.type_object = typ_obj; + this.id_object = id_obj; + this.request_login = login; + this.lockmsg = function() + {return ("user "+this.request_login+ " has locked "+this.type_object +" " +this.id_object);} + this.unlockmsg = function() + {return ("user "+this.request_login+ " has unlocked "+this.type_object +" " +this.id_object);} + } + + var external_waypoint_lock = new Array(); + var external_block_lock = new Array(); + var external_setting_lock = new Array(); + // set or remove a lock to prevent user to change sthg taht is to be changed by another user + function orderprocessing_client_action(event){ + var rqst_login = event.get('login'); + var rqst_action = event.get('action'); + var rqst_obj_type = event.get('type_obj'); + var rqst_obj_id = event.get('id_obj'); + var rqst_id_drone = event.get('webiddrone'); + if (rqst_action=='lock'){ + var lock_obj = new createLock(rqst_id_drone,rqst_obj_type,rqst_obj_id,rqst_login); + if (rqst_obj_type=='waypoint') {external_waypoint_lock.push(lock_obj);} + else if (rqst_obj_type=='block') {external_block_lock.push(lock_obj);} + else if (rqst_obj_type=='setting') {external_setting_lock.push(lock_obj);} + addMsgLog(lock_obj.lockmsg()); + } + else if (rqst_action =='unlock'){ + var trouve = false; + var cur_id_obj=-1; + var i=0; + if (rqst_obj_type=='waypoint') + { + while((!trouve)&&(i + + + + + + + +

    +-------- Paparazzi On the Web ! -------- +
    +Welcome, +<% + String log = (String) session.getAttribute("login"); + if(log != null) { + out.print(log + "!"); + String rights = (String) session.getAttribute("rights"); + if (rights.equals("admin")){ + out.println(" | admin page"); + } + out.println(" | \"pull\" mode"); + out.println(" | log out"); + } + else + { + out.println(""); + } + +%> + +
    +
    + +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +

    + +
    +

    +
    +
    + +
    loading...
    + +
    + +
    +loading... +
    + + + +
    +
    Flight Parameters
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    altitude (m)0
    height0 m
    battery level0V
    speed0 km/h
    GPS statusOFF
    vertical speed0 m/s
    engine power0%
    +
    + + + + +
    +
    + +
    +
    +
    +
    +
      +
    +
    +
    +
    +
    + +
    +
    no news..
    +
    + + + +
    + + + + + +<% + out.println(""); +%> + + +<%-- --%> + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/META-INF/MANIFEST.MF b/sw/in_progress/pow/pow/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..5e9495128c --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/pushlet.properties b/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/pushlet.properties new file mode 100644 index 0000000000..ba656e138f --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/pushlet.properties @@ -0,0 +1,128 @@ +# +# Pushlet configuration. +# Place this file in the CLASSPATH (e.g. WEB-INF/classes) or directly under WEB-INF. +# +# $Id: pushlet.properties,v 1.13 2007/12/07 12:57:40 justb Exp $ +# + +# +# +# +config.version=1.0.2 + +# +# CLASS FACTORY SPECIFICATION +# +# Change these if you want to override any of the core classes +# within the Pushlet framework with your own custom classes. +# +# Examples: +# - custom SessionManager for authorisation +# - maintain lists of active subjects (topics) +# - send events on subscription +# - plug in custom logging like log4j +# Note that you must maintain the semantics of each class ! +# Below are the default properties for the core classes. +controller.class=nl.justobjects.pushlet.core.Controller +dispatcher.class=nl.justobjects.pushlet.core.Dispatcher +logger.class=nl.justobjects.pushlet.util.Log4jLogger +# logger.class=nl.justobjects.pushlet.util.DefaultLogger +sessionmanager.class=nl.justobjects.pushlet.core.SessionManager +session.class=nl.justobjects.pushlet.core.Session +subscriber.class=nl.justobjects.pushlet.core.Subscriber +subscription.class=nl.justobjects.pushlet.core.Subscription + +# sessionmanager.maxsessions=200 + +# +# DISPATCHER +# + + +# TODO: allow properties to be maintained in +# a user dir +# config.redirect=/etc/pushlet.properties + +# +# LOGGING +# + +# log level (trace(6) debug(5) info (4), warn(3), error(2), fatal(1)) +# default is info(4) +log.level=4 + +# +# LOCAL EVENT SOURCES +# + +# should local sources be loaded ? +sources.activate=true + +# +# SESSION +# + + +# algoritm to generate session key: +# values: "randomstring" (default) or "uuid". +# session.id.generation=uuid +session.id.generation=randomstring + +# length of generated session key when using "randomstring" generation +session.id.size=10 + +# Overall session lease time in minutes +# Mainly used for clients that do not perform +# listening, e.g. when publishing only. +session.timeout.mins=5 + +# +# EVENT QUEUE +# +# Properties for per-client data event queue + +# Size for +queue.size=24 +queue.read.timeout.millis=20000 +queue.write.timeout.millis=20 + +# +# LISTENING MODE +# + +# You may force all clients to use pull mode +# for scalability +listen.force.pull.all=false + +# +# Comma-separated list of User Agent substrings. +# Force these browsers to use pull mode, since they +# don't support JS streaming, matching is done using +# String.indexOf() with lowercased agent strings +# use multiple criteria with &. +# +listen.force.pull.agents=safari + +# +# PULL MODE +# + +# time server should wait on refresing pull client +pull.refresh.timeout.millis=45000 + +# minimum/maximum wait time client should wait before refreshing +# server provides a random time between these values +pull.refresh.wait.min.millis=2000 +pull.refresh.wait.max.millis=6000 + +# +# POLL MODE +# + +# time server should wait on refresing poll client +poll.refresh.timeout.millis=60000 + +# minimum/maximum wait time client should wait before refreshing +# server provides a random time between these values +poll.refresh.wait.min.millis=6000 +poll.refresh.wait.max.millis=10000 diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/sources.properties b/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/sources.properties new file mode 100644 index 0000000000..c51dc942e3 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/WEB-INF/classes/sources.properties @@ -0,0 +1,28 @@ +# +# Properties file for EventSource objects to be instantiated. +# +# Place this file in the CLASSPATH (e.g. WEB-INF/classes) or directly under WEB-INF. +# +# $Id: sources.properties,v 1.2 2007/11/10 14:12:16 justb Exp $ +# +# Each EventSource is defined as = +# 1. should be unique within this file but may be any name +# 2. is the full class name +# +# +# Define Pull Sources here. These classes must be derived from +# nl.justobjects.pushlet.core.EventPullSource +# Inner classes are separated with a $ sign from the outer class. +#source1=nl.justobjects.pushlet.test.TestEventPullSources$TemperatureEventPullSource +#source2=nl.justobjects.pushlet.test.TestEventPullSources$SystemStatusEventPullSource +#source3=nl.justobjects.pushlet.test.TestEventPullSources$PushletStatusEventPullSource +#source4=nl.justobjects.pushlet.test.TestEventPullSources$AEXStocksEventPullSource +#source5=nl.justobjects.pushlet.test.TestEventPullSources$WebPresentationEventPullSource +#source6=nl.justobjects.pushlet.test.TestEventPullSources$PingEventPullSource + +source1=pow.Serveur$IvyEventSource + +# TO BE DONE IN NEXT VERSION +# define Push Sources here. These must implement the interface +# nl.justobjects.pushlet.core.EventSource + diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-codec-1.4.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-codec-1.4.jar new file mode 100644 index 0000000000..458d432da8 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-codec-1.4.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar new file mode 100644 index 0000000000..aa209b3887 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar new file mode 100644 index 0000000000..7c59774aed Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-io-1.4.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-io-1.4.jar new file mode 100644 index 0000000000..133dc6cb35 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-io-1.4.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar new file mode 100644 index 0000000000..8758a96b70 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/jdom.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/jdom.jar new file mode 100644 index 0000000000..65a1b3f737 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/jdom.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/pushlet.jar b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/pushlet.jar new file mode 100644 index 0000000000..6dc1c22e21 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/WEB-INF/lib/pushlet.jar differ diff --git a/sw/in_progress/pow/pow/WebContent/WEB-INF/web.xml b/sw/in_progress/pow/pow/WebContent/WEB-INF/web.xml new file mode 100644 index 0000000000..9bd50e4b01 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/WEB-INF/web.xml @@ -0,0 +1,53 @@ + + + TestServletPow + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + + + Greeting + Greeting + pow.Greeting + + + Greeting + /Greeting.srv + + + + Pushlet + Pushlet + nl.justobjects.pushlet.servlet.Pushlet + 1 + + + Pushlet + /pushlet.srv + + + + Ivy2TomcatHttpServer + Ivy2TomcatHttpServer + pow.Ivy2TomcatHttpServer + + + Ivy2TomcatHttpServer + /Ivy2TomcatHttpServer.srv + + + + ajaxRqst + ajaxRqst + pow.ajaxRqst + + + ajaxRqst + /ajaxRqst.srv + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/admin.jsp b/sw/in_progress/pow/pow/WebContent/admin.jsp new file mode 100644 index 0000000000..94657a9011 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/admin.jsp @@ -0,0 +1,790 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@page import="java.util.*,pow.UserTab,pow.User,javax.xml.parsers.*, org.w3c.dom.*,org.xml.sax.*,java.io.*" %> +<% +// recuperation des données sur le serveur + String default_folder = this.getServletContext().getRealPath(""); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + Iterator itr=logTab.getLoginIterator(); + // + UserTab logIvyTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + Iterator itrIvy=logIvyTab.getLoginIterator(); + // lecture liste des noms de drones ds immat.xml + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + // création d'un constructeur de documents + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // lecture du contenu d'un fichier XML avec DOM + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + + +%> + + + + + + + +Administration page + + + + + + + + + + + + + + + +
    +
    +
    + +
    +
    +
    Select an item + + + + + + + + +
    + +
    +
    +
    +
    + + + + + + + + + + + +
    +
    +
    +
    +
    + Add or Remove a name among drones which may be controlled by users + + + + + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + Add or Remove an Ivy User + + + + + + +
    + +
    +
    +
    +
    + + +
    + +
    +
    + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/conf/immat.xml b/sw/in_progress/pow/pow/WebContent/conf/immat.xml new file mode 100644 index 0000000000..42965d30c1 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/conf/immat.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sw/in_progress/pow/pow/WebContent/conf/pow.conf b/sw/in_progress/pow/pow/WebContent/conf/pow.conf new file mode 100644 index 0000000000..3fc60b177c --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/conf/pow.conf @@ -0,0 +1,41 @@ +########################################## +########## PAPARAZZI ON THE WEB ########## +########################################## + +#Beginning of configuration file : + +###################################### + +# The port on which msg from ivy are sended to web server + + +# The port in which msg from web server are sended to ivy + + +# The size of the udp datagram (1024 recommanded) + + +# The name of the dataBase + + +# The userName used in the dataBase on the server + + +# The password of the dataBase on the server + + +# The timeout of the udp connection (in millisecond) + + +# The location of the flightPlan Repertory (finish it with "/") + + +# The administrator's login of POW WEB site + + +# The administrator's mail of POW WEB site + + + +###################################### + diff --git a/sw/in_progress/pow/pow/WebContent/help.jsp b/sw/in_progress/pow/pow/WebContent/help.jsp new file mode 100644 index 0000000000..dab613dc65 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/help.jsp @@ -0,0 +1,55 @@ +<%@page import="pow.ConfJSP" %> + + + + + + Welcome to Paparazzi On the Web + + + + + + + + + +

    Welcome on Paparazzi On the Web help page.

    +

    This page is here to help you to use the Paparazzi On the Web (POW) application. POW is a part of Paparazzi which is a open-project of civil UAV control. With Paparazzi On the Web, you are able to observe and eventually control the UAVs of the system Paparazzi thanks to a browser with your internet connexion. To learn more about Paparazzi project, click here.

    +

    Paparazzi On the Web is optimised for Firefox browser. If you want to have a better performance, you can dowload Firefox here.

    +

    Start page

    +

    If you have a login and a password on Paparazzi On the Web, you can use them to enter the application. Else, click on enter as a guest.

    + +

    Main page

    +

    You are now on Paparazzi On the Web main page. You can see several boxes. We will describe all those boxes and show you the interactions you can have with them.

    + +

    Choose an aircraft

    +

    Here you can select the aircraft you want to observe or control. Click on the arrow to see the list of the aircrafts that are available. Click on the aircraft you want to interacte with.

    +

    You can also choose to activate or desactivate tracking. When tracking is activated, the map is always centered on the selected aircraft.

    + + + +

    The map

    +

    On the map, you can see all the aircrafts that are available. If tracking is activated, the map will be centered on the selected aircraft. There are also red lozenges which are the waypoints of the selected UAV. If you are autentified on Paparazzi On the Web and if your profile gives you the authorization, you can move those waypoints with drag and drop.

    + +

    The flight plan

    +

    Through this box, you can obtain some informations on the flight plan that is followed by the selected plane. If you move your cursor on the informations tab, you obtain informations on the flightplan. If you put your cursor on the "active block" tab, you can see the list of the flight plan blocks that the plane can follow. The active block is in red. If you are authentified and if you have the authorization, you can change the active block by clicking on its name. The waypoints tab gives you informations on the different waypoints. If you are authentified and if you have the authorization, you can move those waypoints by clicking on "move waypoint". In this case, a new windows is openned where you indicate where you want to move the waypoint. +You can also move a waypoint by dragging the icon on the map to its new position.

    + +

    The flight parameters

    +

    This box displays the flight parameters of the selected aircraft. When a value is out of its normal range, it becomes red.

    + +

    The settings

    +

    In this box you can, if you are allowed to control the selected aircraft, you change some settings of this aircraft by clicking on the name of the setting.

    + +

    Any problem ?

    +

    If you have any display problem, such as a ghost aircraft icon, or an aircraft that is not displayed in the aircrafts list, you might resolve it by reloading the page by pressing F5 key. +For any other problem, please inform +<%out.print(" +<%out.print(ConfJSP.getAdminMail()); %> +<%out.print("\">the administrator"); %>.

    +Click here to return to the homepage. + + + diff --git a/sw/in_progress/pow/pow/WebContent/idError.html b/sw/in_progress/pow/pow/WebContent/idError.html new file mode 100644 index 0000000000..a15edb3f6d --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/idError.html @@ -0,0 +1,14 @@ + + + + + Welcome to Paparazzi On the Web + + + + + +

    Sorry, an error occured during your identification. Click here to return on the homepage.

    + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/img/base.gif b/sw/in_progress/pow/pow/WebContent/img/base.gif new file mode 100644 index 0000000000..9ac0b117b0 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/base.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/cd.gif b/sw/in_progress/pow/pow/WebContent/img/cd.gif new file mode 100644 index 0000000000..7503819404 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/cd.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/empty.gif b/sw/in_progress/pow/pow/WebContent/img/empty.gif new file mode 100644 index 0000000000..b5cf52378f Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/empty.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/folder.gif b/sw/in_progress/pow/pow/WebContent/img/folder.gif new file mode 100644 index 0000000000..eb129763dc Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/folder.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/folderopen.gif b/sw/in_progress/pow/pow/WebContent/img/folderopen.gif new file mode 100644 index 0000000000..c5c31102d5 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/folderopen.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/globe.gif b/sw/in_progress/pow/pow/WebContent/img/globe.gif new file mode 100644 index 0000000000..57123d0e69 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/globe.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/imgfolder.gif b/sw/in_progress/pow/pow/WebContent/img/imgfolder.gif new file mode 100644 index 0000000000..e6d880347f Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/imgfolder.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/join.gif b/sw/in_progress/pow/pow/WebContent/img/join.gif new file mode 100644 index 0000000000..34dd47610a Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/join.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/joinbottom.gif b/sw/in_progress/pow/pow/WebContent/img/joinbottom.gif new file mode 100644 index 0000000000..48b81c80a9 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/joinbottom.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/line.gif b/sw/in_progress/pow/pow/WebContent/img/line.gif new file mode 100644 index 0000000000..1a259eea00 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/line.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/minus.gif b/sw/in_progress/pow/pow/WebContent/img/minus.gif new file mode 100644 index 0000000000..3d212a97ae Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/minus.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/minusbottom.gif b/sw/in_progress/pow/pow/WebContent/img/minusbottom.gif new file mode 100644 index 0000000000..dc3198be27 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/minusbottom.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/musicfolder.gif b/sw/in_progress/pow/pow/WebContent/img/musicfolder.gif new file mode 100644 index 0000000000..f620789feb Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/musicfolder.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/nolines_minus.gif b/sw/in_progress/pow/pow/WebContent/img/nolines_minus.gif new file mode 100644 index 0000000000..2592ac20f3 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/nolines_minus.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/nolines_plus.gif b/sw/in_progress/pow/pow/WebContent/img/nolines_plus.gif new file mode 100644 index 0000000000..f258ce211a Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/nolines_plus.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/page.gif b/sw/in_progress/pow/pow/WebContent/img/page.gif new file mode 100644 index 0000000000..42d7318c5d Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/page.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/plus.gif b/sw/in_progress/pow/pow/WebContent/img/plus.gif new file mode 100644 index 0000000000..b2c997233b Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/plus.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/plusbottom.gif b/sw/in_progress/pow/pow/WebContent/img/plusbottom.gif new file mode 100644 index 0000000000..b5671d891a Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/plusbottom.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/question.gif b/sw/in_progress/pow/pow/WebContent/img/question.gif new file mode 100644 index 0000000000..dd4e685078 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/question.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/img/trash.gif b/sw/in_progress/pow/pow/WebContent/img/trash.gif new file mode 100644 index 0000000000..cfa0f000e1 Binary files /dev/null and b/sw/in_progress/pow/pow/WebContent/img/trash.gif differ diff --git a/sw/in_progress/pow/pow/WebContent/index.jsp b/sw/in_progress/pow/pow/WebContent/index.jsp new file mode 100644 index 0000000000..aad5c605b5 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/index.jsp @@ -0,0 +1,69 @@ + + + + + Welcome to Paparazzi On the Web + + + + + + + + + + + +

    Welcome to Paparazzi On The Web !

    + +

    + +

    +
    +
    +

    Login :

    +

    Password :

    + +
    +

    + + +
    +

    +
    +

    or

    + +

    +

    + +
    +

    +help ? + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/js/DOMImplementation.js b/sw/in_progress/pow/pow/WebContent/js/DOMImplementation.js new file mode 100644 index 0000000000..5e94107932 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/DOMImplementation.js @@ -0,0 +1,24 @@ +function DOMImplementation(sUrl, fCallback) { + var dom; + if(window.ActiveXObject) { + dom = new ActiveXObject("Microsoft.XMLDOM"); + dom.onreadystatechange = function() { + if(dom.readyState == 4) { + //alert("win "+sUrl+" loaded"); + fCallback(dom); + } + }; + } + else if(document.implementation && document.implementation.createDocument) { + dom = document.implementation.createDocument("", "", null); + dom.onload = function() { + //alert("other "+sUrl+" loaded"); + fCallback(dom); + } + } + else { + alert("Votre navigateur ne gère pas l'importation de fichiers XML"); + return; + } + dom.load(sUrl); +} diff --git a/sw/in_progress/pow/pow/WebContent/js/XHR_object.js b/sw/in_progress/pow/pow/WebContent/js/XHR_object.js new file mode 100644 index 0000000000..544a2b1a2e --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/XHR_object.js @@ -0,0 +1,20 @@ +function getXMLHttpRequest() { + var xhr = null; + + if (window.XMLHttpRequest || window.ActiveXObject) { + if (window.ActiveXObject) { + try { + xhr = new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + xhr = new ActiveXObject("Microsoft.XMLHTTP"); + } + } else { + xhr = new XMLHttpRequest(); + } + } else { + alert("Votre navigateur ne supporte pas l'objet XMLHTTPRequest..."); + return null; + } + + return xhr; +} diff --git a/sw/in_progress/pow/pow/WebContent/js/browserdetect.js b/sw/in_progress/pow/pow/WebContent/js/browserdetect.js new file mode 100644 index 0000000000..1e0b64da62 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/browserdetect.js @@ -0,0 +1,97 @@ +// Browser Detect Lite v2.1.4 +// http://www.dithered.com/javascript/browser_detect/index.html +// modified by Chris Nott (chris@NOSPAMdithered.com - remove NOSPAM) + + +function BrowserDetectLite() { + var ua = navigator.userAgent.toLowerCase(); + + // browser name + this.isGecko = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1); + this.isMozilla = (this.isGecko && ua.indexOf('gecko/') + 14 == ua.length); + this.isNS = ( (this.isGecko) ? (ua.indexOf('netscape') != -1) : ( (ua.indexOf('mozilla') != -1) && (ua.indexOf('spoofer') == -1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('opera') == -1) && (ua.indexOf('webtv') == -1) && (ua.indexOf('hotjava') == -1) ) ); + this.isIE = ( (ua.indexOf('msie') != -1) && (ua.indexOf('opera') == -1) && (ua.indexOf('webtv') == -1) ); + this.isSafari = (ua.indexOf('safari') != - 1); + this.isOpera = (ua.indexOf('opera') != -1); + this.isKonqueror = (ua.indexOf('konqueror') != -1 && !this.isSafari); + this.isIcab = (ua.indexOf('icab') != -1); + this.isAol = (ua.indexOf('aol') != -1); + + // spoofing and compatible browsers + this.isIECompatible = ( (ua.indexOf('msie') != -1) && !this.isIE); + this.isNSCompatible = ( (ua.indexOf('mozilla') != -1) && !this.isNS && !this.isMozilla); + + // browser version + this.versionMinor = parseFloat(navigator.appVersion); + + // correct version number + if (this.isNS && this.isGecko) { + this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('/') + 1 ) ); + } + else if (this.isIE && this.versionMinor >= 4) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) ); + } + else if (this.isMozilla) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) ); + } + else if (this.isSafari) { + this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('/') + 1 ) ); + } + else if (this.isOpera) { + if (ua.indexOf('opera/') != -1) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera/') + 6 ) ); + } + else { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera ') + 6 ) ); + } + } + else if (this.isKonqueror) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('konqueror/') + 10 ) ); + } + else if (this.isIcab) { + if (ua.indexOf('icab/') != -1) { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab/') + 6 ) ); + } + else { + this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab ') + 6 ) ); + } + } + + this.versionMajor = parseInt(this.versionMinor); + this.geckoVersion = ( (this.isGecko) ? ua.substring( (ua.lastIndexOf('gecko/') + 6), (ua.lastIndexOf('gecko/') + 14) ) : -1 ); + + // dom support + this.isDOM1 = (document.getElementById); + this.isDOM2Event = (document.addEventListener && document.removeEventListener); + + // css compatibility mode + this.mode = document.compatMode ? document.compatMode : 'BackCompat'; + + // platform + this.isWin = (ua.indexOf('win') != -1); + this.isWin32 = (this.isWin && ( ua.indexOf('95') != -1 || ua.indexOf('98') != -1 || ua.indexOf('nt') != -1 || ua.indexOf('win32') != -1 || ua.indexOf('32bit') != -1 || ua.indexOf('xp') != -1) ); + this.isMac = (ua.indexOf('mac') != -1); + this.isUnix = (ua.indexOf('unix') != -1 || ua.indexOf('sunos') != -1 || ua.indexOf('bsd') != -1 || ua.indexOf('x11') != -1) + this.isLinux = (ua.indexOf('linux') != -1); + + // specific browser shortcuts + this.isNS4x = (this.isNS && this.versionMajor == 4); + this.isNS40x = (this.isNS4x && this.versionMinor < 4.5); + this.isNS47x = (this.isNS4x && this.versionMinor >= 4.7); + this.isNS4up = (this.isNS && this.versionMinor >= 4); + this.isNS6x = (this.isNS && this.versionMajor == 6); + this.isNS6up = (this.isNS && this.versionMajor >= 6); + this.isNS7x = (this.isNS && this.versionMajor == 7); + this.isNS7up = (this.isNS && this.versionMajor >= 7); + + this.isIE4x = (this.isIE && this.versionMajor == 4); + this.isIE4up = (this.isIE && this.versionMajor >= 4); + this.isIE5x = (this.isIE && this.versionMajor == 5); + this.isIE55 = (this.isIE && this.versionMinor == 5.5); + this.isIE5up = (this.isIE && this.versionMajor >= 5); + this.isIE6x = (this.isIE && this.versionMajor == 6); + this.isIE6up = (this.isIE && this.versionMajor >= 6); + + this.isIE4xMac = (this.isIE4x && this.isMac); +} +var browser = new BrowserDetectLite(); diff --git a/sw/in_progress/pow/pow/WebContent/js/dtree.js b/sw/in_progress/pow/pow/WebContent/js/dtree.js new file mode 100644 index 0000000000..266779206c --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/dtree.js @@ -0,0 +1,347 @@ +/*--------------------------------------------------| +| dTree 2.05 | www.destroydrop.com/javascript/tree/ | +|---------------------------------------------------| +| Copyright (c) 2002-2003 Geir Landrö | +| | +| This script can be used freely as long as all | +| copyright messages are intact. | +| | +| Updated: 17.04.2003 | +|--------------------------------------------------*/ + +// Node object +function Node(id, pid, name, url, title, target, icon, iconOpen, open) { + this.id = id; + this.pid = pid; + this.name = name; + this.url = url; + this.title = title; + this.target = target; + this.icon = icon; + this.iconOpen = iconOpen; + this._io = open || false; + this._is = false; + this._ls = false; + this._hc = false; + this._ai = 0; + this._p; +}; + +// Tree object +function dTree(objName) { + this.config = { + target : null, + folderLinks : true, + useSelection : true, + useCookies : true, + useLines : true, + useIcons : true, + useStatusText : false, + closeSameLevel : false, + inOrder : false + } + this.icon = { + root : 'img/base.gif', + folder : 'img/folder.gif', + folderOpen : 'img/folderopen.gif', + node : 'img/page.gif', + empty : 'img/empty.gif', + line : 'img/line.gif', + join : 'img/join.gif', + joinBottom : 'img/joinbottom.gif', + plus : 'img/plus.gif', + plusBottom : 'img/plusbottom.gif', + minus : 'img/minus.gif', + minusBottom : 'img/minusbottom.gif', + nlPlus : 'img/nolines_plus.gif', + nlMinus : 'img/nolines_minus.gif' + }; + this.obj = objName; + this.aNodes = []; + this.aIndent = []; + this.root = new Node(-1); + this.selectedNode = null; + this.selectedFound = false; + this.completed = false; +}; + +// Adds a new node to the node array +dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) { + this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open); +}; + +// Open/close all nodes +dTree.prototype.openAll = function() { + this.oAll(true); +}; +dTree.prototype.closeAll = function() { + this.oAll(false); +}; + +// Outputs the tree to the page +dTree.prototype.toString = function() { + var str = '
    \n'; + if (document.getElementById) { + if (this.config.useCookies) this.selectedNode = this.getSelected(); + str += this.addNode(this.root); + } else str += 'Browser not supported.'; + str += '
    '; + if (!this.selectedFound) this.selectedNode = null; + this.completed = true; + return str; +}; + +// Creates the tree structure +dTree.prototype.addNode = function(pNode) { + var str = ''; + var n=0; + if (this.config.inOrder) n = pNode._ai; + for (n; n'; + } + if (node.url) { + str += ''; + str += node.name; + if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += ''; + str += ''; + if (node._hc) { + str += '
    '; + str += this.addNode(node); + str += '
    '; + } + this.aIndent.pop(); + return str; +}; + +// Adds the empty and line icons +dTree.prototype.indent = function(node, nodeId) { + var str = ''; + if (this.root.id != node.pid) { + for (var n=0; n'; + (node._ls) ? this.aIndent.push(0) : this.aIndent.push(1); + if (node._hc) { + str += ''; + } else str += ''; + } + return str; +}; + +// Checks if a node has any children and if it is the last sibling +dTree.prototype.setCS = function(node) { + var lastId; + for (var n=0; n)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
    a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

    ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
    ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
    ","
    "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
    ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
    "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/sw/in_progress/pow/pow/WebContent/js/jquery-ui-1.8.2.custom.min.js b/sw/in_progress/pow/pow/WebContent/js/jquery-ui-1.8.2.custom.min.js new file mode 100644 index 0000000000..c11e844f9b --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/jquery-ui-1.8.2.custom.min.js @@ -0,0 +1,1012 @@ +/*! + * jQuery UI 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + */ +(function(c){c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.2",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=0)&&c(a).is(":focusable")}})}})(jQuery); +;/*! + * jQuery UI Widget 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Widget + */ +(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype= +b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g= +b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create(); +this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f, +h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a= +b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery); +;/*! + * jQuery UI Mouse 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&& +this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault(); +return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&& +this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX- +a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Position + */ +(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h= +0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+= +g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k, +elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"? +-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position= +"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top- +this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions(); +d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis|| +this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element, +b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this== +a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]|| +0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top- +(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment== +"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&& +a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"), +10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], +this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft(): +f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.leftthis.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?e:!(e-this.offset.click.left').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options; +if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!= +"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>=i&& +e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()}; +if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(), +e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset= +this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio: +this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize", +b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height; +g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop", +b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top= +a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidthb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height, +l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+ +a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this, +arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable, +{version:"1.8.2"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)}); +else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&& +d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a= +d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset; +var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left: +a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top- +e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition, +g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b= +d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height= +e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +; +/* + * jQuery UI Selectable 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function($) { + +$.widget("ui.selectable", $.ui.mouse, { + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' + }, + _create: function() { + var self = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(self.options.filter, self.element[0]); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("
    "); + }, + + destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled") + .removeData("selectable") + .unbind(".selectable"); + this._mouseDestroy(); + + return this; + }, + + _mouseStart: function(event) { + var self = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "z-index": 100, + "position": "absolute", + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + self._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var self = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == self.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if (event.metaKey && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var self = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + self._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + self._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +$.extend($.ui.selectable, { + version: "1.8.2" +}); + +})(jQuery); +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
    ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting"); +b.unselecting=true;f._trigger("unselecting",c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f= +this;this.dragged=true;if(!this.options.disabled){var d=this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this, +arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem= +c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset, +{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment(); +if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start", +a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute"); +if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a, +c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]== +document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate", +null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem): +d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c}, +_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a= +this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)? +h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"), +b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)? +i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement, +c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height= +this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()- +parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0], +this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b= +1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update", +g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity", +this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset"); +this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role", +"tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a= +this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion"); +this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height", +"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target}, +a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0, +b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d= +this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected); +a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]), +toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j, +duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion, +{version:"1.8.2",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0], +h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"}, +a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,c=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(d){var b=e.ui.keyCode;switch(d.keyCode){case b.PAGE_UP:a._move("previousPage",d);break;case b.PAGE_DOWN:a._move("nextPage",d);break;case b.UP:a._move("previous",d);d.preventDefault(); +break;case b.DOWN:a._move("next",d);d.preventDefault();break;case b.ENTER:case b.NUMPAD_ENTER:a.menu.active&&d.preventDefault();case b.TAB:if(!a.menu.active)return;a.menu.select(d);break;case b.ESCAPE:a.element.val(a.term);a.close(d);break;case b.LEFT:case b.RIGHT:case b.SHIFT:case b.CONTROL:case b.ALT:case b.COMMAND:case b.COMMAND_RIGHT:case b.INSERT:case b.CAPS_LOCK:case b.END:case b.HOME:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,d)},a.options.delay); +break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete",function(d){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(d);a._change(d)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("
      ").addClass("ui-autocomplete").appendTo("body",c).mousedown(function(){setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(d,b){b=b.item.data("item.autocomplete"); +false!==a._trigger("focus",null,{item:b})&&/^key/.test(d.originalEvent.type)&&a.element.val(b.value)},selected:function(d,b){b=b.item.data("item.autocomplete");false!==a._trigger("select",d,{item:b})&&a.element.val(b.value);a.close(d);d=a.previous;if(a.element[0]!==c.activeElement){a.element.focus();a.previous=d}a.selectedItem=b},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()}, +destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,c;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(d,b){b(e.ui.autocomplete.filter(a,d.term))}}else if(typeof this.options.source=== +"string"){c=this.options.source;this.source=function(d,b){e.getJSON(c,d,b)}}else this.source=this.options.source},search:function(a,c){a=a!=null?a:this.element.val();if(a.length").data("item.autocomplete", +c).append(""+c.label+"").appendTo(a)},_move:function(a,c){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](c);else this.search(null,c)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,c){var d=new RegExp(e.ui.autocomplete.escapeRegex(c), +"i");return e.grep(a,function(b){return d.test(b.label||b.value||b)})}})})(jQuery); +(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(e(c.target).closest(".ui-menu-item a").length){c.preventDefault();a.select(c)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(c){a.activate(c,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,c){this.deactivate();if(this.hasScroll()){var d=c.offset().top-this.element.offset().top,b=this.element.attr("scrollTop"),f=this.element.height();if(d<0)this.element.attr("scrollTop",b+d);else d>f&&this.element.attr("scrollTop",b+d-f+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,c,d){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(d,a):this.activate(d,this.element.children(c))}else this.activate(d,this.element.children(c))},nextPage:function(a){if(this.hasScroll())if(!this.active|| +this.last())this.activate(a,this.element.children(":first"));else{var c=this.active.offset().top,d=this.element.height(),b=this.element.children("li").filter(function(){var f=e(this).offset().top-c-d+e(this).height();return f<10&&f>-10});b.length||(b=this.element.children(":last"));this.activate(a,b)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last")); +else{var c=this.active.offset().top,d=this.element.height();result=this.element.children("li").filter(function(){var b=e(this).offset().top-c+d-e(this).height();return b<10&&b>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()
      ").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("");d.secondary&&b.append("");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon"); +this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()}, +destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
      ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
      ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index", +c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("
      ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a, +function(g,f){g=c('').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging"); +b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position"); +a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop", +f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]= +g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a, +b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break; +case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title", +d.uiDialogTitlebar).html(""+(b||" "));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight", +this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.2",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&& +c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("
      ").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&& +b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight, +document.body.offsetHeight);return a");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("
      ");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("").appendTo(this.element).addClass("ui-slider-handle"); +if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur(); +else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e= +false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");g=a._start(c,f);if(g===false)return}break}i=a.options.step;g=a.options.values&&a.options.values.length?(h=a.values(f)):(h=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(g+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(g-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g=== +a._valueMax())return;h=a._trimAlignValue(g+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===a._valueMin())return;h=a._trimAlignValue(g-i);break}a._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"); +this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,g,h,i;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:a.pageX,y:a.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(b.range===true&&this.values(1)===b.min){i+=1;g=d(this.handles[i])}if(this._start(a, +i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();b=g.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-g.width()/2,top:a.pageY-b.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(a,i,e);return this._animateOff=true},_mouseStart:function(){return true}, +_mouseDrag:function(a){var b=this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b; +if(this.orientation==="horizontal"){b=this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value= +this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;fthis._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({width:f- +h+"%"},{queue:false,duration:b.animate})}else{if(l===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:b.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.2"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d){function s(){return++u}function v(){return++w}var u=0,w=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
      ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:'
    • #{label}
    • '},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+s()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+v());return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c= +d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]|| +(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass": +"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs", +function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show", +null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs", +function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g, +j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs", +function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this, +"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs", +true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide"); +this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1=c?--h:h});this._tabify();this._trigger("remove", +null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this}, +select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing"); +if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}}, +abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.2"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate= +function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k')}function E(a,b){d.extend(a, +b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.2"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]= +f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('
      ')}}, +_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&& +b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f== +""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a, +c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b), +true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor== +Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]); +d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}}, +_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false; +for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target|| +a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a); +d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&& +d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f, +h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover"); +this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover"); +this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"); +a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(), +k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"]; +a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val(): +"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&& +!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth; +b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]); +a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a, +"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")|| +this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null; +for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c, +k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c? +c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+112?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear|| +a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m, +g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+r+"":f?"":''+r+"";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
      '+(c?h:"")+(this._isInRange(a,r)?'":"")+(c?"":h)+"
      ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='
      '+(/all|left/.test(t)&&C==0?c? +f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'
      ';var A=k?'":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="=5?' class="ui-datepicker-week-end"':"")+'>'+s[q]+""}x+=A+"";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N";var O=!k?"":'";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&qo;O+='";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+""}g++;if(g>11){g=0;m++}x+="
      '+this._get(a,"weekHeader")+"
      '+this._get(a,"calculateWeek")(q)+""+(B&&!w?" ":I?''+q.getDate()+ +"":''+q.getDate()+"")+"
      "+(l?""+(i[0]>0&&D==i[1]-1?'
      ':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='
      ',o="";if(h||!k)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(j+=o+(h||!(k&&l)?" ":""));if(h||!l)j+=''+c+"";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b, +i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?" ":"")+o;j+="
      ";return j},_adjustInstDate:function(a,b,c){var e= +a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a, +"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a); +c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a, +"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker= +function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b)); +return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.2";window["DP_jQuery_"+y]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("
      ").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(athis._valueMax())a=this._valueMax();return a}, +_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.2"})})(jQuery); +;/* + * jQuery UI Effects 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit= +true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189, +183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255, +165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u, +i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a? +f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.2",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); +c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| +typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this, +arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c, +a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+ +b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2, +10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)* +a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* +f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.2 + * + * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/js/menu1.js b/sw/in_progress/pow/pow/WebContent/js/menu1.js new file mode 100644 index 0000000000..5f87f66421 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/menu1.js @@ -0,0 +1,155 @@ +/* +Author : bieler batiste +Company : doSimple : http://www.dosimple.ch +send me a mail for more informations : faden@PASDEPOURRIELaltern.org - remove ( PASDEPOURRIEL ) + +Short javascript function to create and handle a CSS navigation menu + +Copyright (C) 2004 Bieler Batiste + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// the timeout for the menu +var timeout = 100; + +// not very clean but simple +// the function can be run in the HTML for faster display +// window.onload=initMenu; + +// creat timeout variables for list item +// it's for avoid some warning with IE +for( var i = 0; i < 100; i++ ) +{ + eval("var timeoutli" + i + " = false;"); +} + +// this fonction apply the CSS style and the event +function initMenu() +{ + // a test to avoid some browser like IE4, Opera 6, and IE Mac + if ( browser.isDOM1 + && !( browser.isMac && browser.isIE ) + && !( browser.isOpera && browser.versionMajor < 7 ) + && !( browser.isIE && browser.versionMajor < 5 ) ) + { + // get some element + var menu = document.getElementById('menu'); // the root element + var lis = menu.getElementsByTagName('li'); // all the li + + // change the class name of the menu, + // it's usefull for compatibility with old browser + menu.className='menu'; + // i am searching for ul element in li element + for ( var i=0; i 0 ) + { + // improve IE key navigation + if ( browser.isIE ) + { + addAnEvent(lis.item(i),'keyup',show); + } + // link events to list item + addAnEvent(lis.item(i),'mouseover',show); + addAnEvent(lis.item(i),'mouseout',timeoutHide); + addAnEvent(lis.item(i),'blur',timeoutHide); + addAnEvent(lis.item(i),'focus',show); + + // add an id to list item + lis.item(i).setAttribute( 'id', "li"+i ); + } + } + } +} + + + + +function addAnEvent( target, eventName, functionName ) +{ + // apply the method to IE + if ( browser.isIE ) + { + //attachEvent dont work properly with this + eval('target.on'+eventName+'=functionName'); + } + // apply the method to DOM compliant browsers + else + { + target.addEventListener( eventName , functionName , true ); // true is important for Opera7 + } +} + +// hide the first ul element of the current element +function timeoutHide() +{ + // start the timeout + eval( "timeout" + this.id + " = window.setTimeout('hideUlUnder( \"" + this.id + "\" )', " + timeout + " );"); +} + +// hide the ul elements under the element identified by id +function hideUlUnder( id ) +{ + document.getElementById(id).getElementsByTagName('ul')[0].style['visibility'] = 'hidden'; +} + +// show the first ul element found under this element +function show() +{ + // show the sub menu + this.getElementsByTagName('ul')[0].style['visibility'] = 'visible'; + var currentNode=this; + while(currentNode) + { + if( currentNode.nodeName=='LI') + { + // currentNode.getElementsByTagName('a')[0].className = 'linkOver'; + } + currentNode=currentNode.parentNode; + } + // clear the timeout + eval ( "clearTimeout( timeout"+ this.id +");" ); + hideAllOthersUls( this ); +} + +// hide all ul on the same level of this list item +function hideAllOthersUls( currentLi ) +{ + var lis = currentLi.parentNode; + for ( var i=0; i 0 ) + { + if ( browser.isIE ) + { + addAnEvent(lis2.item(i),'keyup',show); + } + + addAnEvent(lis2.item(i),'mouseover',show); + addAnEvent(lis2.item(i),'mouseout',timeoutHide); + addAnEvent(lis2.item(i),'blur',timeoutHide); + addAnEvent(lis2.item(i),'focus',show); + + lis2.item(i).setAttribute( 'id', "li2"+i ); + } + } + } +} + + + +function addAnEvent( target, eventName, functionName ) +{ + if ( browser.isIE ) + { + eval('target.on'+eventName+'=functionName'); + } + else + { + target.addEventListener( eventName , functionName , true ); + } +} + +function timeoutHide() +{ + eval( "timeout" + this.id + " = window.setTimeout('hideUlUnder( \"" + this.id + "\" )', " + timeout + " );"); +} + +// hide the ul elements under the element identified by id +function hideUlUnder( id ) +{ + document.getElementById(id).getElementsByTagName('ul')[0].style['visibility'] = 'hidden'; +} + +// show the first ul element found under this element +function show() +{ + // show the sub menu + this.getElementsByTagName('ul')[0].style['visibility'] = 'visible'; + var currentNode=this; + while(currentNode) + { + if( currentNode.nodeName=='LI') + { + // currentNode.getElementsByTagName('a')[0].className = 'linkOver'; + } + currentNode=currentNode.parentNode; + } + // clear the timeout + eval ( "clearTimeout( timeout"+ this.id +");" ); + hideAllOthersUls( this ); +} + +// hide all ul on the same level of this list item +function hideAllOthersUls( currentLi ) +{ + var lis = currentLi.parentNode; + for ( var i=0; i -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + + hide: function(element) { + element = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = Element.ancestors(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value || value == 'auto') { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
      ', 1], + TBODY: ['', '
      ', 2], + TR: ['', '
      ', 3], + TD: ['
      ', '
      ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
      '; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/sw/in_progress/pow/pow/WebContent/js/tabber.js b/sw/in_progress/pow/pow/WebContent/js/tabber.js new file mode 100644 index 0000000000..a53b1b3060 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/js/tabber.js @@ -0,0 +1,536 @@ +/*================================================== + $Id: tabber.js,v 1.9 2006/04/27 20:51:51 pat Exp $ + tabber.js by Patrick Fitzgerald pat@barelyfitz.com + + Documentation can be found at the following URL: + http://www.barelyfitz.com/projects/tabber/ + + License (http://www.opensource.org/licenses/mit-license.php) + + Copyright (c) 2006 Patrick Fitzgerald + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + ==================================================*/ + +function tabberObj(argsObj) +{ + var arg; /* name of an argument to override */ + + /* Element for the main tabber div. If you supply this in argsObj, + then the init() method will be called. + */ + this.div = null; + + /* Class of the main tabber div */ + this.classMain = "tabber"; + + /* Rename classMain to classMainLive after tabifying + (so a different style can be applied) + */ + this.classMainLive = "tabberlive"; + + /* Class of each DIV that contains a tab */ + this.classTab = "tabbertab"; + + /* Class to indicate which tab should be active on startup */ + this.classTabDefault = "tabbertabdefault"; + + /* Class for the navigation UL */ + this.classNav = "tabbernav"; + + /* When a tab is to be hidden, instead of setting display='none', we + set the class of the div to classTabHide. In your screen + stylesheet you should set classTabHide to display:none. In your + print stylesheet you should set display:block to ensure that all + the information is printed. + */ + this.classTabHide = "tabbertabhide"; + + /* Class to set the navigation LI when the tab is active, so you can + use a different style on the active tab. + */ + this.classNavActive = "tabberactive"; + + /* Elements that might contain the title for the tab, only used if a + title is not specified in the TITLE attribute of DIV classTab. + */ + this.titleElements = ['h2','h3','h4','h5','h6']; + + /* Should we strip out the HTML from the innerHTML of the title elements? + This should usually be true. + */ + this.titleElementsStripHTML = true; + + /* If the user specified the tab names using a TITLE attribute on + the DIV, then the browser will display a tooltip whenever the + mouse is over the DIV. To prevent this tooltip, we can remove the + TITLE attribute after getting the tab name. + */ + this.removeTitle = true; + + /* If you want to add an id to each link set this to true */ + this.addLinkId = false; + + /* If addIds==true, then you can set a format for the ids. + will be replaced with the id of the main tabber div. + will be replaced with the tab number + (tab numbers starting at zero) + will be replaced with the tab number + (tab numbers starting at one) + will be replaced by the tab title + (with all non-alphanumeric characters removed) + */ + this.linkIdFormat = 'nav'; + + /* You can override the defaults listed above by passing in an object: + var mytab = new tabber({property:value,property:value}); + */ + for (arg in argsObj) { this[arg] = argsObj[arg]; } + + /* Create regular expressions for the class names; Note: if you + change the class names after a new object is created you must + also change these regular expressions. + */ + this.REclassMain = new RegExp('\\b' + this.classMain + '\\b', 'gi'); + this.REclassMainLive = new RegExp('\\b' + this.classMainLive + '\\b', 'gi'); + this.REclassTab = new RegExp('\\b' + this.classTab + '\\b', 'gi'); + this.REclassTabDefault = new RegExp('\\b' + this.classTabDefault + '\\b', 'gi'); + this.REclassTabHide = new RegExp('\\b' + this.classTabHide + '\\b', 'gi'); + + /* Array of objects holding info about each tab */ + this.tabs = new Array(); + + /* If the main tabber div was specified, call init() now */ + if (this.div) { + + this.init(this.div); + + /* We don't need the main div anymore, and to prevent a memory leak + in IE, we must remove the circular reference between the div + and the tabber object. */ + this.div = null; + } +} + + +/*-------------------------------------------------- + Methods for tabberObj + --------------------------------------------------*/ + + +tabberObj.prototype.init = function(e) +{ + /* Set up the tabber interface. + + e = element (the main containing div) + + Example: + init(document.getElementById('mytabberdiv')) + */ + + var + childNodes, /* child nodes of the tabber div */ + i, i2, /* loop indices */ + t, /* object to store info about a single tab */ + defaultTab=0, /* which tab to select by default */ + DOM_ul, /* tabbernav list */ + DOM_li, /* tabbernav list item */ + DOM_a, /* tabbernav link */ + aId, /* A unique id for DOM_a */ + headingElement; /* searching for text to use in the tab */ + + /* Verify that the browser supports DOM scripting */ + if (!document.getElementsByTagName) { return false; } + + /* If the main DIV has an ID then save it. */ + if (e.id) { + this.id = e.id; + } + + /* Clear the tabs array (but it should normally be empty) */ + this.tabs.length = 0; + + /* Loop through an array of all the child nodes within our tabber element. */ + childNodes = e.childNodes; + for(i=0; i < childNodes.length; i++) { + + /* Find the nodes where class="tabbertab" */ + if(childNodes[i].className && + childNodes[i].className.match(this.REclassTab)) { + + /* Create a new object to save info about this tab */ + t = new Object(); + + /* Save a pointer to the div for this tab */ + t.div = childNodes[i]; + + /* Add the new object to the array of tabs */ + this.tabs[this.tabs.length] = t; + + /* If the class name contains classTabDefault, + then select this tab by default. + */ + if (childNodes[i].className.match(this.REclassTabDefault)) { + defaultTab = this.tabs.length-1; + } + } + } + + /* Create a new UL list to hold the tab headings */ + DOM_ul = document.createElement("ul"); + DOM_ul.className = this.classNav; + + /* Loop through each tab we found */ + for (i=0; i < this.tabs.length; i++) { + + t = this.tabs[i]; + + /* Get the label to use for this tab: + From the title attribute on the DIV, + Or from one of the this.titleElements[] elements, + Or use an automatically generated number. + */ + t.headingText = t.div.title; + + /* Remove the title attribute to prevent a tooltip from appearing */ + if (this.removeTitle) { t.div.title = ''; } + + if (!t.headingText) { + + /* Title was not defined in the title of the DIV, + So try to get the title from an element within the DIV. + Go through the list of elements in this.titleElements + (typically heading elements ['h2','h3','h4']) + */ + for (i2=0; i2/gi," "); + t.headingText = t.headingText.replace(/<[^>]+>/g,""); + } + break; + } + } + } + + if (!t.headingText) { + /* Title was not found (or is blank) so automatically generate a + number for the tab. + */ + t.headingText = i + 1; + } + + /* Create a list element for the tab */ + DOM_li = document.createElement("li"); + + /* Save a reference to this list item so we can later change it to + the "active" class */ + t.li = DOM_li; + + /* Create a link to activate the tab */ + DOM_a = document.createElement("a"); + DOM_a.appendChild(document.createTextNode(t.headingText)); + DOM_a.href = "javascript:void(null);"; + DOM_a.title = t.headingText; + DOM_a.onclick = this.navClick; + + /* Add some properties to the link so we can identify which tab + was clicked. Later the navClick method will need this. + */ + DOM_a.tabber = this; + DOM_a.tabberIndex = i; + + /* Do we need to add an id to DOM_a? */ + if (this.addLinkId && this.linkIdFormat) { + + /* Determine the id name */ + aId = this.linkIdFormat; + aId = aId.replace(//gi, this.id); + aId = aId.replace(//gi, i); + aId = aId.replace(//gi, i+1); + aId = aId.replace(//gi, t.headingText.replace(/[^a-zA-Z0-9\-]/gi, '')); + + DOM_a.id = aId; + } + + /* Add the link to the list element */ + DOM_li.appendChild(DOM_a); + + /* Add the list element to the list */ + DOM_ul.appendChild(DOM_li); + } + + /* Add the UL list to the beginning of the tabber div */ + e.insertBefore(DOM_ul, e.firstChild); + + /* Make the tabber div "live" so different CSS can be applied */ + e.className = e.className.replace(this.REclassMain, this.classMainLive); + + /* Activate the default tab, and do not call the onclick handler */ + this.tabShow(defaultTab); + + /* If the user specified an onLoad function, call it now. */ + if (typeof this.onLoad == 'function') { + this.onLoad({tabber:this}); + } + + return this; +}; + + +tabberObj.prototype.navClick = function(event) +{ + /* This method should only be called by the onClick event of an + element, in which case we will determine which tab was clicked by + examining a property that we previously attached to the + element. + + Since this was triggered from an onClick event, the variable + "this" refers to the element that triggered the onClick + event (and not to the tabberObj). + + When tabberObj was initialized, we added some extra properties + to the element, for the purpose of retrieving them now. Get + the tabberObj object, plus the tab number that was clicked. + */ + + var + rVal, /* Return value from the user onclick function */ + a, /* element that triggered the onclick event */ + self, /* the tabber object */ + tabberIndex, /* index of the tab that triggered the event */ + onClickArgs; /* args to send the onclick function */ + + a = this; + if (!a.tabber) { return false; } + + self = a.tabber; + tabberIndex = a.tabberIndex; + + /* Remove focus from the link because it looks ugly. + I don't know if this is a good idea... + */ + a.blur(); + + /* If the user specified an onClick function, call it now. + If the function returns false then do not continue. + */ + if (typeof self.onClick == 'function') { + + onClickArgs = {'tabber':self, 'index':tabberIndex, 'event':event}; + + /* IE uses a different way to access the event object */ + if (!event) { onClickArgs.event = window.event; } + + rVal = self.onClick(onClickArgs); + if (rVal === false) { return false; } + } + + self.tabShow(tabberIndex); + + return false; +}; + + +tabberObj.prototype.tabHideAll = function() +{ + var i; /* counter */ + + /* Hide all tabs and make all navigation links inactive */ + for (i = 0; i < this.tabs.length; i++) { + this.tabHide(i); + } +}; + + +tabberObj.prototype.tabHide = function(tabberIndex) +{ + var div; + + if (!this.tabs[tabberIndex]) { return false; } + + /* Hide a single tab and make its navigation link inactive */ + div = this.tabs[tabberIndex].div; + + /* Hide the tab contents by adding classTabHide to the div */ + if (!div.className.match(this.REclassTabHide)) { + div.className += ' ' + this.classTabHide; + } + this.navClearActive(tabberIndex); + + return this; +}; + + +tabberObj.prototype.tabShow = function(tabberIndex) +{ + /* Show the tabberIndex tab and hide all the other tabs */ + + var div; + + if (!this.tabs[tabberIndex]) { return false; } + + /* Hide all the tabs first */ + this.tabHideAll(); + + /* Get the div that holds this tab */ + div = this.tabs[tabberIndex].div; + + /* Remove classTabHide from the div */ + div.className = div.className.replace(this.REclassTabHide, ''); + + /* Mark this tab navigation link as "active" */ + this.navSetActive(tabberIndex); + + /* If the user specified an onTabDisplay function, call it now. */ + if (typeof this.onTabDisplay == 'function') { + this.onTabDisplay({'tabber':this, 'index':tabberIndex}); + } + + return this; +}; + +tabberObj.prototype.navSetActive = function(tabberIndex) +{ + /* Note: this method does *not* enforce the rule + that only one nav item can be active at a time. + */ + + /* Set classNavActive for the navigation list item */ + this.tabs[tabberIndex].li.className = this.classNavActive; + + return this; +}; + + +tabberObj.prototype.navClearActive = function(tabberIndex) +{ + /* Note: this method does *not* enforce the rule + that one nav should always be active. + */ + + /* Remove classNavActive from the navigation list item */ + this.tabs[tabberIndex].li.className = ''; + + return this; +}; + + +/*==================================================*/ + + +function tabberAutomatic(tabberArgs) +{ + /* This function finds all DIV elements in the document where + class=tabber.classMain, then converts them to use the tabber + interface. + + tabberArgs = an object to send to "new tabber()" + */ + var + tempObj, /* Temporary tabber object */ + divs, /* Array of all divs on the page */ + i; /* Loop index */ + + if (!tabberArgs) { tabberArgs = {}; } + + /* Create a tabber object so we can get the value of classMain */ + tempObj = new tabberObj(tabberArgs); + + /* Find all DIV elements in the document that have class=tabber */ + + /* First get an array of all DIV elements and loop through them */ + divs = document.getElementsByTagName("div"); + for (i=0; i < divs.length; i++) { + + /* Is this DIV the correct class? */ + if (divs[i].className && + divs[i].className.match(tempObj.REclassMain)) { + + /* Now tabify the DIV */ + tabberArgs.div = divs[i]; + divs[i].tabber = new tabberObj(tabberArgs); + } + } + + return this; +} + + +/*==================================================*/ + + +function tabberAutomaticOnLoad(tabberArgs) +{ + /* This function adds tabberAutomatic to the window.onload event, + so it will run after the document has finished loading. + */ + var oldOnLoad; + + if (!tabberArgs) { tabberArgs = {}; } + + /* Taken from: http://simon.incutio.com/archive/2004/05/26/addLoadEvent */ + + oldOnLoad = window.onload; + if (typeof window.onload != 'function') { + window.onload = function() { + tabberAutomatic(tabberArgs); + + }; + } else { + window.onload = function() { + oldOnLoad(); + tabberAutomatic(tabberArgs); + + }; + } +} + + +/*==================================================*/ +function init_tabs(){ + if (typeof tabberOptions == 'undefined') { + tabberAutomatic({}); + } + else + {if (!tabberOptions['manualStartup']) { + tabberAutomatic(tabberOptions); + } + } +} + +function init_autotabber(){ +/* Run tabberAutomaticOnload() unless the "manualStartup" option was specified */ + + if (typeof tabberOptions == 'undefined') { + + tabberAutomaticOnLoad(); + + } else { + + if (!tabberOptions['manualStartup']) { + tabberAutomaticOnLoad(tabberOptions); + } + + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-client.js b/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-client.js new file mode 100644 index 0000000000..8a0739d9ca --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-client.js @@ -0,0 +1,612 @@ +/* + * Pushlet JS client library. + * NOTE: this should replace the js-pushlet-client.jsp file + * (since we can figure out pushletWebRoot from within JS) + * + * $Id: js-pushlet-client.js,v 1.2 2007/11/10 14:17:18 justb Exp $ + */ +var flag = false; +var pushletWebRoot = null; +var pushletURI; +var pushletNetURI; +var sessionId = null; +var controlQueue = new Queue(20); +var statusMsg = 'null'; +var statusChanged = false; +var statusChar = '|'; +var pushletNet; +var listenMode = null; +var listenSubject = null; + +// Initialize various URLs +_initURIs(); + +/************ Public application functions ******************/ + +// Embed pushlet frame in page +function p_embed(thePushletWebRoot) { + if (thePushletWebRoot) { + // Use this when webapp is not in same server e.g. with virtual hosts + pushletWebRoot = thePushletWebRoot; + _initURIs(); + } +//alert(pushletNetURI+""); + p_debug(flag, "p_embed", 'write ' + pushletLayer); + var pushletLayer = ''; + + self.document.write(pushletLayer); + _setStatus('initializing...'); + _showStatus(); + _waitForPushletFrame(); +} + +// Join the pushlet server +function p_join() { + // Ignore (for now) if already joined + if (sessionId != null) { + return; + } + + _setStatus('connecting...'); + p_debug(flag, "p_join", 'joining..'); + + + // Check if pushlet frame is loaded + if (pushletNet) { + // Pushlet iframe is ready for calls + pushletNet.setControlURI(pushletURI + '?p_event=join'); + } else { + + // Pushlet net iframe not loaded: continue waiting + setTimeout("p_join()", 100); + } +} + +// Create data event channel with the server +function p_listen(subject, mode) { + // Optional initial subject to subscribe to + if (subject) { + // Remember + listenSubject = subject; + } + + // Optional mode (stream, pull, poll) i.s.o. default + if (mode) { + // Remember + listenMode = mode; + } + + // Loop forever as long not joined + if (sessionId) { + // ok we have joined + + // Create event URI for listen + var uri = pushletURI + '?p_id=' + sessionId + '&p_event=listen'; + + // Optional subject to subscribe to + if (listenSubject) { + uri = uri + '&p_subject=' + listenSubject; + } + + // Optional mode (stream, pull, poll) i.s.o. default + if (listenMode) { + uri = uri + '&p_mode=' + listenMode; + } + + pushletNet.listen(uri); + return; + } + + // No join ack (sessionId) yet: wait until received + setTimeout("p_listen()", 100); + +} + +// Shorthand: Join the pushlet server and start listening immediately +function p_join_listen(subject, mode) { + p_join(); + p_listen(subject, mode); +} + +// Leave the pushlet server +function p_leave() { + // Ignore (for now) if already left + if (sessionId == null) { + return; + } + + var uri = pushletURI + '?p_event=leave'; + p_debug(flag, 'p_leave', 'leave uri=' + uri); + _sendControlURI(uri); +} + + +// Send heartbeat event; callback is onHeartbeatAck() +function p_heartbeat() { + var uri = pushletURI + '?p_event=hb'; + p_debug(flag, 'p_heartbeat'); + _sendControlURI(uri); +} + +// Publish to a subject +function p_publish(subject, nvPairs) { + if (!subject) { + return false; + } + + var uri = pushletURI + '?p_event=publish&p_subject=' + subject; + + var args = p_publish.arguments; + + // Put the arguments' name/value pairs in the URI + for (var i = 1; i < args.length; i++) { + uri = uri + '&' + args[i] + '=' + args[++i]; + } + + p_debug(false, 'p_publish', 'publish uri=' + uri); + _sendControlURI(uri); +} + +// Subscribe to a subject with optional label +function p_subscribe(subject, label) { + var uri = pushletURI + '?p_event=subscribe&p_subject=' + subject; + if (label) { + uri = uri + '&p_label=' + label; + } + + p_debug(flag, 'p_subscribe', 'subscribe uri=' + uri); + _sendControlURI(uri); +} + + // Unsubscribe from a subject +function p_unsubscribe(subscriptionId) { + var uri = pushletURI + '?p_event=unsubscribe'; + + if (subscriptionId) { + uri = uri + '&p_sid=' + subscriptionId; + } + + p_debug(flag, 'p_unsubscribe', 'unsubscribe uri=' + uri); + _sendControlURI(uri); +} + + +// Get webroot for this webapp +function p_getWebRoot() { + return pushletWebRoot; +} + +// Get pushlet session id +function p_getSessionId() { + return sessionId; +} + +// Show debug window +function p_setDebug(aFlag) { + flag = aFlag; + p_setNetDebug(aFlag); +} + +// Show network debug window +function p_setNetDebug(aFlag) { + pushletNet.p_setDebug(aFlag); +} + +/************ Private functions ******************/ + +/** CALLBACKS FROM pushletFrame ***/ + +// Generic callback from server; this function is called from within the +// Pushlet subscriber frame (see frames below). +function _push(args) { + // Create a PushletEvent object from the arguments passed in + // push.arguments is event data coming from the Server + var event = new PushletEvent(args); + + p_debug(flag, '_push() from server: ', event.toString()); + + // Do action based on event type + var eventType = event.getEvent(); + + if (eventType == 'data') { + _setStatus('data'); + _doCallback(event, window.onData); + } else if (eventType == 'join-ack') { + sessionId = event.get('p_id'); + _setStatus('connected'); + _doCallback(event, window.onJoinAck); + } else if (eventType == 'listen-ack') { + _setStatus('listening'); + _doCallback(event, window.onListenAck); + + // Send empty heartbeat event. This + // silences many busy browser windows. + // At least in Moz and IE. + p_heartbeat(); + } else if (eventType == 'hb') { + _setStatus('heartbeat'); + _doCallback(event, window.onHeartbeat); + } else if (eventType == 'hb-ack') { + _doCallback(event, window.onHeartbeatAck); + } else if (eventType == 'leave-ack') { + sessionId = null; + _setStatus('disconnected'); + _doCallback(event, window.onLeaveAck); + } else if (eventType == 'refresh-ack') { + _doCallback(event, window.onRefreshAck); + } else if (eventType == 'subscribe-ack') { + _setStatus('subscribed to ' + event.get('p_subject')); + _doCallback(event, window.onSubscribeAck); + } else if (eventType == 'unsubscribe-ack') { + _setStatus('unsubscribed'); + _doCallback(event, window.onUnsubscribeAck); + } else if (eventType == 'abort') { + _setStatus('abort'); + _doCallback(event, window.onAbort); + } else if (eventType.match(/nack$/)) { + _setStatus('error response: ' + event.get('p_reason')); + _doCallback(event, window.onNack); + } +} + +function getWebRoot() { + /** Return directory of this relative to document URL. */ + if (pushletWebRoot != null) { + return pushletWebRoot; + } + //derive the baseDir value by looking for the script tag that loaded this file + var head = document.getElementsByTagName('head')[0]; + var nodes = head.childNodes; + for (var i = 0; i < nodes.length; ++i) { + var src = nodes.item(i).src; + if (src) { + var index = src.indexOf("lib/js-pushlet-client.js"); + if (index >= 0) { + pushletWebRoot = src.substring(0, index); + break; + } + } + } + return pushletWebRoot; +} + +function _initURIs() { + pushletURI = getWebRoot() + 'pushlet.srv'; + pushletNetURI = getWebRoot() + 'lib/js-pushlet-net.html'; + //alert(pushletURI); +// alert(pushletNetURI); +} + +function _showStatus() { + // To show progress + if (statusChanged == true) { + if (statusChar == '|') statusChar = '/'; + else if (statusChar == '/') statusChar = '--'; + else if (statusChar == '--') statusChar = '\\'; + else statusChar = '|'; + statusChanged = false; + } + + window.defaultStatus = statusMsg; + window.status = statusMsg + ' ' + statusChar; + timeout = window.setTimeout('_showStatus()', 400); +} + +function _setStatus(status) { + statusMsg = "pushlet - " + status; + statusChanged = true; +} + +function _onUnload() { + p_debug(true, "pushlet-lib", "_onUnload() called"); +} + +function _onBeforeUnload() { + p_debug(true, "pushlet-lib", "_onBeforeUnload() called"); +} + +function _onStop() { + p_debug(true, "pushlet-lib", "_onStop() called"); +} + +function _doCallback(event, cbFunction) { + // Do specific callback function if provided by client + if (cbFunction) { + // Do specific callback like onData(), onJoinAck() etc. + cbFunction(event); + } else if (window.onEvent) { + // general callback onEvent() provided to catch all events + onEvent(event); + } +} + +/** CALLS TO pushletFrame ***/ + + +function _sendControlURI(uri) { + if (controlQueue.isFull()) { + // TODO divert to errpage + alert('serious problem: control queue is full'); + // no sense going on + return; + } + + if (sessionId == null) { + controlQueue.enqueue(uri); + _processControlQueue(); + return; + } + + // All clear to send immediately ? + if (controlQueue.isEmpty()) { + if (pushletNet.isControlReady()) { + // Ok send direct + uri = uri + '&p_id=' + sessionId; + pushletNet.setControlURI(uri); + } else { + controlQueue.enqueue(uri); + } + } else { + // Queue not empty + controlQueue.enqueue(uri); + } + + if (!controlQueue.isEmpty()) { + _processControlQueue(); + } +} + +function _processControlQueue() { + if (controlQueue.isEmpty()) { + // all done + return; + } + + if (sessionId != null) { + // Dequeue next control URI if pushletFrame ready + if (pushletNet.isControlReady()) { + var uri = controlQueue.dequeue() + '&p_id=' + sessionId; + pushletNet.setControlURI(uri); + } + } + + // Loop forever as long queue is not empty + if (!controlQueue.isEmpty()) { + setTimeout("_processControlQueue()", 50); + } +} + + +function _waitForPushletFrame() { + // Loop forever as long net uri not ready + if (self.pushletFrame && self.pushletFrame.isLoaded && self.pushletFrame.isLoaded()) { + _setStatus('loaded pushlet frame...'); + + pushletNet = self.pushletFrame; + return; + } + + _setStatus('pushlet frame not ready'); + setTimeout("_waitForPushletFrame()", 20); +} + +/************** Util classes *******************************/ + +/** NV pair object */ +function NameValuePair(name, value) { + this.name = name; + this.value = value; +} + +/** Simple Map object to store array of name/value pairs */ +function Map() { + // Data members + this.index = 0; + this.map = new Array(); + + // Function members + this.get = MapGet; + this.put = MapPut; + this.toString = MapToString; + this.toTable = MapToTable; +} + +/** get() */ +function MapGet(name) { + for (var i = 0; i < this.index; i++) { + if (this.map[i].name == name) { + return this.map[i].value; + } + } + return ''; +} + +/** put() */ +function MapPut(name, value) { + this.map[this.index++] = new NameValuePair(name, value); +} + +/** To HTML string */ +function MapToString() { + var res = ''; + + for (var i = 0; i < this.index; i++) { + res = res + this.map[i].name + '=' + this.map[i].value + '\n'; + } + return res; +} + +/** To HTML table */ +function MapToTable() { + var res = ''; + var styleDiv = '
      ' + + for (var i = 0; i < this.index; i++) { + res = res + '
      '; + } + res += '
      ' + styleDiv + this.map[i].name + '' + styleDiv + this.map[i].value + '
      ' + return res; +} + +/** Simple FIFO Queue class */ +function Queue(aCapacity) { + // Data members + this.capacity = aCapacity; + this.size = 0; + this.arr = new Array(); + this.front = 0; + this.rear = 0; + + // Function members + this.dequeue = QueueDequeue; + this.enqueue = QueueEnqueue; + this.next = QueueNext; + this.isFull = QueueIsFull; + this.isEmpty = QueueIsEmpty; +} + +/** enqueue() */ +function QueueEnqueue(item) { + if (this.isFull()) { + alert('queue full !!'); + return; + } + + this.arr[this.rear] = item; + this.rear = this.next(this.rear); + this.size++; +} + +/** dequeue() */ +function QueueDequeue(name) { + if (this.isEmpty()) { + alert('queue empty !!'); + return; + } + var temp = this.arr[this.front]; + this.arr[this.front] = null; + this.front = this.next(this.front); + this.size--; + return temp; +} + +/** Circular counter. */ +function QueueNext(index) { + return (index + 1 < this.capacity ? index + 1 : 0); +} + +function QueueIsFull() { + return this.size == this.capacity; +} + +function QueueIsEmpty() { + return this.size == 0; +} + +/* Class to represent nl.justobjects.pushlet.Event in JavaScript. + Arguments are an array where args[i] is name and args[i+1] is value +*/ +function PushletEvent(args) { + // Member variable setup; the Map stores the N/V pairs + this.map = new Map(); + + // Member function setup + this.getSubject = PushletEventGetSubject + this.getEvent = PushletEventGetEvent + this.put = PushletEventPut + this.get = PushletEventGet + this.toString = PushletEventToString + this.toTable = PushletEventToTable + + // Put the arguments' name/value pairs in the Map + for (var i = 0; i < args.length; i++) { + this.put(args[i], args[++i]); + } +} + +// Get the subject attribute +function PushletEventGetSubject() { + return this.map.get('p_subject') +} + +// Get the subject attribute +function PushletEventGetEvent() { + return this.map.get('p_event') +} + +// Get event attribute +function PushletEventGet(name) { + return this.map.get(name) +} + +// Put event attribute +function PushletEventPut(name, value) { + return this.map.put(name, value) +} + +function PushletEventToString() { + return this.map.toString(); +} + +// Convert content to HTML TABLE +function PushletEventToTable() { + return this.map.toTable(); +} + +/*************** Debug utility *******************************/ +var timestamp = 0 +var debugWindow = null +var messages = new Array() +var messagesIndex = 0 + +/** Send debug messages to a (D)HTML window. */ +function p_debug(flag, label, value) { + + // Only print if the flag is set + if (!flag) { + return; + } + + var funcName = "none"; + + // Fetch JS function name if any + if (p_debug.caller) { + funcName = p_debug.caller.toString() + funcName = funcName.substring(9, funcName.indexOf(")") + 1) + } + + // Create message + var msg = "-" + funcName + ": " + label + "=" + value + + // Add optional timestamp + var now = new Date() + var elapsed = now - timestamp + if (elapsed < 10000) { + msg += " (" + elapsed + " msec)" + } + + timestamp = now + + // Show. + + if ((debugWindow == null) || debugWindow.closed) { + debugWindow = window.open("", "p_debugWin", "toolbar=no,scrollbars=yes,resizable=yes,width=600,height=400"); + } + + // Add message to current list + messages[messagesIndex++] = msg + + // Write doc header + debugWindow.document.writeln('Pushlet Debug Window'); + + // Write the messages + for (var i = 0; i < messagesIndex; i++) { + debugWindow.document.writeln('
      ' + i + ': ' + messages[i] + '
      '); + } + + // Write doc footer and close + debugWindow.document.writeln(''); + debugWindow.document.close(); + debugWindow.focus(); + +} diff --git a/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-net.html b/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-net.html new file mode 100644 index 0000000000..fceafc90b2 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/lib/js-pushlet-net.html @@ -0,0 +1,109 @@ + + + + + Pushlet Networking Component + + + + + + + + + + + + + + + diff --git a/sw/in_progress/pow/pow/WebContent/logOut.jsp b/sw/in_progress/pow/pow/WebContent/logOut.jsp new file mode 100644 index 0000000000..49ec9f46f0 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/logOut.jsp @@ -0,0 +1,39 @@ + + + + + + + + + + Log Out + + + + + + + + + + <%-- desabonnement du pushlet--%> +
      +Bye bye <% out.println(session.getAttribute("login")); %> !
      +Thank you for using Paparazzi On the Web !
      + +<% +session.removeAttribute("login"); +session.removeAttribute("rights"); +session.invalidate(); +%> + +

      +Click here to go to the Paparazzi project homepage.
      +Click here to return to the Paparazzi On the Web homepage. +

      +
      + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/WebContent/test.html b/sw/in_progress/pow/pow/WebContent/test.html new file mode 100644 index 0000000000..048391b403 --- /dev/null +++ b/sw/in_progress/pow/pow/WebContent/test.html @@ -0,0 +1,92 @@ + + + +Test Dom + + + + + + + + +

      Coucou

      + + + +
      + +
      + +
      +
      +
      + + + \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/Version.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/Version.java new file mode 100644 index 0000000000..a2563f7192 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/Version.java @@ -0,0 +1,37 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet; + +/** + * Version info class. + * + *

      Purpose

      + * Extract version info from jar manifest file. + * + * @author Just van den Broecke + * @version $Id: Version.java,v 1.4 2006/05/06 00:10:11 justb Exp $ + */ + +public class Version { + /** Version info extracted from the .jar manifest file (see build.xml and build.properties). */ + public static final String SOFTWARE_VERSION = Version.class.getPackage().getSpecificationVersion(); + public static final String BUILD_DATE = Version.class.getPackage().getImplementationVersion(); +} + +/* + * $Log: Version.java,v $ + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2004/02/08 16:07:55 justb + * *** empty log message *** + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/11 21:29:48 justb + * first checkin + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java new file mode 100644 index 0000000000..f2dc390f26 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java @@ -0,0 +1,699 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventParser; +import nl.justobjects.pushlet.core.Protocol; +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.OutputStream; +import java.net.*; +import java.util.Map; + +/** + * Client API for Java HTTP client applets or apps. + *

      + * Use this class within Java client applications or applets. + * Implement a PushletClientListener to receive callbacks for + * data-related Event objects pushed by the server. + *

      + * This class may also be used as a base class and be extended + * for custom clients, hence the presence of many proteced methods. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: PushletClient.java,v 1.19 2009/06/04 12:46:35 justb Exp $ + * @see PushletClientListener + * @see nl.justobjects.pushlet.test.PushletApplet + * @see nl.justobjects.pushlet.test.PushletPingApplication + */ +public class PushletClient implements Protocol { + /** + * Pushlet URL. + */ + private String pushletURL; + + /** + * Debug flag for verbose output. + */ + private boolean debug; + + /** + * Id gotten on join ack + */ + private String id; + + /** + * Internal listener for data events pushed by server. + */ + protected DataEventListener dataEventListener; + + /** + * Constructor with full pushlet URL. + */ + public PushletClient(String aPushletURL) { + pushletURL = aPushletURL; + } + + /** + * Constructor with host and port using default URI. + */ + public PushletClient(String aHost, int aPort) { + this("http://" + aHost + ":" + aPort + DEFAULT_SERVLET_URI); + } + + /** + * Set proxy options and optional proxy authentication. + *

      + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + *

      + * Usage: + * PushletClient pushletClient = new PushletClient("http:://www.domain.com/pushlet"); + * pushletClient.setProxyOptions("proxy.bla.com", "8080", ....); + *

      + * use pushletClient further as normal + */ + public void setProxyOptions(String aProxyHost, + String aProxyPort, String theNonProxyHosts, + String aUserName, String aPassword, String anNTLMDomain) { + + // Enable proxying + System.setProperty("http.proxySet", "true"); + System.setProperty("http.proxyHost", aProxyHost); + System.setProperty("http.proxyPort", aProxyPort); + + // Set optional non-proxy hosts + if (theNonProxyHosts != null) { + System.setProperty("http.nonProxyHosts", theNonProxyHosts); + } + + // If user name specified configure proxy authentication + if (aUserName != null) { + System.setProperty("http.proxyUser", aUserName); + System.setProperty("http.proxyPassword", aPassword); + + // See inner class below + Authenticator.setDefault(new HTTPAuthenticateProxy(aUserName, aPassword)); + + // Optional NT domain + if (anNTLMDomain != null) { + System.setProperty("http.auth.ntlm.domain", anNTLMDomain); + } + } + } + + /** + * Join server, starts session. + */ + public void join() throws PushletException { + Event event = new Event(E_JOIN); + event.setField(P_FORMAT, FORMAT_XML); + Event response = doControl(event); + throwOnNack(response); + + // Join Ack received + id = response.getField(P_ID); + } + + /** + * Leave server, stops session. + */ + public void leave() throws PushletException { + stopListen(); + throwOnInvalidSession(); + Event event = new Event(E_LEAVE); + event.setField(P_ID, id); + Event response = doControl(event); + + throwOnNack(response); + id = null; + } + + /** + * Open data channel. + */ + public void listen(PushletClientListener aListener) throws PushletException { + listen(aListener, MODE_STREAM); + } + + /** + * Open data channel in stream or push mode. + */ + public void listen(PushletClientListener aListener, String aMode) throws PushletException { + listen(aListener, aMode, null); + } + + /** + * Open data channel in stream or push mode with a subject. + */ + public void listen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + throwOnInvalidSession(); + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_LISTEN + + "&" + P_ID + "=" + id + + "&" + P_MODE + "=" + aMode; + if (aSubject != null) { + listenURL = listenURL + "&" + P_SUBJECT + "=" + aSubject; + } + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Immediate listener: joins/subscribes and listens in one action. + */ + public void joinListen(PushletClientListener aListener, String aMode, String aSubject) throws PushletException { + stopListen(); + + String listenURL = pushletURL + + "?" + P_EVENT + "=" + E_JOIN_LISTEN + + "&" + P_FORMAT + "=" + FORMAT_XML + + "&" + P_MODE + "=" + aMode + + "&" + P_SUBJECT + "=" + aSubject; + + // Start listener thread (sync call). + startDataEventListener(aListener, listenURL); + } + + /** + * Publish an event through server. + */ + public void publish(String aSubject, Map theAttributes) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_PUBLISH, theAttributes); + event.setField(P_SUBJECT, aSubject); + event.setField(P_ID, id); + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject, String aLabel) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_SUBSCRIBE); + event.setField(P_ID, id); + event.setField(P_SUBJECT, aSubject); + + // Optional label, is returned in data events + if (aLabel != null) { + event.setField(P_SUBSCRIPTION_LABEL, aLabel); + } + + // Send request + Event response = doControl(event); + throwOnNack(response); + + return response.getField(P_SUBSCRIPTION_ID); + } + + /** + * Subscribes, returning subscription id. + */ + public String subscribe(String aSubject) throws PushletException { + return subscribe(aSubject, null); + } + + /** + * Unsubscribes with subscription id. + */ + public void unsubscribe(String aSubscriptionId) throws PushletException { + throwOnInvalidSession(); + Event event = new Event(E_UNSUBSCRIBE); + event.setField(P_ID, id); + + // Optional subscription id + if (aSubscriptionId != null) { + event.setField(P_SUBSCRIPTION_ID, aSubscriptionId); + } + + Event response = doControl(event); + throwOnNack(response); + } + + /** + * Unsubscribes from all subjects. + */ + public void unsubscribe() throws PushletException { + unsubscribe(null); + } + + /** + * Stop the listener. + */ + public void stopListen() throws PushletException { + if (dataEventListener != null) { + unsubscribe(); + dataEventListener.stop(); + dataEventListener = null; + } + } + + public void setDebug(boolean b) { + debug = b; + } + + /** + * Starts default DataEventListener and waits for its thread to start. + */ + protected void startDataEventListener(PushletClientListener aListener, String aListenURL) { + // Suggestion by Jeff Nowakowski 29.oct.2006 + dataEventListener = new DataEventListener(aListener, aListenURL); + + synchronized (dataEventListener) { + dataEventListener.start(); + try { + // Wait for data event listener (thread) to start + dataEventListener.wait(); + } catch (InterruptedException e) { + } + } + } + + protected void throwOnNack(Event anEvent) throws PushletException { + if (anEvent.getEventType().equals(E_NACK)) { + throw new PushletException("Negative response: reason=" + anEvent.getField(P_REASON)); + } + } + + protected void throwOnInvalidSession() throws PushletException { + if (id == null) { + throw new PushletException("Invalid pushlet session"); + } + } + + protected Reader openURL(String aURL) throws PushletException { + // Open URL connection with server + try { + p("Connecting to " + aURL); + URL url = new URL(aURL); + URLConnection urlConnection = url.openConnection(); + + // Disable any kind of caching. + urlConnection.setUseCaches(false); + urlConnection.setDefaultUseCaches(false); + + // TODO: later version may use POST + // Enable HTTP POST + // urlConnection.setDoOutput(true); + + // Do the POST with Event in XML in body + // OutputStream os = urlConnection.getOutputStream(); + // os.write(anEvent.toXML().getBytes()); + // os.flush(); + // os.close(); + + // Get the stream from the server. + // reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + // Note: somehow the client does not work with some JVMs when using + // BufferedInputStream... So do unbuffered input. + // p("Opening urlConnection inputstream"); + return new InputStreamReader(urlConnection.getInputStream()); + + } catch (Throwable t) { + warn("openURL() could not open " + aURL, t); + throw new PushletException(" could not open " + aURL, t); + } + } + + + /** + * Send control events to server and return response. + */ + protected Event doControl(Event aControlEvent) throws PushletException { + String controlURL = pushletURL + "?" + aControlEvent.toQueryString(); + + p("doControl to " + controlURL); + + // Open URL connection with server + Reader reader = openURL(controlURL); + + // Get Pushlet event from stream + Event event = null; + try { + p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + return event; + } catch (Throwable t) { + // Stop and report error. + warn("doControl() exception", t); + throw new PushletException(" error parsing response from" + controlURL, t); + } + } + + /** + * Util: print. + */ + protected void p(String s) { + if (debug) { + System.out.println("[PushletClient] " + s); + } + } + + /** + * Util: warn. + */ + protected void warn(String s) { + warn(s, null); + } + + /** + * Util: warn with exception. + */ + protected void warn(String s, Throwable t) { + System.err.println("[PushletClient] - WARN - " + s + " ex=" + t); + + if (t != null) { + t.printStackTrace(); + } + } + + /** + * Internal (default) listener for the Pushlet data channel. + */ + protected class DataEventListener implements Runnable { + /** + * Client's listener that gets called back on events. + */ + private PushletClientListener listener; + + /** + * Receiver receiveThread. + */ + private Thread receiveThread = null; + private Reader reader; + private String refreshURL; + private String listenURL; + + public DataEventListener(PushletClientListener aListener, String aListenURL) { + listener = aListener; + listenURL = aListenURL; + } + + public void start() { + // All ok: start a receiver receiveThread + receiveThread = new Thread(this); + receiveThread.start(); + + } + + /** + * Stop listening; may restart later with start(). + */ + public void stop() { + p("In stop()"); + bailout(); + } + + /** + * Receive event objects from server and callback listener. + */ + public void run() { + p("Start run()"); + try { + while (receiveThread != null && receiveThread.isAlive()) { + // Connect to server + reader = openURL(listenURL); + + synchronized (this) { + // Inform the calling thread we're ready to receive events. + // Suggestion by Jeff Nowakowski 29.oct.2006 + this.notify(); + } + + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; + try { + // p("Getting event..."); + // Get next event from server + event = EventParser.parse(reader); + p("Event received " + event); + } catch (Throwable t) { + + // Stop and report error. + // warn("Stop run() on exception", t); + if (listener != null) { + listener.onError("exception during receive: " + t); + } + + break; + } + + // Handle event by calling listener + if (event != null && listener != null) { + // p("received: " + event.toXML()); + String eventType = event.getEventType(); + if (eventType.equals(E_HEARTBEAT)) { + listener.onHeartbeat(event); + } else if (eventType.equals(E_DATA)) { + listener.onData(event); + } else if (eventType.equals(E_JOIN_LISTEN_ACK)) { + id = event.getField(P_ID); + } else if (eventType.equals(E_LISTEN_ACK)) { + p("Listen ack ok"); + } else if (eventType.equals(E_REFRESH_ACK)) { + // ignore + } else if (eventType.equals(E_ABORT)) { + listener.onAbort(event); + listener = null; + break; + } else if (eventType.equals(E_REFRESH)) { + refresh(event); + } else { + handleUnknownEventType(eventType, event, listener); + } + } + } + } + } catch (Throwable t) { + warn("Exception in run() ", t); + // bailout(); + } + } + + protected void disconnect() { + p("start disconnect()"); + if (reader != null) { + try { + // this blocks, find another way + // reader.close(); + p("Closed reader ok"); + } catch (Exception ignore) { + } finally { + reader = null; + } + } + p("end disconnect()"); + } + + /** + * Stop receiver receiveThread. + */ + public void stopThread() { + p("In stopThread()"); + + // Keep a reference such that we can kill it from here. + Thread targetThread = receiveThread; + + receiveThread = null; + + // This should stop the main loop for this receiveThread. + // Killing a receiveThread on a blcing read is tricky. + // See also http://gee.cs.oswego.edu/dl/cpj/cancel.html + if ((targetThread != null) && targetThread.isAlive()) { + + targetThread.interrupt(); + + try { + + // Wait for it to die + targetThread.join(500); + } catch (InterruptedException ignore) { + } + + // If current receiveThread refuses to die, + // take more rigorous methods. + if (targetThread.isAlive()) { + + // Not preferred but may be needed + // to stop during a blocking read. + targetThread.stop(); + + // Wait for it to die + try { + targetThread.join(500); + } catch (Throwable ignore) { + } + } + + p("Stopped receiveThread alive=" + targetThread.isAlive()); + + } + } + + /** + * Stop listening on stream from server. + */ + public void bailout() { + p("In bailout()"); + stopThread(); + disconnect(); + } + + /** + * Handle refresh, by pausing. + */ + protected void refresh(Event aRefreshEvent) throws PushletException { + try { + // Wait for specified time. + Thread.sleep(Long.parseLong(aRefreshEvent.getField(P_WAIT))); + } catch (Throwable t) { + warn("abort while refresing"); + refreshURL = null; + return; + } + + // If stopped during sleep, don't proceed + if (receiveThread == null) { + return; + } + + // Create url to refresh + refreshURL = pushletURL + + "?" + P_ID + "=" + id + + "&" + P_EVENT + "=" + E_REFRESH + ; + + if (reader != null) { + try { + reader.close(); + + } catch (IOException ignore) { + + } + reader = null; + } + + reader = openURL(refreshURL); + } + + /** + * Handle unknown Event (default behaviour). + */ + protected void handleUnknownEventType(String eventType, Event event, PushletClientListener listener) { + warn("unsupported event type received: " + eventType); + } + } + + /** + * Authenticator + */ + private static class HTTPAuthenticateProxy extends Authenticator { + + /** + * Contributed by Dele Olajide + * See http://groups.yahoo.com/group/pushlet/message/634 + */ + + private String thePassword = ""; + private String theUser = ""; + + public HTTPAuthenticateProxy(String username, String password) { + + thePassword = password; + theUser = username; + } + + protected PasswordAuthentication getPasswordAuthentication() { + // System.out.println("[HttpAuthenticateProxy] Username = " + theUser); + // System.out.println("[HttpAuthenticateProxy] Password = " + thePassword); + + return new PasswordAuthentication(theUser, thePassword.toCharArray()); + } + + } + +} + +/* + * $Log: PushletClient.java,v $ + * Revision 1.19 2009/06/04 12:46:35 justb + * PushletClient: add more hooks for extension (feat ID: 2799694 Craig M) + * + * Revision 1.18 2007/11/10 13:52:47 justb + * make startDataEventListener method protected to allow overriding + * + * Revision 1.17 2006/10/29 16:47:57 justb + * included patch from Jeff Nowakowski: wait until listener thread runs + * + * Revision 1.16 2005/05/06 20:08:20 justb + * client enhancements + * + * Revision 1.15 2005/03/27 17:42:27 justb + * enhancements + * + * Revision 1.14 2005/03/25 23:54:04 justb + * *** empty log message *** + * + * Revision 1.13 2005/02/28 16:59:40 justb + * fixes for leave and disconnect + * + * Revision 1.12 2005/02/28 15:57:54 justb + * added SimpleListener example + * + * Revision 1.11 2005/02/21 12:31:44 justb + * added proxy contribution from Dele Olajide + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/02/18 09:54:12 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.7 2005/02/15 15:46:30 justb + * client API improves + * + * Revision 1.6 2005/02/15 13:28:56 justb + * first quick rewrite adapt for v2 protocol + * + * Revision 1.5 2004/10/25 21:23:44 justb + * *** empty log message *** + * + * Revision 1.4 2004/10/24 13:52:51 justb + * small fixes in client lib + * + * Revision 1.3 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 20:14:17 justb + * renamed all *JavaPushletClient* to *PushletClient* + * + * Revision 1.10 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.9 2003/08/17 20:30:20 justb + * cosmetic changes + * + * Revision 1.8 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java.patch b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java.patch new file mode 100644 index 0000000000..63d660354d --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClient.java.patch @@ -0,0 +1,29 @@ +--- PushletClient.java 6 May 2005 20:08:20 -0000 1.16 ++++ PushletClient.java 28 Oct 2006 23:19:12 -0000 +@@ -142,7 +142,13 @@ + } + + dataEventListener = new DataEventListener(aListener, listenURL); +- dataEventListener.start(); ++ synchronized (dataEventListener) { ++ dataEventListener.start(); ++ try { ++ dataEventListener.wait(); ++ } catch (InterruptedException e) { ++ } ++ } + } + + /** Immediate listener. */ +@@ -354,6 +360,11 @@ + // Connect to server + reader = openURL(listenURL); + ++ synchronized (this) { ++ // Inform the calling thread we're ready to receive events. ++ this.notify(); ++ } ++ + // Get events while we're alive. + while (receiveThread != null && receiveThread.isAlive()) { + Event event = null; diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClientListener.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClientListener.java new file mode 100644 index 0000000000..74cee7b2b2 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/client/PushletClientListener.java @@ -0,0 +1,50 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.client; + +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.Protocol; + +/** + * Interface for listener of the PushletClient object. + * + * @version $Id: PushletClientListener.java,v 1.5 2005/02/21 11:50:37 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ +public interface PushletClientListener extends Protocol { + /** Abort event from server. */ + public void onAbort(Event theEvent); + + /** Data event from server. */ + public void onData(Event theEvent); + + /** Heartbeat event from server. */ + public void onHeartbeat(Event theEvent); + + /** Error occurred. */ + public void onError(String message); +} + +/* +* $Log: PushletClientListener.java,v $ +* Revision 1.5 2005/02/21 11:50:37 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.4 2005/02/15 15:46:31 justb +* client API improves +* +* Revision 1.3 2004/10/24 12:58:18 justb +* revised client and test classes for new protocol +* +* Revision 1.2 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.1 2004/03/10 20:14:17 justb +* renamed all *JavaPushletClient* to *PushletClient* +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/BrowserAdapter.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/BrowserAdapter.java new file mode 100644 index 0000000000..8aa226b659 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/BrowserAdapter.java @@ -0,0 +1,203 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Iterator; + +/** + * Generic implementation of ClientAdapter for browser clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: BrowserAdapter.java,v 1.6 2007/11/09 13:15:35 justb Exp $ + */ +public class BrowserAdapter implements ClientAdapter, Protocol { + + public static final String START_DOCUMENT = + "" + + "" + + "\n"; + public static final String END_DOCUMENT = ""; + + private PrintWriter servletOut; + private HttpServletResponse servletRsp; + private int bytesSent; + + /** + * Constructor. + */ + public BrowserAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + /** + * Generic init. + */ + public void start() throws IOException { + // Keep servlet request/response objects until page ends in stop() + // Content type as HTML + servletRsp.setStatus(HttpServletResponse.SC_OK); + servletRsp.setContentType("text/html;charset=UTF-8"); + + // http://www.junlu.com/msg/45902.html + // Log.debug("bufsize=" + aRsp.getBufferSize()); + servletOut = servletRsp.getWriter(); + send(START_DOCUMENT); + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + Log.debug("BCA event=" + anEvent.toXML()); + + // Check if we should refresh + if (anEvent.getEventType().equals(Protocol.E_REFRESH)) { + // Append refresh and tail of HTML document + // Construct the JS callback line to be sent as last line of doc. + // This will refresh the request using the unique id to determine + // the subscriber instance on the server. The client will wait for + // a number of milliseconds. + long refreshWaitMillis = Long.parseLong(anEvent.getField(P_WAIT)); + + // Create servlet request for requesting next events (refresh) + String url = anEvent.getField(P_URL); + String jsRefreshTrigger = "\n"; + + + send(jsRefreshTrigger + END_DOCUMENT); + } else { + send(event2JavaScript(anEvent)); + } + } + + /** + * End HTML page in client browser. + */ + public void stop() { + // To be garbage collected if adapter remains active + servletOut = null; + } + + /** + * Send any string to browser. + */ + protected void send(String s) throws IOException { + // Send string to browser. + // Log.debug("Adapter: sending: " + s); + if (servletOut == null) { + throw new IOException("Client adapter was stopped"); + } + + servletOut.print(s); + + servletOut.flush(); + + // Note: this doesn't seem to have effect + // in Tomcat 4/5 if the client already disconnected. + servletRsp.flushBuffer(); + + bytesSent += s.length(); + Log.debug("bytesSent= " + bytesSent); + // Log.debug("BCA sent event: " + s); + } + + /** + * Converts the Java Event to a JavaScript function call in browser page. + */ + protected String event2JavaScript(Event event) throws IOException { + + // Convert the event to a comma-separated string. + String jsArgs = ""; + for (Iterator iter = event.getFieldNames(); iter.hasNext();) { + String name = (String) iter.next(); + String value = event.getField(name); + String nextArgument = (jsArgs.equals("") ? "" : ",") + "'" + name + "'" + ", \"" + value + "\""; + jsArgs += nextArgument; + } + + // Construct and return the function call */ + return ""; + } + +} + +/* + * $Log: BrowserAdapter.java,v $ + * Revision 1.6 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.5 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:44 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.12 2005/02/15 13:30:23 justb + * changes for Tomcat buffering (now working in tc4 and 5.0) + * + * Revision 1.11 2005/01/24 22:45:58 justb + * getting safari to work + * + * Revision 1.10 2005/01/18 16:46:27 justb + * buffer size setting ignored by tomcat workings + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:07 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:02 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/10/30 14:15:47 just + * no message + * + * + */ + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ClientAdapter.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ClientAdapter.java new file mode 100644 index 0000000000..c7ea141fee --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ClientAdapter.java @@ -0,0 +1,72 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.IOException; + +/** + * Adapter interface for encapsulation of specific HTTP clients. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ClientAdapter.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public interface ClientAdapter { + + /** + * Start event push. + */ + public void start() throws IOException; + + /** + * Push single Event to client. + */ + public void push(Event anEvent) throws IOException; + + /** + * Stop event push. + */ + public void stop() throws IOException; +} + +/* + * $Log: ClientAdapter.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/21 11:50:45 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:30 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Command.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Command.java new file mode 100644 index 0000000000..dbba4fae76 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Command.java @@ -0,0 +1,158 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Servlets; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Wraps pushlet request/response data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Command.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +public class Command implements Protocol { + + /** + * Pushlet request event. + */ + public final Event reqEvent; + + /** + * Pushlet response event. + */ + private Event rspEvent; + + /** + * HTTP Servlet GET/POST request. + */ + public final HttpServletRequest httpReq; + + /** + * HTTP Servlet GET/POST response. + */ + public final HttpServletResponse httpRsp; + + /** + * Pushlet session. + */ + public final Session session; + + /** + * Per-response client adapter. + */ + private ClientAdapter clientAdapter; + + /** + * Constructor. + */ + private Command(Session aSession, Event aRequestEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + session = aSession; + reqEvent = aRequestEvent; + httpReq = aHTTPReq; + httpRsp = aHTTPRsp; + } + + /** + * Create new Command object. + */ + public static Command create(Session aSession, Event aReqEvent, HttpServletRequest aHTTPReq, HttpServletResponse aHTTPRsp) { + return new Command(aSession, aReqEvent, aHTTPReq, aHTTPRsp); + } + + /** + * Set pushlet response event. + */ + public void setResponseEvent(Event aResponseEvent) { + rspEvent = aResponseEvent; + } + + /** + * Get pushlet response event. + */ + public Event getResponseEvent() { + return rspEvent; + } + + /** + * Get client adapter for request. + */ + public ClientAdapter getClientAdapter() throws PushletException { + if (clientAdapter == null) { + // Create and initialize client-specific adapter. + clientAdapter = createClientAdapter(); + } + return clientAdapter; + } + + /** + * Create client notifier based on "format" parameter passed in request. + */ + protected ClientAdapter createClientAdapter() throws PushletException { + + // Assumed to be set by parent. + String outputFormat = session.getFormat(); + + // Determine client adapter to create. + if (outputFormat.equals(FORMAT_JAVASCRIPT)) { + // Client expects to receive Events as JavaScript dispatch calls.. + return new BrowserAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_SERIALIZED_JAVA_OBJECT)) { + // Client expects to receive Events as Serialized Java Objects. + return new SerializedAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML)) { + // Client expects to receive Events as stream of XML docs. + return new XMLAdapter(httpRsp); + } else if (outputFormat.equals(FORMAT_XML_STRICT)) { + // Client expects to receive Events embedded in single XML doc. + return new XMLAdapter(httpRsp, true); + } else { + throw new PushletException("Null or invalid output format: " + outputFormat); + } + } + + /** + * Sends HTTP response headers. + */ + protected void sendResponseHeaders() { + // Just to try to prevent caching in any form. + Servlets.setNoCacheHeaders(httpRsp); + + // Close connection for Java enabled browsers + if (session.getUserAgent().indexOf("java") > 0) { + // The connection should be closed after this request + // NB: this allows sending a "long response". Some clients + // in particular java.net.URL in VMs > 1.1 that use HTTP/1.1 + // will block if + // - the content length is not sent + // - if Connection: close HTTP header is not sent. + // + // Since we don't know the content length we will assume + // the underlying servlet engine will use chunked encoding. + httpRsp.setHeader("Connection", "close"); + } + } + + +} + +/* + * $Log: Command.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.2 2005/02/28 17:25:15 justb + * commented + * + * Revision 1.1 2005/02/28 12:45:59 justb + * introduced Command class + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Config.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Config.java new file mode 100644 index 0000000000..c598e033d7 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Config.java @@ -0,0 +1,152 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Sys; + +import java.io.File; +import java.util.Properties; + +/** + * Loads and maintains overall configuration. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Config.java,v 1.5 2007/11/23 21:10:17 justb Exp $ + */ +public class Config implements ConfigDefs { + private static final String PROPERTIES_FILE = "pushlet.properties"; + private static Properties properties; + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return an instance of class denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Object createObject(String aClassNameProp, String aDefault) throws PushletException { + Class clazz = getClass(aClassNameProp, aDefault); + try { + return clazz.newInstance(); + } catch (Throwable t) { + // Usually a misconfiguration + throw new PushletException("Cannot instantiate class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Factory method: create object from property denoting class name. + * + * @param aClassNameProp property name e.g. "session.class" + * @return a Class object denoted by property + * @throws PushletException when class cannot be instantiated + */ + public static Class getClass(String aClassNameProp, String aDefault) throws PushletException { + // Singleton + factory pattern: create object instance + // from configured class name + String clazz = (aDefault == null ? getProperty(aClassNameProp) : getProperty(aClassNameProp, aDefault)); + + try { + return Class.forName(clazz); + } catch (ClassNotFoundException t) { + // Usually a misconfiguration + throw new PushletException("Cannot find class for " + aClassNameProp + "=" + clazz, t); + } + } + + /** + * Initialize event sources from properties file. + */ + public static void load(String aDirPath) { + // Load Event sources using properties file. + try { + // Try loading through classpath first (e.g. in WEB-INF/classes or from .jar) + Log.info("Config: loading " + PROPERTIES_FILE + " from classpath"); + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("Config: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("Config: cannot load properties file from " + filePath, t); + + // Give up + return; + } + } + + Log.info("Config: loaded values=" + properties); + } + + public static String getProperty(String aName, String aDefault) { + return properties.getProperty(aName, aDefault); + } + + public static String getProperty(String aName) { + String value = properties.getProperty(aName); + if (value == null) { + throw new IllegalArgumentException("Unknown property: " + aName); + } + return value; + } + + public static boolean getBoolProperty(String aName) { + String value = getProperty(aName); + try { + return value.equals("true"); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static int getIntProperty(String aName) { + String value = getProperty(aName); + try { + return Integer.parseInt(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static long getLongProperty(String aName) { + String value = getProperty(aName); + try { + return Long.parseLong(value); + } catch (Throwable t) { + throw new IllegalArgumentException("Illegal property value: " + aName + " val=" + value); + } + } + + public static boolean hasProperty(String aName) { + return properties.containsKey(aName); + } + + +} + +/* + * $Log: Config.java,v $ + * Revision 1.5 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ConfigDefs.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ConfigDefs.java new file mode 100644 index 0000000000..df00d41beb --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/ConfigDefs.java @@ -0,0 +1,104 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Definition of config property strings. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: ConfigDefs.java,v 1.9 2007/12/07 12:57:40 justb Exp $ + */ +public interface ConfigDefs { + /** + * Class factory definitions, used to insert your custom classes. + */ + public static final String CONTROLLER_CLASS = "controller.class"; + public static final String DISPATCHER_CLASS = "dispatcher.class"; + public static final String LOGGER_CLASS = "logger.class"; + public static final String SESSION_MANAGER_CLASS = "sessionmanager.class"; + public static final String SESSION_CLASS = "session.class"; + public static final String SUBSCRIBER_CLASS = "subscriber.class"; + public static final String SUBSCRIPTION_CLASS = "subscription.class"; + + /** + * Session management. + */ + public static final String SESSION_ID_SIZE = "session.id.size"; + public static final String SESSION_ID_GENERATION = "session.id.generation"; + public static final String SESSION_ID_GENERATION_UUID = "uuid"; + public static final String SESSION_ID_GENERATION_RANDOMSTRING = "randomstring"; + public static final String SESSION_TIMEOUT_MINS = "session.timeout.mins"; + + public static final String SOURCES_ACTIVATE = "sources.activate"; + + /** + * Logging + */ + public static final String LOG_LEVEL = "log.level"; + public static final int LOG_LEVEL_FATAL = 1; + public static final int LOG_LEVEL_ERROR = 2; + public static final int LOG_LEVEL_WARN = 3; + public static final int LOG_LEVEL_INFO = 4; + public static final int LOG_LEVEL_DEBUG = 5; + public static final int LOG_LEVEL_TRACE = 6; + + /** + * Queues + */ + public static final String QUEUE_SIZE = "queue.size"; + public static final String QUEUE_READ_TIMEOUT_MILLIS = "queue.read.timeout.millis"; + public static final String QUEUE_WRITE_TIMEOUT_MILLIS = "queue.write.timeout.millis"; + + /** + * Listening modes. + */ + public static final String LISTEN_FORCE_PULL_ALL = "listen.force.pull.all"; + public static final String LISTEN_FORCE_PULL_AGENTS = "listen.force.pull.agents"; + + + public static final String PULL_REFRESH_TIMEOUT_MILLIS = "pull.refresh.timeout.millis"; + public static final String PULL_REFRESH_WAIT_MIN_MILLIS = "pull.refresh.wait.min.millis"; + public static final String PULL_REFRESH_WAIT_MAX_MILLIS = "pull.refresh.wait.max.millis"; + + + public static final String POLL_REFRESH_TIMEOUT_MILLIS = "poll.refresh.timeout.millis"; + public static final String POLL_REFRESH_WAIT_MIN_MILLIS = "poll.refresh.wait.min.millis"; + public static final String POLL_REFRESH_WAIT_MAX_MILLIS = "poll.refresh.wait.max.millis"; + +} + +/* + * $Log: ConfigDefs.java,v $ + * Revision 1.9 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.8 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2007/11/10 14:48:35 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/21 16:59:00 justb + * SessionManager and session lease introduced + * + * Revision 1.3 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.2 2005/02/21 11:16:44 justb + * add log level config prop + * + * Revision 1.1 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * + * + */ + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Controller.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Controller.java new file mode 100644 index 0000000000..ca90b1539e --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Controller.java @@ -0,0 +1,502 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; + +import java.io.IOException; + +/** + * Handles servlet requests from client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Controller.java,v 1.9 2007/11/23 14:33:07 justb Exp $ + */ +public class Controller implements Protocol, ConfigDefs { + + private Session session; + + /** + * Protected constructor as we create through factory method. + */ + protected Controller() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Controller object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Controller create(Session aSession) throws PushletException { + Controller controller; + try { + controller = (Controller) Config.getClass(CONTROLLER_CLASS, "nl.justobjects.pushlet.core.Controller").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Controller from config", t); + } + controller.session = aSession; + return controller; + } + + /** + * Handle command. + */ + public void doCommand(Command aCommand) { + try { + // Update lease time to live + session.kick(); + + // Set remote IP address of client + session.setAddress(aCommand.httpReq.getRemoteAddr()); + + debug("doCommand() event=" + aCommand.reqEvent); + + // Get event type + String eventType = aCommand.reqEvent.getEventType(); + + // Determine action based on event type + if (eventType.equals(Protocol.E_REFRESH)) { + // Pull/poll mode clients that refresh + doRefresh(aCommand); + } else if (eventType.equals(Protocol.E_SUBSCRIBE)) { + // Subscribe + doSubscribe(aCommand); + } else if (eventType.equals(Protocol.E_UNSUBSCRIBE)) { + // Unsubscribe + doUnsubscribe(aCommand); + } else if (eventType.equals(Protocol.E_JOIN)) { + // Join + doJoin(aCommand); + } else if (eventType.equals(Protocol.E_JOIN_LISTEN)) { + // Join and listen (for simple and e.g. REST apps) + doJoinListen(aCommand); + } else if (eventType.equals(Protocol.E_LEAVE)) { + // Leave + doLeave(aCommand); + } else if (eventType.equals(Protocol.E_HEARTBEAT)) { + // Heartbeat mainly to do away with browser "busy" cursor + doHeartbeat(aCommand); + } else if (eventType.equals(Protocol.E_PUBLISH)) { + // Publish event + doPublish(aCommand); + } else if (eventType.equals(Protocol.E_LISTEN)) { + // Listen to pushed events + doListen(aCommand); + } + + // Handle response back to client + if (eventType.endsWith(Protocol.E_LISTEN) || + eventType.equals(Protocol.E_REFRESH)) { + // Data channel events + // Loops until refresh or connection closed + getSubscriber().fetchEvents(aCommand); + + } else { + // Send response for control commands + sendControlResponse(aCommand); + } + + } catch (Throwable t) { + warn("Exception in doCommand(): " + t); + t.printStackTrace(); + } + } + + public String toString() { + return session.toString(); + } + + /** + * Handle heartbeat event. + */ + protected void doHeartbeat(Command aCommand) { + + // Set heartbeat acknowledgement to client + aCommand.setResponseEvent(new Event(E_HEARTBEAT_ACK)); + } + + /** + * Handle Join request. + */ + protected void doJoin(Command aCommand) throws PushletException { + + Event responseEvent = null; + + try { + + session.start(); + + // Determine format for encoding Events to client. + // Default assume a userAgent window on the other end. + String format = aCommand.reqEvent.getField(P_FORMAT, FORMAT_JAVASCRIPT); + + session.setFormat(format); + responseEvent = new Event(E_JOIN_ACK); + + // Set unique subscriber id and encoding format + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_FORMAT, format); + info("joined"); + } catch (Throwable t) { + session.stop(); + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doJoin() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle JoinListen request. + */ + protected void doJoinListen(Command aCommand) throws PushletException { + + // Basically bundles a join and a listen + // This request is handly for simple apps that + // need to do a single request to get events immediately + // For example in RESTful apps. + + // First do regular join + doJoin(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If successful do the listen + doListen(aCommand); + if (!aCommand.getResponseEvent().getEventType().equals(E_NACK)) { + // If still ok do the listen ack + aCommand.getResponseEvent().setField(P_EVENT, E_JOIN_LISTEN_ACK); + } + } + } + + /** + * Handle Leave request. + */ + protected void doLeave(Command aCommand) throws IOException { + + Event responseEvent = null; + + try { + // Also removes all subscriptions + session.stop(); + + // Prepare acknowledgement + responseEvent = new Event(E_LEAVE_ACK); + + // Set unique subscriber id + responseEvent.setField(P_ID, session.getId()); + info("left"); + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doLeave() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + + } + + /** + * Handle Listen request. + */ + protected void doListen(Command aCommand) throws PushletException { + + + String mode = MODE_STREAM; + // Should we always force "pull" mode ? + if (Config.getBoolProperty(LISTEN_FORCE_PULL_ALL)) { + mode = MODE_PULL; + } else { + // Determine optimal mode determined by parameter and/or user agent + // Mode param determines how events are transfered to the client + + // In "stream" mode, a stream of events is sent, i.e. the document + // is neverending. In "pull" or "poll" mode a complete document is returned + // ending with a request to refresh. + mode = aCommand.reqEvent.getField(P_MODE, MODE_STREAM); + + String userAgent = aCommand.httpReq.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + for (int i = 0; i < session.FORCED_PULL_AGENTS.length; i++) { + if ((userAgent.indexOf(session.FORCED_PULL_AGENTS[i]) != -1)) { + info("Forcing pull mode for agent=" + userAgent); + mode = MODE_PULL; + break; + } + } + } else { + userAgent = "unknown"; + } + } + + getSubscriber().setMode(mode); + + // Prepare acknowledgement + Event listenAckEvent = new Event(E_LISTEN_ACK); + + // Add subscription(s) if subject(s) specified + String subject = aCommand.reqEvent.getField(P_SUBJECT); + if (subject != null) { + // Optional label for subscription + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + + // Add a subscription + Subscription subscription = getSubscriber().addSubscription(subject, label); + + // Add subscription id and optional label to listen-ack event + listenAckEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + listenAckEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + } + + // Set unique subscriber id, push mode and encoding format + listenAckEvent.setField(P_ID, session.getId()); + listenAckEvent.setField(P_MODE, mode); + listenAckEvent.setField(P_FORMAT, session.getFormat()); + + // Activate the subscriber + getSubscriber().start(); + + // Enqueue listen ack event on data channel + aCommand.setResponseEvent(listenAckEvent); + + info("Listening mode=" + mode + " userAgent=" + session.getUserAgent()); + + } + + /** + * Handle Publish request. + */ + protected void doPublish(Command aCommand) { + Event responseEvent = null; + + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + aCommand.reqEvent.setField(P_FROM, session.getId()); + aCommand.reqEvent.setField(P_EVENT, E_DATA); + + // Event may be targeted to specific user (p_to field) + String to = aCommand.reqEvent.getField(P_TO); + if (to != null) { + Dispatcher.getInstance().unicast(aCommand.reqEvent, to); + } else { + // No to: multicast + debug("doPublish() event=" + aCommand.reqEvent); + Dispatcher.getInstance().multicast(aCommand.reqEvent); + } + + // Acknowledge + responseEvent = new Event(E_PUBLISH_ACK); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doPublish() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle refresh event. + */ + protected void doRefresh(Command aCommand) { + // Set ack + aCommand.setResponseEvent(new Event(E_REFRESH_ACK)); + } + + /** + * Handle Subscribe request. + */ + protected void doSubscribe(Command aCommand) throws IOException { + + Event responseEvent = null; + try { + String subject = aCommand.reqEvent.getField(Protocol.P_SUBJECT); + Subscription subscription = null; + if (subject == null) { + // Return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subject provided"); + } else { + + String label = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_LABEL); + subscription = getSubscriber().addSubscription(subject, label); + + // Acknowledge + responseEvent = new Event(E_SUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBJECT, subject); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (label != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, label); + } + info("subscribed to " + subject + " sid=" + subscription.getId()); + } + + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doSubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + /** + * Handle Unsubscribe request. + */ + protected void doUnsubscribe(Command aCommand) throws IOException { + + + Event responseEvent = null; + try { + String subscriptionId = aCommand.reqEvent.getField(Protocol.P_SUBSCRIPTION_ID); + if (subscriptionId == null) { + // Unsuscbribe all + getSubscriber().removeSubscriptions(); + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + info("unsubscribed all"); + } else { + // Subscription id provided: remove Subscription + Subscription subscription = getSubscriber().removeSubscription(subscriptionId); + if (subscription == null) { + // Unknown subscription id: return error response + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "no subscription for sid=" + subscriptionId); + warn("unsubscribe: no subscription for sid=" + subscriptionId); + } else { + // OK return ack + responseEvent = new Event(E_UNSUBSCRIBE_ACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + responseEvent.setField(P_SUBJECT, subscription.getSubject()); + if (subscription.getLabel() != null) { + responseEvent.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + info("unsubscribed sid= " + subscriptionId); + } + } + } catch (Throwable t) { + responseEvent = new Event(E_NACK); + responseEvent.setField(P_ID, session.getId()); + responseEvent.setField(P_REASON, "unexpected error: " + t); + warn("doUnsubscribe() error: " + t); + t.printStackTrace(); + } finally { + // Always set response event in command + aCommand.setResponseEvent(responseEvent); + } + } + + public Subscriber getSubscriber() { + return session.getSubscriber(); + } + + /** + * Send response on the control channel. + */ + protected void sendControlResponse(Command aCommand) { + try { + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + aCommand.getClientAdapter().start(); + + // Push to client through client adapter + aCommand.getClientAdapter().push(aCommand.getResponseEvent()); + + // One shot response + aCommand.getClientAdapter().stop(); + } catch (Throwable t) { + session.stop(); + } + } + + + /** + * Info. + */ + protected void info(String s) { + session.info("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Controller] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Controller] " + s); + } + + +} + +/* + * $Log: Controller.java,v $ + * Revision 1.9 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.8 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.7 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:00 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Dispatcher.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Dispatcher.java new file mode 100644 index 0000000000..5cd739d5bd --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Dispatcher.java @@ -0,0 +1,265 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Routes Events to Subscribers. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Dispatcher.java,v 1.9 2007/12/04 13:55:53 justb Exp $ + */ +public class Dispatcher implements Protocol, ConfigDefs { + /** + * Singleton pattern: single instance. + */ + private static Dispatcher instance; + protected SessionManagerVisitor sessionManagerVisitor; + + static { + try { + instance = (Dispatcher) Config.getClass(DISPATCHER_CLASS, "nl.justobjects.pushlet.core.Dispatcher").newInstance(); + Log.info("Dispatcher created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate Dispatcher from config", t); + } + } + + /** + * Singleton pattern with factory method: protected constructor. + */ + protected Dispatcher() { + + } + + /** + * Singleton pattern: get single instance. + */ + public static Dispatcher getInstance() { + return instance; + } + + /** + * Send event to all subscribers. + */ + public synchronized void broadcast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Object[] args = new Object[2]; + args[1] = anEvent; + Method method = sessionManagerVisitor.getMethod("visitBroadcast"); + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + /** + * Send event to subscribers matching Event subject. + */ + public synchronized void multicast(Event anEvent) { + try { + // Let the SessionManager loop through Sessions, calling + // our Visitor Method for each Session. This is done to guard + // synchronization with SessionManager and to optimize by + // not getting an array of all sessions. + Method method = sessionManagerVisitor.getMethod("visitMulticast"); + Object[] args = new Object[2]; + args[1] = anEvent; + SessionManager.getInstance().apply(sessionManagerVisitor, method, args); + } catch (Throwable t) { + Log.error("Error calling SessionManager.apply: ", t); + } + } + + + /** + * Send event to specific subscriber. + */ + public synchronized void unicast(Event event, String aSessionId) { + // Get subscriber to send event to + Session session = SessionManager.getInstance().getSession(aSessionId); + if (session == null) { + Log.warn("unicast: session with id=" + aSessionId + " does not exist"); + return; + } + + // Send Event to subscriber. + session.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Start Dispatcher. + */ + public void start() throws PushletException { + Log.info("Dispatcher started"); + + // Create callback for SessionManager visits. + sessionManagerVisitor = new SessionManagerVisitor(); + } + + /** + * Stop Dispatcher. + */ + public void stop() { + // Send abort control event to all subscribers. + Log.info("Dispatcher stopped: broadcast abort to all subscribers"); + broadcast(new Event(E_ABORT)); + } + + /** + * Supplies Visitor methods for callbacks from SessionManager. + */ + private class SessionManagerVisitor { + private final Map visitorMethods = new HashMap(2); + + SessionManagerVisitor() throws PushletException { + + try { + // Setup Visitor Methods for callback from SessionManager + // This is a slight opitmization over creating Method objects + // on each invokation. + Class[] argsClasses = {Session.class, Event.class}; + visitorMethods.put("visitMulticast", this.getClass().getMethod("visitMulticast", argsClasses)); + visitorMethods.put("visitBroadcast", this.getClass().getMethod("visitBroadcast", argsClasses)); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup SessionManagerVisitor", e); + } + } + + /** + * Return Visitor Method by name. + */ + public Method getMethod(String aName) { + return (Method) visitorMethods.get(aName); + + } + + /** + * Visitor method called by SessionManager. + */ + public void visitBroadcast(Session aSession, Event event) { + aSession.getSubscriber().onEvent((Event) event.clone()); + } + + /** + * Visitor method called by SessionManager. + */ + public void visitMulticast(Session aSession, Event event) { + Subscriber subscriber = aSession.getSubscriber(); + Event clonedEvent; + Subscription subscription; + + // Send only if the subscriber's criteria + // match the event. + if ((subscription = subscriber.match(event)) != null) { + // Personalize event + clonedEvent = (Event) event.clone(); + + // Set subscription id and optional label + clonedEvent.setField(P_SUBSCRIPTION_ID, subscription.getId()); + if (subscription.getLabel() != null) { + event.setField(P_SUBSCRIPTION_LABEL, subscription.getLabel()); + } + + subscriber.onEvent(clonedEvent); + } + } + } +} + +/* + * $Log: Dispatcher.java,v $ + * Revision 1.9 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.6 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.5 2005/02/21 16:59:06 justb + * SessionManager and session lease introduced + * + * Revision 1.4 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.3 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.2 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.1 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.14 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.13 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.12 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.11 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.10 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.9 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.8 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.7 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.6 2004/03/10 15:45:55 justb + * many cosmetic changes + * + * Revision 1.5 2004/03/10 13:59:28 justb + * rewrite using Collection classes and finer synchronization + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 08:54:40 justb + * added getSubscriberCount() and use Log + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Event.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Event.java new file mode 100644 index 0000000000..e9a0aaa48b --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Event.java @@ -0,0 +1,184 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Sys; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Represents the event data. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Event.java,v 1.13 2007/11/23 14:33:07 justb Exp $ + */ +public class Event implements Protocol, Serializable { + + protected Map attributes = new HashMap(3); + + public Event(String anEventType) { + this(anEventType, null); + } + + public Event(String anEventType, Map theAttributes) { + + if (theAttributes != null) { + setAttrs(theAttributes); + } + + // Set required field event type + setField(P_EVENT, anEventType); + + // Set time in seconds since 1970 + setField(P_TIME, System.currentTimeMillis() / 1000); + } + + public Event(Map theAttributes) { + if (!theAttributes.containsKey(P_EVENT)) { + throw new IllegalArgumentException(P_EVENT + " not found in attributes"); + } + setAttrs(theAttributes); + } + + public static Event createDataEvent(String aSubject) { + return createDataEvent(aSubject, null); + } + + public static Event createDataEvent(String aSubject, Map theAttributes) { + Event dataEvent = new Event(E_DATA, theAttributes); + dataEvent.setField(P_SUBJECT, aSubject); + return dataEvent; + } + + public String getEventType() { + return getField(P_EVENT); + } + + public String getSubject() { + return getField(P_SUBJECT); + } + + public void setField(String name, String value) { + attributes.put(name, value); + } + + public void setField(String name, int value) { + attributes.put(name, value + ""); + } + + public void setField(String name, long value) { + attributes.put(name, value + ""); + } + + public String getField(String name) { + return (String) attributes.get(name); + } + + /** + * Return field; if null return default. + */ + public String getField(String name, String aDefault) { + String result = getField(name); + return result == null ? aDefault : result; + } + + public Iterator getFieldNames() { + return attributes.keySet().iterator(); + } + + public String toString() { + return attributes.toString(); + } + + /** + * Convert to HTTP query string. + */ + public String toQueryString() { + String queryString = ""; + String amp = ""; + for (Iterator iter = getFieldNames(); iter.hasNext();) { + String nextAttrName = (String) iter.next(); + String nextAttrValue = getField(nextAttrName); + queryString = queryString + amp + nextAttrName + "=" + nextAttrValue; + // After first add "&". + amp = "&"; + } + + return queryString; + } + + public String toXML(boolean strict) { + String xmlString = " +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import java.io.*; +import java.util.HashMap; + +/** + * Parses XML into Event objects. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventParser.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventParser { + + + private EventParser() { + } + + /** + * Parse Event from a File. + */ + public static Event parse(File aFile) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(aFile)); + return parse(br); + } + + /** + * Parse Event from input Reader. + */ + public static Event parse(Reader aReader) throws IOException { + StringBuffer preparsedString = new StringBuffer(24); + + // First find the opening tag ('<') + char nextChar; + while ((nextChar = (char) aReader.read()) != '<') ; + + // Append '<' + preparsedString.append(nextChar); + + // Then find end-tag ('>'), appending all chars to preparsed string. + do { + nextChar = (char) aReader.read(); + preparsedString.append(nextChar); + } while (nextChar != '>'); + + return parse(preparsedString.toString()); + } + + /** + * Parse Event from a String. + */ + public static Event parse(String aString) throws IOException { + aString = aString.trim(); + + if (!aString.startsWith("<") || !aString.endsWith("/>")) { + throw new IOException("No start or end tag found while parsing event [" + aString + "]"); + } + + // Create the attributes object. + HashMap properties = new HashMap(3); + + // Remove the start and end (< ... />) from the string + aString = aString.substring(1, aString.length() - 2).trim(); + + int index = 0; + + // Parse the tag + while (!Character.isWhitespace(aString.charAt(index)) + && (index < aString.length())) { + index++; + } + + // We don't use the tag: remove from string + aString = aString.substring(index).trim(); + index = 0; + + String attrName; + String attrValue; + + while (index < aString.length()) { + + // Parse attribute name + while ((aString.charAt(index) != '=') + && (index < aString.length())) { + index++; + } + + // Create attr name string + attrName = aString.substring(0, index).trim(); + + // remove the attributeName and the '=' from the string + aString = aString.substring(index + 1).trim(); + index = 1; // read past the first wrapping "\"" + + // Parse attribute value + while ((aString.charAt(index) != '\"') + && (index < aString.length())) { + + // bypass the special characters '\' and '"' inside the + // attributevalue itself which are deliniated with a preceding + // '\' + if (aString.charAt(index) == '\\') { + aString = aString.substring(0, index) + + aString.substring(index + 1); // remove the '\' + } + + index++; + } + + // create the attribute value; exclude the wrapping quote-characters + attrValue = aString.substring(1, index); + + // Set the attribute N/V + properties.put(attrName, attrValue); + + aString = aString.substring(index + 1).trim(); + index = 0; + } + + return new Event(properties); + } + + /** + * Test method: use files to test. + */ + public static void main(String[] args) { + try { + Event event = parse(new File(args[0])); + System.out.println("OK parsed Event file " + args[0]); + System.out.println(event.toXML()); + + event = parse(event.toXML()); + System.out.println("OK parsed Event string"); + System.out.println(event.toXML()); + } catch (Throwable t) { + System.out.println("Error parsing event file: " + args[0]); + t.printStackTrace(); + } + } +} + +/* + * $Log: EventParser.java,v $ + * Revision 1.3 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.2 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.3 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/05/18 16:12:27 justb + * adding support for XML encoded Events + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventPullSource.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventPullSource.java new file mode 100644 index 0000000000..cf63d98389 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventPullSource.java @@ -0,0 +1,185 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventPullSource.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * ABC for specifc EventPullSources. + */ +abstract public class EventPullSource implements EventSource, Runnable { + private volatile boolean alive = false; + private volatile boolean active = false; + private static int threadNum = 0; + private Thread thread; + + public EventPullSource() { + } + + abstract protected long getSleepTime(); + + abstract protected Event pullEvent(); + + public void start() { + thread = new Thread(this, "EventPullSource-" + (++threadNum)); + thread.setDaemon(true); + thread.start(); + } + + public boolean isAlive() { + return alive; + } + + /** + * Stop the event generator thread. + */ + public void stop() { + alive = false; + + if (thread != null) { + thread.interrupt(); + thread = null; + } + + } + + /** + * Activate the event generator thread. + */ + synchronized public void activate() { + if (active) { + return; + } + active = true; + if (!alive) { + start(); + return; + } + Log.debug(getClass().getName() + ": notifying..."); + notifyAll(); + } + + /** + * Deactivate the event generator thread. + */ + public void passivate() { + if (!active) { + return; + } + active = false; + } + + /** + * Main loop: sleep, generate event and publish. + */ + public void run() { + Log.debug(getClass().getName() + ": starting..."); + alive = true; + while (alive) { + try { + + Thread.sleep(getSleepTime()); + + // Stopped during sleep: end loop. + if (!alive) { + break; + } + + // If passivated wait until we get + // get notify()-ied. If there are no subscribers + // it wasts CPU to remain producing events... + synchronized (this) { + while (!active) { + Log.debug(getClass().getName() + ": waiting..."); + wait(); + } + } + + } catch (InterruptedException e) { + break; + } + + try { + // Derived class should produce an event. + Event event = pullEvent(); + + // Let the publisher push it to subscribers. + Dispatcher.getInstance().multicast(event); + } catch (Throwable t) { + Log.warn("EventPullSource exception while multicasting ", t); + t.printStackTrace(); + } + } + Log.debug(getClass().getName() + ": stopped"); + } +} + +/* + * $Log: EventPullSource.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.13 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.12 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:57:05 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventQueue.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventQueue.java new file mode 100644 index 0000000000..85c730e2d7 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventQueue.java @@ -0,0 +1,269 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +/** + * FIFO queue with guarded suspension. + * Purpose
      + *

      + * Implementation
      + * FIFO queue class implemented with circular array. The enQueue() and + * deQueue() methods use guarded suspension according to a readers/writers + * pattern, implemented with java.lang.Object.wait()/notify(). + *

      + * Examples
      + *

      + *
      + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventQueue.java,v 1.3 2007/11/23 14:33:07 justb Exp $ + */ +public class EventQueue { + /** + * Defines maximum queue size + */ + private int capacity = 8; + private Event[] queue = null; + private int front, rear; + + /** + * Construct queue with default (8) capacity. + */ + public EventQueue() { + this(8); + } + + /** + * Construct queue with specified capacity. + */ + public EventQueue(int capacity) { + this.capacity = capacity; + queue = new Event[capacity]; + front = rear = 0; + } + + /** + * Put item in queue; waits() indefinitely if queue is full. + */ + public synchronized boolean enQueue(Event item) throws InterruptedException { + return enQueue(item, -1); + } + + /** + * Put item in queue; if full wait maxtime. + */ + public synchronized boolean enQueue(Event item, long maxWaitTime) throws InterruptedException { + + // Wait (optional maxtime) as long as the queue is full + while (isFull()) { + if (maxWaitTime > 0) { + // Wait at most maximum time + wait(maxWaitTime); + + // Timed out or woken; if still full we + // had bad luck and return failure. + if (isFull()) { + return false; + } + } else { + wait(); + } + } + + // Put item in queue + queue[rear] = item; + rear = next(rear); + + // Wake up waiters; NOTE: first waiter will eat item + notifyAll(); + return true; + } + + /** + * Get head; if empty wait until something in queue. + */ + public synchronized Event deQueue() throws InterruptedException { + return deQueue(-1); + } + + /** + * Get head; if empty wait for specified time at max. + */ + public synchronized Event deQueue(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue item + Event result = fetchNext(); + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return result; + } + + /** + * Get all queued Events. + */ + public synchronized Event[] deQueueAll(long maxWaitTime) throws InterruptedException { + while (isEmpty()) { + if (maxWaitTime >= 0) { + wait(maxWaitTime); + + // Timed out or woken; if still empty we + // had bad luck and return failure. + if (isEmpty()) { + return null; + } + } else { + // Wait indefinitely for something in queue. + wait(); + } + } + + // Dequeue all items item + Event[] events = new Event[getSize()]; + for (int i = 0; i < events.length; i++) { + events[i] = fetchNext(); + } + + // Notify possible wait()-ing enQueue()-ers + notifyAll(); + + // Return dequeued item + return events; + } + + public synchronized int getSize() { + return (rear >= front) ? (rear - front) : (capacity - front + rear); + } + + /** + * Is the queue empty ? + */ + public synchronized boolean isEmpty() { + return front == rear; + } + + /** + * Is the queue full ? + */ + public synchronized boolean isFull() { + return (next(rear) == front); + } + + /** + * Circular counter. + */ + private int next(int index) { + return (index + 1 < capacity ? index + 1 : 0); + } + + /** + * Circular counter. + */ + private Event fetchNext() { + Event temp = queue[front]; + queue[front] = null; + front = next(front); + return temp; + } + + public static void p(String s) { + System.out.println(s); + } + + public static void main(String[] args) { + EventQueue q = new EventQueue(8); + Event event = new Event("t"); + try { + q.enQueue(event); + p("(1) size = " + q.getSize()); + q.enQueue(event); + p("(2) size = " + q.getSize()); + q.deQueue(); + p("(1) size = " + q.getSize()); + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(3) size = " + q.getSize()); + q.deQueue(); + p("(2) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + q.enQueue(event); + q.enQueue(event); + p("(7) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + p("(4) size = " + q.getSize()); + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(0) size = " + q.getSize()); + + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + q.enQueue(event); + p("(5) size = " + q.getSize()); + + q.deQueue(); + q.deQueue(); + q.deQueue(); + ; + q.deQueue(); + p("(1) size = " + q.getSize()); + } catch (InterruptedException ie) { + } + } +} + +/* +* $Log: EventQueue.java,v $ +* Revision 1.3 2007/11/23 14:33:07 justb +* core classes now configurable through factory +* +* Revision 1.2 2005/02/21 11:50:46 justb +* ohase1 of refactoring Subscriber into Session/Controller/Subscriber +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.6 2005/02/16 12:16:16 justb +* added support for "poll" mode +* +* Revision 1.5 2005/01/13 14:47:15 justb +* control evt: send response on same (control) connection +* +* Revision 1.4 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* +*/ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSource.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSource.java new file mode 100644 index 0000000000..1de0c4a985 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSource.java @@ -0,0 +1,79 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import javax.servlet.ServletContext; + +/** + * Abstract Event source from which Events are pulled. + * + * @version $Id: EventSource.java,v 1.7 2007/11/23 14:33:07 justb Exp $ + * @author Just van den Broecke - Just Objects © + **/ + +/** + * Interface for specifc Event(Pull/Push)Sources. + */ +public interface EventSource { + /** + * Activate the event source. + */ + public void activate(); + + /** + * Deactivate the event source. + */ + public void passivate(); + + /** + * Halt the event source. + */ + public void stop(); + + /** + * @author thomas genin + * gives access to the servlet context of pushlet to the source class + */ + public void setServletContext(ServletContext srvCtxt); + +} + +/* + * $Log: EventSource.java,v $ + * Revision 1.7 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.6 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.5 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSourceManager.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSourceManager.java new file mode 100644 index 0000000000..472b4290cc --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/EventSourceManager.java @@ -0,0 +1,175 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; +import java.io.File; + +import javax.servlet.ServletContext; + +/** + * Maintains lifecycle of event sources. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: EventSourceManager.java,v 1.14 2007/11/10 13:44:02 justb Exp $ + */ +public class EventSourceManager { + private static Vector eventSources = new Vector(0); + private static final String PROPERTIES_FILE = "sources.properties"; + + /** + * Initialize event sources from properties file. + */ + public static void start(String aDirPath,ServletContext srvCtxt) { + // Load Event sources using properties file. + Log.info("EventSourceManager: start"); + + Properties properties = null; + + try { + properties = Sys.loadPropertiesResource(PROPERTIES_FILE); + } catch (Throwable t) { + // Try from provided dir (e.g. WEB_INF/pushlet.properties) + String filePath = aDirPath + File.separator + PROPERTIES_FILE; + Log.info("EventSourceManager: cannot load " + PROPERTIES_FILE + " from classpath, will try from " + filePath); + + try { + properties = Sys.loadPropertiesFile(filePath); + } catch (Throwable t2) { + Log.fatal("EventSourceManager: cannot load properties file from " + filePath, t); + + // Give up + Log.warn("EventSourceManager: not starting local event sources (maybe that is what you want)"); + return; + } + } + + // Create event source collection + eventSources = new Vector(properties.size()); + + // Add the configured sources + for (Enumeration e = properties.keys(); e.hasMoreElements();) { + String nextKey = (String) e.nextElement(); + String nextClass = properties.getProperty(nextKey); + EventSource nextEventSource = null; + try { + nextEventSource = (EventSource) Class.forName(nextClass).newInstance(); + //rajout thomas genin + nextEventSource.setServletContext(srvCtxt); + ////////////////////// + Log.info("created EventSource: key=" + nextKey + " class=" + nextClass); + eventSources.addElement(nextEventSource); + + } catch (Exception ex) { + Log.warn("Cannot create EventSource: class=" + nextClass, ex); + } + } + + activate(); + } + + /** + * Activate all event sources. + */ + public static void activate() { + Log.info("Activating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).activate(); + } + Log.info("EventSources activated"); + } + + /** + * Deactivate all event sources. + */ + public static void passivate() { + Log.info("Passivating " + eventSources.size() + " EventSources"); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).passivate(); + } + Log.info("EventSources passivated"); + } + + /** + * Halt event sources. + */ + public static void stop() { + Log.info("Stopping " + eventSources.size() + " EventSources..."); + for (int i = 0; i < eventSources.size(); i++) { + ((EventSource) eventSources.elementAt(i)).stop(); + } + Log.info("EventSources stopped"); + } + +} + +/* + * $Log: EventSourceManager.java,v $ + * Revision 1.14 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.13 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.12 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.11 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.10 2005/02/15 13:29:49 justb + * use Sys.loadPropertiesResource() + * + * Revision 1.9 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.8 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.7 2004/08/15 16:00:15 justb + * enhancements to pull mode + * + * Revision 1.6 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.5 2004/08/12 13:18:54 justb + * cosmetic changes + * + * Revision 1.4 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.3 2003/08/12 09:41:35 justb + * replace static initalizer with explicit init() + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:17 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/10/30 14:15:47 just + * no message + * + * Revision 1.3 2000/08/31 08:26:54 just + * Changed classloader that loads eventsources.properties to use EventSourceManager's classloader + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Protocol.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Protocol.java new file mode 100644 index 0000000000..79c265f62f --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Protocol.java @@ -0,0 +1,294 @@ +// Copyright (c) 2004 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + + +/** + * Constants for Pushlet protocols. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Protocol.java,v 1.15 2007/11/23 14:33:07 justb Exp $ + */ +public interface Protocol { + /** + * Default URI . + */ + public static final String DEFAULT_SERVLET_URI = "/pushlet/pushlet.srv"; + + // + // Common protocol header/parameter names + // + + /** + * Event type (join, leave, data, subscribe etc) . + */ + public static final String P_EVENT = "p_event"; + + /** + * Time in seconds since 1970 + */ + public static final String P_TIME = "p_time"; + + /** + * Event sequence number, numbers per-client. + */ + public static final String P_SEQ = "p_seq"; + + /** + * Subject (topic) of data event. + */ + public static final String P_SUBJECT = "p_subject"; + + /** + * Originator of Event. + */ + public static final String P_FROM = "p_from"; + + /** + * Addressee of Event, subject or client p_id. + */ + public static final String P_TO = "p_to"; + + /** + * Identifier for client instance within server. + */ + public static final String P_ID = "p_id"; + + /** + * Subscription id, identifies single subscription. + */ + public static final String P_SUBSCRIPTION_ID = "p_sid"; + + /** + * Format to receive events + */ + public static final String P_FORMAT = "p_format"; + + /** + * Protocol mode. + */ + public static final String P_MODE = "p_mode"; + + /** + * Reason for errors. + */ + public static final String P_REASON = "p_reason"; + + /** + * URL attribute. + */ + public static final String P_URL = "p_url"; + + /** + * Wait attribute. + */ + public static final String P_WAIT = "p_wait"; + + /** + * Subscription label, may be used to return user-specific + * token with a data event, e.g. the name of a function for a callback. + */ + public static final String P_SUBSCRIPTION_LABEL = "p_label"; + + // + // Event values with direction for P_EVENT (C=client, S=server) + // + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN = "join"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_ACK = "join-ack"; + + /** + * C-->S Request to join server. + */ + public static final String E_JOIN_LISTEN = "join-listen"; + + /** + * S-->C Acknowledgement of join. + */ + public static final String E_JOIN_LISTEN_ACK = "join-listen-ack"; + + /** + * C-->S Client starts listening. + */ + public static final String E_LISTEN = "listen"; + + /** + * S-->C Ack of listen. + */ + public static final String E_LISTEN_ACK = "listen-ack"; + + /** + * C-->S Client leaves server. + */ + public static final String E_LEAVE = "leave"; + + /** + * S-->C Ack of leave. + */ + public static final String E_LEAVE_ACK = "leave-ack"; + + /** + * C-->S Publish to subject. + */ + public static final String E_PUBLISH = "publish"; + + /** + * S-->C Publish to subject acknowledge. + */ + public static final String E_PUBLISH_ACK = "publish-ack"; + + /** + * C-->S Subscribe to subject request. + */ + public static final String E_SUBSCRIBE = "subscribe"; + + /** + * S-->C Subscribe to subject acknowledge. + */ + public static final String E_SUBSCRIBE_ACK = "subscribe-ack"; + + /** + * C-->S Unsubscribe from subject request. + */ + public static final String E_UNSUBSCRIBE = "unsubscribe"; + + /** + * S--C Unsubscribe from subject acknowledge. + */ + public static final String E_UNSUBSCRIBE_ACK = "unsubscribe-ack"; + + /** + * S-->C Client error response, transitional error. + */ + public static final String E_NACK = "nack"; + + /** + * S-->C Client should abort, permanent error. + */ + public static final String E_ABORT = "abort"; + + /** + * S-->C Data. + */ + public static final String E_DATA = "data"; + + /** + * S-->C or C-->S Heartbeat. + */ + public static final String E_HEARTBEAT = "hb"; + + /** + * S-->C S-->C or C-->S Heartbeat confirmed. + */ + public static final String E_HEARTBEAT_ACK = "hb-ack"; + + /** + * S-->C or C-->S client refresh of data channel. + */ + public static final String E_REFRESH = "refresh"; + + /** + * S-->C client should refresh data channel. + */ + public static final String E_REFRESH_ACK = "refresh-ack"; + + // + // Values for P_FORMAT parameter + // + + /** + * JavaScript callback. + */ + public static String FORMAT_JAVASCRIPT = "js"; + + /** + * Java serialized object. + */ + public static String FORMAT_SERIALIZED_JAVA_OBJECT = "ser"; + + /** + * Stream of XML documents. + */ + public static String FORMAT_XML = "xml"; + + /** + * Single XML document containing zero or more events. + */ + public static String FORMAT_XML_STRICT = "xml-strict"; + + // + // Values for P_MODE parameter + // + public static final String MODE_STREAM = "stream"; + public static final String MODE_PULL = "pull"; + public static final String MODE_POLL = "poll"; + + // + // Values for special/reserved subjects + // TODO: use these to publish events when clients do these actions + // TODO: Dispatcher may intercept these subjects to send cached events + // + public static final String SUBJECT_META = "/meta"; + public static final String SUBJECT_META_SUBS = SUBJECT_META + "/subs"; + public static final String SUBJECT_META_JOINS = SUBJECT_META + "/joins"; + + +} + +/* + * $Log: Protocol.java,v $ + * Revision 1.15 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.14 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.13 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.12 2005/02/28 13:05:59 justb + * introduced join-listen protocol service + * + * Revision 1.11 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.10 2005/02/16 12:16:17 justb + * added support for "poll" mode + * + * Revision 1.9 2005/01/24 22:46:02 justb + * getting safari to work + * + * Revision 1.8 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.7 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.6 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.5 2004/10/24 13:52:52 justb + * small fixes in client lib + * + * Revision 1.4 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.3 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.2 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/09/03 21:02:20 justb + * make more formalized protocol + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SerializedAdapter.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SerializedAdapter.java new file mode 100644 index 0000000000..462a4dd5c2 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SerializedAdapter.java @@ -0,0 +1,99 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.ObjectOutputStream; + +/** + * Implementation of ClientAdapter that sends Events as serialized objects. + *

      + * NOTE: You are discouraged to use this adapter, since it is Java-only + * and may have JVM-specific problems. Far better choice is to use XML + * and the XMLAdapter. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SerializedAdapter.java,v 1.4 2007/11/23 14:33:07 justb Exp $ + */ +class SerializedAdapter implements ClientAdapter { + private ObjectOutputStream out = null; + public static final String CONTENT_TYPE = "application/x-java-serialized-object"; + private HttpServletResponse servletRsp; + + /** + * Initialize. + */ + public SerializedAdapter(HttpServletResponse aServletResponse) { + servletRsp = aServletResponse; + } + + public void start() throws IOException { + + servletRsp.setContentType(CONTENT_TYPE); + + // Use a serialized object output stream + out = new ObjectOutputStream(servletRsp.getOutputStream()); + + // Don't need this further + servletRsp = null; + } + + /** + * Push Event to client. + */ + public void push(Event anEvent) throws IOException { + out.writeObject(anEvent); + + out.flush(); + } + + + public void stop() throws IOException { + } +} + +/* + * $Log: SerializedAdapter.java,v $ + * Revision 1.4 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:13:48 justb + * fixed blocking for java.net.URL with HTTP/1.1 (JVMs > 1.1) + * + * Revision 1.1.1.1 2002/09/24 21:02:31 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:03 justb + * first import into SF + * + * Revision 1.5 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.4 2000/12/27 22:39:35 just + * no message + * + * Revision 1.3 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Session.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Session.java new file mode 100644 index 0000000000..8adf9ba6f4 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Session.java @@ -0,0 +1,205 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; + +/** + * Represents client pushlet session state. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Session.java,v 1.8 2007/11/23 14:33:07 justb Exp $ + */ +public class Session implements Protocol, ConfigDefs { + private Controller controller; + private Subscriber subscriber; + + private String userAgent; + private long LEASE_TIME_MILLIS = Config.getLongProperty(SESSION_TIMEOUT_MINS) * 60 * 1000; + private volatile long timeToLive = LEASE_TIME_MILLIS; + + public static String[] FORCED_PULL_AGENTS = Config.getProperty(LISTEN_FORCE_PULL_AGENTS).split(","); + + private String address = "unknown"; + private String format = FORMAT_XML; + + private String id; + + /** + * Protected constructor as we create through factory method. + */ + protected Session() { + } + + /** + * Create instance through factory method. + * + * @param anId a session id + * @return a Session object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Session create(String anId) throws PushletException { + Session session; + try { + session = (Session) Config.getClass(SESSION_CLASS, "nl.justobjects.pushlet.core.Session").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Session from config", t); + } + + // Init session + session.id = anId; + session.controller = Controller.create(session); + session.subscriber = Subscriber.create(session); + return session; + } + + /** + * Return (remote) Subscriber client's IP address. + */ + public String getAddress() { + return address; + } + + /** + * Return command controller. + */ + public Controller getController() { + return controller; + } + + /** + * Return Event format to send to client. + */ + public String getFormat() { + return format; + } + + /** + * Return (remote) Subscriber client's unique id. + */ + public String getId() { + return id; + } + + /** + * Return subscriber. + */ + public Subscriber getSubscriber() { + return subscriber; + } + + /** + * Return remote HTTP User-Agent. + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Set address. + */ + protected void setAddress(String anAddress) { + address = anAddress; + } + + /** + * Set event format to encode. + */ + protected void setFormat(String aFormat) { + format = aFormat; + } + + /** + * Set client HTTP UserAgent. + */ + public void setUserAgent(String aUserAgent) { + userAgent = aUserAgent; + } + + /** + * Decrease time to live. + */ + public void age(long aDeltaMillis) { + timeToLive -= aDeltaMillis; + } + + /** + * Has session timed out? + */ + public boolean isExpired() { + return timeToLive <= 0; + } + + /** + * Keep alive by resetting TTL. + */ + public void kick() { + timeToLive = LEASE_TIME_MILLIS; + } + + public void start() { + SessionManager.getInstance().addSession(this); + } + + public void stop() { + subscriber.stop(); + SessionManager.getInstance().removeSession(this); + } + + /** + * Info. + */ + public void info(String s) { + Log.info("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void warn(String s) { + Log.warn("S-" + this + ": " + s); + } + + /** + * Exceptional print util. + */ + public void debug(String s) { + Log.debug("S-" + this + ": " + s); + } + + public String toString() { + return getAddress() + "[" + getId() + "]"; + } +} + +/* + * $Log: Session.java,v $ + * Revision 1.8 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.7 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.6 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.5 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.4 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.3 2005/02/21 16:59:08 justb + * SessionManager and session lease introduced + * + * Revision 1.2 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.1 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SessionManager.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SessionManager.java new file mode 100644 index 0000000000..7d3441dc7b --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/SessionManager.java @@ -0,0 +1,386 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.rmi.server.UID; +import java.util.*; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * Manages lifecycle of Sessions. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: SessionManager.java,v 1.12 2007/12/04 13:55:53 justb Exp $ + */ +public class SessionManager implements ConfigDefs { + + /** + * Singleton pattern: single instance. + */ + private static SessionManager instance; + + static { + // Singleton + factory pattern: create single instance + // from configured class name + try { + instance = (SessionManager) Config.getClass(SESSION_MANAGER_CLASS, "nl.justobjects.pushlet.core.SessionManager").newInstance(); + Log.info("SessionManager created className=" + instance.getClass()); + } catch (Throwable t) { + Log.fatal("Cannot instantiate SessionManager from config", t); + } + } + + /** + * Timer to schedule session leasing TimerTasks. + */ + private Timer timer; + private final long TIMER_INTERVAL_MILLIS = 60000; + + /** + * Map of active sessions, keyed by their id, all access is through mutex. + */ + private Map sessions = new HashMap(13); + + /** + * Cache of Sessions for iteration and to allow concurrent modification. + */ + private Session[] sessionCache = new Session[0]; + + /** + * State of SessionCache, becomes true whenever sessionCache out of sync with sessions Map. + */ + private boolean sessionCacheDirty = false; + + /** + * Lock for any operation on Sessions (Session Map and/or -cache). + */ + private final Object mutex = new Object(); + + /** + * Singleton pattern: protected constructor needed for derived classes. + */ + protected SessionManager() { + } + + /** + * Visitor pattern implementation for Session iteration. + *

      + * This method can be used to iterate over all Sessions in a threadsafe way. + * See Dispatcher.multicast and broadcast methods for examples. + * + * @param visitor the object that should implement method parm + * @param method the method to be called from visitor + * @param args arguments to be passed in visit method, args[0] will always be Session object + */ + public void apply(Object visitor, Method method, Object[] args) { + + synchronized (mutex) { + + // Refresh Session cache if required + // We use a cache for two reasons: + // 1. to prevent concurrent modification from within visitor method + // 2. some optimization (vs setting up Iterator for each apply() + if (sessionCacheDirty) { + // Clear out existing cache + for (int i = 0; i < sessionCache.length; i++) { + sessionCache[i] = null; + } + + // Refill cache and update state + sessionCache = (Session[]) sessions.values().toArray(sessionCache); + sessionCacheDirty = false; + } + + // Valid session cache: loop and call supplied Visitor method + Session nextSession; + for (int i = 0; i < sessionCache.length; i++) { + nextSession = sessionCache[i]; + + // Session cache may not be entirely filled + if (nextSession == null) { + break; + } + + try { + // First argument is always a Session object + args[0] = nextSession; + + // Use Java reflection to call the method passed by the Visitor + method.invoke(visitor, args); + } catch (IllegalAccessException e) { + Log.warn("apply: illegal method access: ", e); + } catch (InvocationTargetException e) { + Log.warn("apply: method invoke: ", e); + } + } + } + } + + /** + * Create new Session (but add later). + */ + public Session createSession(Event anEvent) throws PushletException { + // Trivial + return Session.create(createSessionId()); + } + + + /** + * Singleton pattern: get single instance. + */ + public static SessionManager getInstance() { + return instance; + } + + /** + * Get Session by session id. + */ + public Session getSession(String anId) { + synchronized (mutex) { + return (Session) sessions.get(anId); + } + } + + /** + * Get copy of listening Sessions. + */ + public Session[] getSessions() { + synchronized (mutex) { + return (Session[]) sessions.values().toArray(new Session[0]); + } + } + + /** + * Get number of listening Sessions. + */ + public int getSessionCount() { + synchronized (mutex) { + return sessions.size(); + } + } + + /** + * Get status info. + */ + public String getStatus() { + Session[] sessions = getSessions(); + StringBuffer statusBuffer = new StringBuffer(); + statusBuffer.append("SessionMgr: " + sessions.length + " sessions \\n"); + for (int i = 0; i < sessions.length; i++) { + statusBuffer.append(sessions[i] + "\\n"); + } + return statusBuffer.toString(); + } + + /** + * Is Session present?. + */ + public boolean hasSession(String anId) { + synchronized (mutex) { + return sessions.containsKey(anId); + } + } + + /** + * Add session. + */ + public void addSession(Session session) { + synchronized (mutex) { + sessions.put(session.getId(), session); + sessionCacheDirty = true; + } + // log(session.getId() + " at " + session.getAddress() + " adding "); + info(session.getId() + " at " + session.getAddress() + " added "); + } + + /** + * Register session for removal. + */ + public Session removeSession(Session aSession) { + synchronized (mutex) { + Session session = (Session) sessions.remove(aSession.getId()); + if (session != null) { + info(session.getId() + " at " + session.getAddress() + " removed "); + } + sessionCacheDirty = true; + return session; + } + } + + + /** + * Starts us. + */ + public void start() throws PushletException { + if (timer != null) { + stop(); + } + timer = new Timer(false); + timer.schedule(new AgingTimerTask(), TIMER_INTERVAL_MILLIS, TIMER_INTERVAL_MILLIS); + info("started; interval=" + TIMER_INTERVAL_MILLIS + "ms"); + } + + /** + * Stopis us. + */ + public void stop() { + if (timer != null) { + timer.cancel(); + timer = null; + } + synchronized (mutex) { + sessions.clear(); + } + info("stopped"); + } + + /** + * Create unique Session id. + */ + protected String createSessionId() { + // Use UUID if specified in config (thanks Uli Romahn) + if (Config.hasProperty(SESSION_ID_GENERATION) && Config.getProperty(SESSION_ID_GENERATION).equals(SESSION_ID_GENERATION_UUID)) { + // We want to be Java 1.4 compatible so use UID class (1.5+ we may use java.util.UUID). + return new UID().toString(); + } + + // Other cases use random name + + // Create a unique session id + // In 99.9999 % of the cases this should be generated at once + // We need the mutext to prevent the chance of creating + // same-valued ids (thanks Uli Romahn) + synchronized (mutex) { + String id; + while (true) { + id = Rand.randomName(Config.getIntProperty(SESSION_ID_SIZE)); + if (!hasSession(id)) { + // Created unique session id + break; + } + } + return id; + } + } + + /** + * Util: stdout printing. + */ + protected void info(String s) { + Log.info("SessionManager: " + new Date() + " " + s); + } + + /** + * Util: stdout printing. + */ + protected void warn(String s) { + Log.warn("SessionManager: " + s); + } + + /** + * Util: stdout printing. + */ + protected void debug(String s) { + Log.debug("SessionManager: " + s); + } + + /** + * Manages Session timeouts. + */ + private class AgingTimerTask extends TimerTask { + private long lastRun = Sys.now(); + private long delta; + private Method visitMethod; + + public AgingTimerTask() throws PushletException { + try { + // Setup Visitor Methods for callback from SessionManager + Class[] argsClasses = {Session.class}; + visitMethod = this.getClass().getMethod("visit", argsClasses); + } catch (NoSuchMethodException e) { + throw new PushletException("Failed to setup AgingTimerTask", e); + } + } + + /** + * Clock tick callback from Timer. + */ + public void run() { + long now = Sys.now(); + delta = now - lastRun; + lastRun = now; + debug("AgingTimerTask: tick"); + + // Use Visitor pattern to loop through Session objects (see visit() below) + getInstance().apply(this, visitMethod, new Object[1]); + } + + /** + * Callback from SessionManager during apply() + */ + public void visit(Session aSession) { + try { + // Age the lease + aSession.age(delta); + debug("AgingTimerTask: visit: " + aSession); + + // Stop session if lease expired + if (aSession.isExpired()) { + info("AgingTimerTask: Session expired: " + aSession); + aSession.stop(); + } + } catch (Throwable t) { + warn("AgingTimerTask: Error in timer task : " + t); + } + } + } +} + +/* + * $Log: SessionManager.java,v $ + * Revision 1.12 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.11 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.10 2007/11/10 14:47:45 justb + * make session key generation configurable (can use uuid) + * + * Revision 1.9 2007/11/10 14:17:18 justb + * minor cosmetic changes just commit now + * + * Revision 1.8 2007/07/02 08:12:16 justb + * redo to original version of session cache (with break, but nullify array first) + * + * Revision 1.7 2007/07/02 07:33:02 justb + * small fix in sessionmgr for holes in sessioncache array (continue i.s.o. break) + * + * Revision 1.6 2006/11/18 12:13:47 justb + * made SessionManager constructor protected to allow constructing derived classes + * + * Revision 1.5 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.4 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.3 2005/02/28 09:14:55 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.2 2005/02/25 15:13:01 justb + * session id generation more robust + * + * Revision 1.1 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscriber.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscriber.java new file mode 100644 index 0000000000..39f5ba0198 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscriber.java @@ -0,0 +1,469 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.Sys; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.net.URLEncoder; + +/** + * Handles data channel between dispatcher and client. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscriber.java,v 1.26 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscriber implements Protocol, ConfigDefs { + private Session session; + + /** + * Blocking queue. + */ + private EventQueue eventQueue = new EventQueue(Config.getIntProperty(QUEUE_SIZE)); + + /** + * URL to be used in refresh requests in pull/poll modes. + */ + private long queueReadTimeoutMillis = Config.getLongProperty(QUEUE_READ_TIMEOUT_MILLIS); + private long queueWriteTimeoutMillis = Config.getLongProperty(QUEUE_WRITE_TIMEOUT_MILLIS); + private long refreshTimeoutMillis = Config.getLongProperty(PULL_REFRESH_TIMEOUT_MILLIS); + volatile long lastAlive = Sys.now(); + + /** + * Map of active subscriptions, keyed by their subscription id. + */ + private Map subscriptions = Collections.synchronizedMap(new HashMap(3)); + + /** + * Are we able to accept/send events ?. + */ + private volatile boolean active; + + /** + * Transfer mode (stream, pull, poll). + */ + private String mode; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscriber() { + } + + /** + * Create instance through factory method. + * + * @param aSession the parent Session + * @return a Subscriber object (or derived) + * @throws PushletException exception, usually misconfiguration + */ + public static Subscriber create(Session aSession) throws PushletException { + Subscriber subscriber; + try { + subscriber = (Subscriber) Config.getClass(SUBSCRIBER_CLASS, "nl.justobjects.pushlet.core.Subscriber").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + subscriber.session = aSession; + return subscriber; + } + + public void start() { + active = true; + } + + public void stop() { + removeSubscriptions(); + active = false; + } + + public void bailout() { + session.stop(); + } + + /** + * Are we still active to handle events. + */ + public boolean isActive() { + return active; + } + + /** + * Return client session. + */ + public Session getSession() { + return session; + } + + /** + * Get (session) id. + */ + public String getId() { + return session.getId(); + } + + /** + * Return subscriptions. + */ + public Subscription[] getSubscriptions() { + // todo: Optimize + return (Subscription[]) subscriptions.values().toArray(new Subscription[0]); + } + + /** + * Add a subscription. + */ + public Subscription addSubscription(String aSubject, String aLabel) throws PushletException { + Subscription subscription = Subscription.create(aSubject, aLabel); + subscriptions.put(subscription.getId(), subscription); + info("Subscription added subject=" + aSubject + " sid=" + subscription.getId() + " label=" + aLabel); + return subscription; + } + + /** + * Remove a subscription. + */ + public Subscription removeSubscription(String aSubscriptionId) { + Subscription subscription = (Subscription) subscriptions.remove(aSubscriptionId); + if (subscription == null) { + warn("No subscription found sid=" + aSubscriptionId); + return null; + } + info("Subscription removed subject=" + subscription.getSubject() + " sid=" + subscription.getId() + " label=" + subscription.getLabel()); + return subscription; + } + + /** + * Remove all subscriptions. + */ + public void removeSubscriptions() { + subscriptions.clear(); + } + + public String getMode() { + return mode; + } + + public void setMode(String aMode) { + mode = aMode; + } + + public long getRefreshTimeMillis() { + String minWaitProperty = PULL_REFRESH_WAIT_MIN_MILLIS; + String maxWaitProperty = PULL_REFRESH_WAIT_MAX_MILLIS; + if (mode.equals((MODE_POLL))) { + minWaitProperty = POLL_REFRESH_WAIT_MIN_MILLIS; + maxWaitProperty = POLL_REFRESH_WAIT_MAX_MILLIS; + + } + return Rand.randomLong(Config.getLongProperty(minWaitProperty), + Config.getLongProperty(maxWaitProperty)); + } + + /** + * Get events from queue and push to client. + */ + public void fetchEvents(Command aCommand) throws PushletException { + + String refreshURL = aCommand.httpReq.getRequestURI() + "?" + P_ID + "=" + session.getId() + "&" + P_EVENT + "=" + E_REFRESH; + + // This is the only thing required to support "poll" mode + if (mode.equals(MODE_POLL)) { + queueReadTimeoutMillis = 0; + refreshTimeoutMillis = Config.getLongProperty(POLL_REFRESH_TIMEOUT_MILLIS); + } + + // Required for fast bailout (tomcat) + aCommand.httpRsp.setBufferSize(128); + + // Try to prevent caching in any form. + aCommand.sendResponseHeaders(); + + // Let clientAdapter determine how to send event + ClientAdapter clientAdapter = aCommand.getClientAdapter(); + Event responseEvent = aCommand.getResponseEvent(); + try { + clientAdapter.start(); + + // Send first event (usually hb-ack or listen-ack) + clientAdapter.push(responseEvent); + + // In pull/poll mode and when response is listen-ack or join-listen-ack, + // return and force refresh immediately + // such that the client recieves response immediately over this channel. + // This is usually when loading the browser app for the first time + if ((mode.equals(MODE_POLL) || mode.equals(MODE_PULL)) + && responseEvent.getEventType().endsWith(Protocol.E_LISTEN_ACK)) { + sendRefresh(clientAdapter, refreshURL); + + // We should come back later with refresh event... + return; + } + } catch (Throwable t) { + bailout(); + return; + } + + + Event[] events = null; + + // Main loop: as long as connected, get events and push to client + long eventSeqNr = 1; + while (isActive()) { + // Indicate we are still alive + lastAlive = Sys.now(); + + // Update session time to live + session.kick(); + + // Get next events; blocks until timeout or entire contents + // of event queue is returned. Note that "poll" mode + // will return immediately when queue is empty. + try { + // Put heartbeat in queue when starting to listen in stream mode + // This speeds up the return of *_LISTEN_ACK + if (mode.equals(MODE_STREAM) && eventSeqNr == 1) { + eventQueue.enQueue(new Event(E_HEARTBEAT)); + } + + events = eventQueue.deQueueAll(queueReadTimeoutMillis); + } catch (InterruptedException ie) { + warn("interrupted"); + bailout(); + } + + // Send heartbeat when no events received + if (events == null) { + events = new Event[1]; + events[0] = new Event(E_HEARTBEAT); + } + + // ASSERT: one or more events available + + // Send events to client using adapter + // debug("received event count=" + events.length); + for (int i = 0; i < events.length; i++) { + // Check for abort event + if (events[i].getEventType().equals(E_ABORT)) { + warn("Aborting Subscriber"); + bailout(); + } + + // Push next Event to client + try { + // Set sequence number + events[i].setField(P_SEQ, eventSeqNr++); + + // Push to client through client adapter + clientAdapter.push(events[i]); + } catch (Throwable t) { + bailout(); + return; + } + } + + // Force client refresh request in pull or poll modes + if (mode.equals(MODE_PULL) || mode.equals(MODE_POLL)) { + sendRefresh(clientAdapter, refreshURL); + + // Always leave loop in pull/poll mode + break; + } + } + } + + /** + * Determine if we should receive event. + */ + public Subscription match(Event event) { + Subscription[] subscriptions = getSubscriptions(); + for (int i = 0; i < subscriptions.length; i++) { + if (subscriptions[i].match(event)) { + return subscriptions[i]; + } + } + return null; + } + + /** + * Event from Dispatcher: enqueue it. + */ + public void onEvent(Event theEvent) { + if (!isActive()) { + return; + } + + // p("send: queue event: "+theEvent.getSubject()); + + // Check if we had any active continuation for at + // least 'timeOut' millisecs. If the client has left this + // instance there would be no way of knowing otherwise. + long now = Sys.now(); + if (now - lastAlive > refreshTimeoutMillis) { + warn("not alive for at least: " + refreshTimeoutMillis + "ms, leaving..."); + bailout(); + return; + } + + // Put event in queue; leave if queue full + try { + if (!eventQueue.enQueue(theEvent, queueWriteTimeoutMillis)) { + warn("queue full, bailing out..."); + bailout(); + } + + // ASSERTION : Event in queue. + // see fetchEvents() where Events are dequeued and pushed to the client. + } catch (InterruptedException ie) { + bailout(); + } + + } + + /** + * Send refresh command to pull/poll clients. + */ + protected void sendRefresh(ClientAdapter aClientAdapter, String aRefreshURL) { + Event refreshEvent = new Event(E_REFRESH); + + // Set wait time and url for refresh + refreshEvent.setField(P_WAIT, "" + getRefreshTimeMillis()); + refreshEvent.setField(P_URL, aRefreshURL); + + try { + // Push to client through client adapter + aClientAdapter.push(refreshEvent); + + // Stop this round until refresh event + aClientAdapter.stop(); + } catch (Throwable t) { + // Leave on any exception + bailout(); + } + } + + /** + * Info. + */ + protected void info(String s) { + session.info("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void warn(String s) { + session.warn("[Subscriber] " + s); + } + + /** + * Exceptional print util. + */ + protected void debug(String s) { + session.debug("[Subscriber] " + s); + } + + + public String toString() { + return session.toString(); + } +} + +/* + * $Log: Subscriber.java,v $ + * Revision 1.26 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.25 2007/11/10 15:53:15 justb + * put heartbeat in queue when start fetching events in stream-mode + * + * Revision 1.24 2006/10/19 12:33:40 justb + * add atomic join-listen support (one request) + * + * Revision 1.22 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.21 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.20 2005/02/21 16:59:09 justb + * SessionManager and session lease introduced + * + * Revision 1.19 2005/02/21 12:32:28 justb + * fixed publish event in Controller + * + * Revision 1.18 2005/02/21 11:50:46 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.17 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.16 2005/02/18 12:36:47 justb + * changes for renaming and configurability + * + * Revision 1.15 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.14 2005/02/18 09:54:15 justb + * refactor: rename Publisher Dispatcher and single Subscriber class + * + * Revision 1.13 2005/02/16 14:39:34 justb + * fixed leave handling and added "poll" mode + * + * Revision 1.12 2005/01/24 13:42:00 justb + * new protocol changes (p_listen) + * + * Revision 1.11 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.10 2004/10/24 20:50:35 justb + * refine subscription with label and sending sid and label on events + * + * Revision 1.9 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.8 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.7 2004/09/20 22:01:38 justb + * more changes for new protocol + * + * Revision 1.6 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.5 2004/08/13 23:36:05 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.4 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.3 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscription.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscription.java new file mode 100644 index 0000000000..c6f88bd597 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/Subscription.java @@ -0,0 +1,133 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Rand; +import nl.justobjects.pushlet.util.PushletException; + + +/** + * Represents single subject subscription + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Subscription.java,v 1.5 2007/11/23 14:33:07 justb Exp $ + */ +public class Subscription implements ConfigDefs { + public static final int ID_SIZE = 5; + public static final String SUBJECT_SEPARATOR = ","; + private String id = Rand.randomName(ID_SIZE); + private String subject; + private String[] subjects; + + /** + * Optional label, a user supplied token. + */ + private String label; + + + /** + * Protected constructor as we create through factory method. + */ + protected Subscription() { + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject) throws PushletException { + return create(aSubject, null); + } + + /** + * Create instance through factory method. + * + * @param aSubject the subject (topic). + * @param aLabel the subject label (optional). + * @return a Subscription object (or derived) + * @throws nl.justobjects.pushlet.util.PushletException + * exception, usually misconfiguration + */ + public static Subscription create(String aSubject, String aLabel) throws PushletException { + if (aSubject == null || aSubject.length() == 0) { + throw new IllegalArgumentException("Null or emtpy subject"); + } + + Subscription subscription; + try { + subscription = (Subscription) Config.getClass(SUBSCRIPTION_CLASS, "nl.justobjects.pushlet.core.Subscription").newInstance(); + } catch (Throwable t) { + throw new PushletException("Cannot instantiate Subscriber from config", t); + } + + // Init + subscription.subject = aSubject; + + // We may subscribe to multiple subjects by separating + // them with SUBJECT_SEPARATOR, e.g. "/stocks/aex,/system/memory,.."). + subscription.subjects = aSubject.split(SUBJECT_SEPARATOR); + + subscription.label = aLabel; + return subscription; + } + + + public String getId() { + return id; + } + + public String getLabel() { + return label; + } + + public String getSubject() { + return subject; + } + + /** + * Determine if Event matches subscription. + */ + public boolean match(Event event) { + String eventSubject = event.getSubject(); + + // Silly case but check anyway + if (eventSubject == null || eventSubject.length() == 0) { + return false; + } + + // Test if one of the subjects matches + for (int i = 0; i < subjects.length; i++) { + if (eventSubject.startsWith(subjects[i])) { + return true; + } + } + + // No match + return false; + } +} + +/* + * $Log: Subscription.java,v $ + * Revision 1.5 2007/11/23 14:33:07 justb + * core classes now configurable through factory + * + * Revision 1.4 2006/05/06 00:10:11 justb + * various chgs but not too serious... + * + * Revision 1.3 2005/02/16 15:23:10 justb + * multiple subject (, separated) support + * + * Revision 1.2 2005/01/18 16:47:10 justb + * protocol changes for v2 and publishing from pushlet client + * + * Revision 1.1 2004/09/26 21:39:43 justb + * allow multiple subscriptions and out-of-band requests + * + * + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/XMLAdapter.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/XMLAdapter.java new file mode 100644 index 0000000000..15d7096e59 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/core/XMLAdapter.java @@ -0,0 +1,137 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.core; + +import nl.justobjects.pushlet.util.Log; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * ClientAdapter that sends Events as XML. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: XMLAdapter.java,v 1.7 2007/11/09 13:15:35 justb Exp $ + */ +class XMLAdapter implements ClientAdapter { + /** + * Header for strict XML + */ + // public static final String XML_HEAD = "\n"; + private String contentType = "text/plain;charset=UTF-8"; + private ServletOutputStream out = null; + private HttpServletResponse servletRsp; + private boolean strictXML; + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse) { + this(aServletResponse, false); + } + + /** + * Initialize. + */ + public XMLAdapter(HttpServletResponse aServletResponse, boolean useStrictXML) { + servletRsp = aServletResponse; + + // Strict XML implies returning a complete XML document + strictXML = useStrictXML; + if (strictXML) { + contentType = "text/xml;charset=UTF-8"; + } + } + + public void start() throws IOException { + + // If content type is plain text + // then this is not a complete XML document, but rather + // a stream of XML documents where each document is + // an Event. In strict XML mode a complete document is returned. + servletRsp.setContentType(contentType); + + out = servletRsp.getOutputStream(); + + // Don't need this further + servletRsp = null; + + // Start XML document if strict XML mode + if (strictXML) { + out.print(""); + } + } + + /** + * Force client to refresh the request. + */ + public void push(Event anEvent) throws IOException { + debug("event=" + anEvent); + + // Send the event as XML to the client and flush. + out.print(anEvent.toXML(strictXML)); + out.flush(); + } + + /** + * No action. + */ + public void stop() throws IOException { + // Close XML document if strict XML mode + if (strictXML) { + out.print(""); + out.flush(); + } + } + + private void debug(String s) { + Log.debug("[XMLAdapter]" + s); + } +} + +/* + * $Log: XMLAdapter.java,v $ + * Revision 1.7 2007/11/09 13:15:35 justb + * add charset=UTF-8 in returned HTTP content types + * + * Revision 1.6 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.5 2006/05/06 00:06:28 justb + * first rough version AJAX client + * + * Revision 1.4 2005/05/06 19:44:00 justb + * added xml-strict format + * + * Revision 1.3 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.2 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.1 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.7 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.6 2004/03/10 14:01:55 justb + * formatting and *Subscriber refactoring + * + * Revision 1.5 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.4 2003/08/13 14:00:00 justb + * some testing for applets; no real change + * + * Revision 1.3 2003/08/12 09:57:06 justb + * replaced all print statements to Log.*() calls + * + * Revision 1.2 2003/05/19 21:56:29 justb + * various fixes for applet clients + * + * Revision 1.1 2003/05/18 16:12:28 justb + * adding support for XML encoded Events + */ diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/servlet/Pushlet.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/servlet/Pushlet.java new file mode 100644 index 0000000000..0c19494dd3 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/servlet/Pushlet.java @@ -0,0 +1,293 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.servlet; + +import nl.justobjects.pushlet.core.*; +import nl.justobjects.pushlet.util.Log; +import nl.justobjects.pushlet.util.Servlets; +import nl.justobjects.pushlet.util.PushletException; +import nl.justobjects.pushlet.Version; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Enumeration; + +/** + * Servlet runs a Subscriber per request. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Pushlet.java,v 1.23 2007/12/04 13:55:53 justb Exp $ + */ +public class Pushlet extends HttpServlet implements Protocol { + + public void init() throws ServletException { + try { + // Load configuration (from classpath or WEB-INF root path) + String webInfPath = getServletContext().getRealPath("/") + "/WEB-INF"; + Config.load(webInfPath); + + Log.init(); + + // Start + Log.info("init() Pushlet Webapp - version=" + Version.SOFTWARE_VERSION + " built=" + Version.BUILD_DATE); + + // Start session manager + SessionManager.getInstance().start(); + + // Start event Dispatcher + Dispatcher.getInstance().start(); + + + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + EventSourceManager.start(webInfPath,getServletContext());// changed by thomas genin + } else { + Log.info("Not starting local event sources"); + } + } catch (Throwable t) { + throw new ServletException("Failed to initialize Pushlet framework " + t, t); + } + } + + public void destroy() { + Log.info("destroy(): Exit Pushlet webapp"); + + if (Config.getBoolProperty(Config.SOURCES_ACTIVATE)) { + // Stop local event sources + EventSourceManager.stop(); + } else { + Log.info("No local event sources to stop"); + } + + // Should abort all subscribers + Dispatcher.getInstance().stop(); + + // Should stop all sessions + SessionManager.getInstance().stop(); + } + + /** + * Servlet GET request: handles event requests. + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + + try { + // Event parm identifies event type from the client + String eventType = Servlets.getParameter(request, P_EVENT); + + // Always must have an event type + if (eventType == null) { + Log.warn("Pushlet.doGet(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + // Create Event and set attributes from parameters + event = new Event(eventType); + for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) { + String nextAttribute = (String) e.nextElement(); + event.setField(nextAttribute, request.getParameter(nextAttribute)); + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doGet(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Servlet POST request: extracts event data from body. + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Event event = null; + try { + // Create Event by parsing XML from input stream. + event = EventParser.parse(new InputStreamReader(request.getInputStream())); + + // Always must have an event type + if (event.getEventType() == null) { + Log.warn("Pushlet.doPost(): bad request, no event specified"); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No eventType specified"); + return; + } + + + } catch (Throwable t) { + // Error creating event + Log.warn("Pushlet: Error creating event in doPost(): ", t); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + // Handle parsed request + doRequest(event, request, response); + + } + + /** + * Generic request handler (GET+POST). + */ + protected void doRequest(Event anEvent, HttpServletRequest request, HttpServletResponse response) { + // Must have valid event type. + String eventType = anEvent.getEventType(); + try { + + // Get Session: either by creating (on Join eventType) + // or by id (any other eventType, since client is supposed to have joined). + Session session = null; + if (eventType.startsWith(Protocol.E_JOIN)) { + // Join request: create new subscriber + session = SessionManager.getInstance().createSession(anEvent); + + String userAgent = request.getHeader("User-Agent"); + if (userAgent != null) { + userAgent = userAgent.toLowerCase(); + } else { + userAgent = "unknown"; + } + session.setUserAgent(userAgent); + + } else { + // Must be a request for existing Session + + // Get id + String id = anEvent.getField(P_ID); + + // We must have an id value + if (id == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No id specified"); + Log.warn("Pushlet: bad request, no id specified event=" + eventType); + return; + } + + // We have an id: get the session object + session = SessionManager.getInstance().getSession(id); + + // Check for invalid id + if (session == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid or expired id: " + id); + Log.warn("Pushlet: bad request, no session found id=" + id + " event=" + eventType); + return; + } + } + + // ASSERTION: we have a valid Session + + // Let Controller handle request further + // including exceptions + Command command = Command.create(session, anEvent, request, response); + session.getController().doCommand(command); + } catch (Throwable t) { + // Hmm we should never ever get here + Log.warn("Pushlet: Exception in doRequest() event=" + eventType, t); + t.printStackTrace(); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + } +} + +/* + * $Log: Pushlet.java,v $ + * Revision 1.23 2007/12/04 13:55:53 justb + * reimplement SessionManager concurrency (prev version was not thread-safe!) + * + * Revision 1.22 2007/11/24 10:29:36 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.21 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.20 2007/11/10 13:44:02 justb + * pushlet.properties and sources.properties can now also be put under WEB-INF + * + * Revision 1.19 2006/05/15 11:52:53 justb + * updates mainly for AJAX client + * + * Revision 1.18 2005/02/28 15:58:05 justb + * added SimpleListener example + * + * Revision 1.17 2005/02/28 13:06:01 justb + * introduced join-listen protocol service + * + * Revision 1.16 2005/02/28 12:45:59 justb + * introduced Command class + * + * Revision 1.15 2005/02/28 09:14:56 justb + * sessmgr/dispatcher factory/singleton support + * + * Revision 1.14 2005/02/25 15:13:04 justb + * session id generation more robust + * + * Revision 1.13 2005/02/21 17:19:21 justb + * move init()/destroy() to Pushlet servlet + * + * Revision 1.12 2005/02/21 16:59:17 justb + * SessionManager and session lease introduced + * + * Revision 1.11 2005/02/21 11:50:47 justb + * ohase1 of refactoring Subscriber into Session/Controller/Subscriber + * + * Revision 1.10 2005/02/20 13:05:32 justb + * removed the Postlet (integrated in Pushlet protocol) + * + * Revision 1.9 2005/02/18 10:07:23 justb + * many renamings of classes (make names compact) + * + * Revision 1.8 2005/01/13 14:47:15 justb + * control evt: send response on same (control) connection + * + * Revision 1.7 2004/10/24 12:58:18 justb + * revised client and test classes for new protocol + * + * Revision 1.6 2004/09/26 21:39:44 justb + * allow multiple subscriptions and out-of-band requests + * + * Revision 1.5 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * Revision 1.4 2004/09/03 22:35:37 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.3 2004/08/13 23:36:06 justb + * rewrite of Pullet into Pushlet "pull" mode + * + * Revision 1.2 2003/08/15 08:37:40 justb + * fix/add Copyright+LGPL file headers and footers + * + * Revision 1.1 2003/08/13 13:26:57 justb + * moved all servlets to servlet package + * + * Revision 1.2 2003/05/18 16:15:08 justb + * support for XML encoded Events + * + * Revision 1.1.1.1 2002/09/24 21:02:32 justb + * import to sourceforge + * + * Revision 1.1.1.1 2002/09/20 22:48:18 justb + * import to SF + * + * Revision 1.1.1.1 2002/09/20 14:19:04 justb + * first import into SF + * + * Revision 1.3 2002/04/15 20:42:41 just + * reformatting and renaming GuardedQueue to EventQueue + * + * Revision 1.2 2000/08/21 20:48:29 just + * added CVS log and id tags plus copyrights + * + * + */ + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/DefaultLogger.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/DefaultLogger.java new file mode 100644 index 0000000000..bec2d94f34 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/DefaultLogger.java @@ -0,0 +1,164 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Default logger. + *

      + * Logs to stdout. Override this class by setting "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: DefaultLogger.java,v 1.2 2007/12/07 12:57:40 justb Exp $ + */ +public class DefaultLogger implements PushletLogger { + + + /** + * Level intialized with default. + */ + private int level = LOG_LEVEL_INFO; + + public DefaultLogger() { + } + + public void init() { + + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage) { + if (level < LOG_LEVEL_TRACE) { + return; + } + print("TRACE", aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage) { + if (level < LOG_LEVEL_DEBUG) { + return; + } + print("DEBUG", aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage) { + if (level < LOG_LEVEL_INFO) { + return; + } + print("INFO", aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage) { + if (level < LOG_LEVEL_WARN) { + return; + } + print("WARN", aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable) { + warn(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage) { + if (level < LOG_LEVEL_ERROR) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable) { + error(aMessage + " exception=" + aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage) { + if (level < LOG_LEVEL_FATAL) { + return; + } + print("FATAL", aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable) { + fatal(aMessage + " exception=" + aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + public void setLevel(int aLevel) { + level = aLevel; + } + + /** + * Print message. + * + * @param aTag the log type + * @param aMessage the message to be logged + */ + private void print(String aTag, String aMessage) { + // SImple std out e.g. to catalina.out in Tomcat + System.out.println("Pushlet[" + aTag + "] " + aMessage); + } + +} + +/* +* $Log: DefaultLogger.java,v $ +* Revision 1.2 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.1 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log.java new file mode 100644 index 0000000000..3ce40153e7 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log.java @@ -0,0 +1,178 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.Config; +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logging wrapper. + *

      + * Provides a hook to direct logging to your own logging library. Override the DefaultLogger class by setting + * "logger.class" in pushlet.properties to your own logger + * to integrate your own logging library. + * + * @author Just van den Broecke + * @version $Id: Log.java,v 1.5 2007/12/07 12:57:40 justb Exp $ + */ +public class Log implements ConfigDefs { + /** + * Init with default to have at least some logging. + */ + private static PushletLogger logger = new DefaultLogger(); + + /** + * General purpose initialization. + */ + static public void init() { + try { + logger = (PushletLogger) Config.getClass(LOGGER_CLASS, "nl.justobjects.pushlet.util.DefaultLogger").newInstance(); + } catch (Throwable t) { + // Hmmm cannot log this since we don't have a log... + System.out.println("Cannot instantiate Logger from config ex=" + t); + return; + } + + logger.init(); + + // Set log level + logger.setLevel(Config.getIntProperty(Config.LOG_LEVEL)); + + logger.info("Logging intialized logger class=" + logger.getClass()); + } + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + static public void trace(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + static public void debug(String aMessage) { + logger.debug(aMessage); + } + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + static public void info(String aMessage) { + logger.info(aMessage); + } + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + static public void warn(String aMessage) { + logger.warn(aMessage); + } + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + static public void error(String aMessage) { + logger.error(aMessage); + } + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + static public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + static public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /** + * Set log level + * + * @param aLevel the message to be logged + */ + static public void setLevel(int aLevel) { + logger.setLevel(aLevel); + } +} + +/* +* $Log: Log.java,v $ +* Revision 1.5 2007/12/07 12:57:40 justb +* added log4j and make it the default logging method +* +* Revision 1.4 2007/11/23 21:29:43 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.3 2007/11/23 21:10:17 justb +* add hooks for custom logging (you can override DefaultLogger in pushlet.properties) +* +* Revision 1.2 2005/02/21 11:15:59 justb +* support log levels +* +* Revision 1.1 2005/02/18 10:07:23 justb +* many renamings of classes (make names compact) +* +* Revision 1.7 2004/09/03 22:35:37 justb +* Almost complete rewrite, just checking in now +* +* Revision 1.6 2004/08/12 13:16:08 justb +* make debug flag false +* +* Revision 1.5 2004/03/10 14:01:55 justb +* formatting and *Subscriber refactoring +* +* Revision 1.4 2003/08/15 09:54:46 justb +* fix javadoc warnings +* +* Revision 1.3 2003/08/15 08:37:40 justb +* fix/add Copyright+LGPL file headers and footers +* +* Revision 1.2 2003/08/12 09:42:47 justb +* enhancements +* +* Revision 1.1 2003/08/12 08:46:00 justb +* cvs comment tags added +* +* +*/ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log4jLogger.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log4jLogger.java new file mode 100644 index 0000000000..d7ee1df832 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Log4jLogger.java @@ -0,0 +1,134 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +/** + * Logger to use Log4j for logging. + *

      + * Logs using Log4j. + * This class will require a log4j library in the classpath of the Pushlet. + * + * @author Uli Romahn + * @version $Id: Log4jLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public class Log4jLogger implements PushletLogger { + + /** + * Level intialized with default. + */ + private Logger logger = LogManager.getLogger("pushlet"); + + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#init() + */ + public void init() { + setLevel(LOG_LEVEL_INFO); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#debug(java.lang.String) + */ + public void debug(String aMessage) { + if (!logger.isDebugEnabled()) { + return; + } + logger.debug(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String) + */ + public void error(String aMessage) { + logger.error(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#error(java.lang.String, java.lang.Throwable) + */ + public void error(String aMessage, Throwable aThrowable) { + logger.error(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String) + */ + public void fatal(String aMessage) { + logger.fatal(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#fatal(java.lang.String, java.lang.Throwable) + */ + public void fatal(String aMessage, Throwable aThrowable) { + logger.fatal(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#info(java.lang.String) + */ + public void info(String aMessage) { + if (!logger.isInfoEnabled()) { + return; + } + logger.info(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#trace(java.lang.String) + */ + public void trace(String aMessage) { + logger.trace(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String) + */ + public void warn(String aMessage) { + logger.warn(aMessage); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#warn(java.lang.String, java.lang.Throwable) + */ + public void warn(String aMessage, Throwable aThrowable) { + logger.warn(aMessage, aThrowable); + } + + /* (non-Javadoc) + * @see nl.justobjects.pushlet.util.PushletLogger#setLevel(int) + */ + public void setLevel(int aLevel) { + if (aLevel < LOG_LEVEL_FATAL) { + logger.setLevel(Level.OFF); + } else { + switch (aLevel) { + case LOG_LEVEL_FATAL: + logger.setLevel(Level.FATAL); + break; + case LOG_LEVEL_ERROR: + logger.setLevel(Level.ERROR); + break; + case LOG_LEVEL_WARN: + logger.setLevel(Level.WARN); + break; + case LOG_LEVEL_INFO: + logger.setLevel(Level.INFO); + break; + case LOG_LEVEL_DEBUG: + logger.setLevel(Level.DEBUG); + break; + case LOG_LEVEL_TRACE: + logger.setLevel(Level.TRACE); + break; + default: + logger.setLevel(Level.INFO); + } + } + } +} diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletException.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletException.java new file mode 100644 index 0000000000..09ecd3176c --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletException.java @@ -0,0 +1,41 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +/** + * Generic exception wrapper. + * + * @author Just van den Broecke + * @version $Id: PushletException.java,v 1.1 2005/02/15 15:14:34 justb Exp $ + */ +public class PushletException extends Exception { + + private PushletException() { + } + + public PushletException(String aMessage, Throwable t) { + super(aMessage + "\n embedded exception=" + t.toString()); + } + + public PushletException(String aMessage) { + super(aMessage); + } + + public PushletException(Throwable t) { + this("PushletException: ", t); + } + + public String toString() { + return "PushletException: " + getMessage(); + } +} + +/* + * $Log: PushletException.java,v $ + * Revision 1.1 2005/02/15 15:14:34 justb + * *** empty log message *** + * + + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletLogger.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletLogger.java new file mode 100644 index 0000000000..c3853369ba --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/PushletLogger.java @@ -0,0 +1,94 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import nl.justobjects.pushlet.core.ConfigDefs; + +/** + * Logger interface to allow different logging providers. + *

      + * + * @author Ulrich Romahn + * @version $Id: PushletLogger.java,v 1.1 2007/12/07 12:57:40 justb Exp $ + */ +public interface PushletLogger extends ConfigDefs { + + /** + * Method allowing to initialize our logger + */ + public void init(); + + /** + * Log message for trace level. + * + * @param aMessage the message to be logged + */ + public void trace(String aMessage); + + /** + * Log message for debug level. + * + * @param aMessage the message to be logged + */ + public void debug(String aMessage); + + /** + * Log message for info level. + * + * @param aMessage the message to be logged + */ + public void info(String aMessage); + + /** + * Log message for warning level. + * + * @param aMessage the message to be logged + */ + public void warn(String aMessage); + + /** + * Log message for warning level with exception. + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void warn(String aMessage, Throwable aThrowable); + + /** + * Log message for error level. + * + * @param aMessage the message to be logged + */ + public void error(String aMessage); + + /** + * Log message (error level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void error(String aMessage, Throwable aThrowable); + + /** + * Log message for fatal level. + * + * @param aMessage the message to be logged + */ + public void fatal(String aMessage); + + /** + * Log message (fatal level with exception). + * + * @param aMessage the message to be logged + * @param aThrowable the exception + */ + public void fatal(String aMessage, Throwable aThrowable); + + /** + * Set log level + * + * @param aLevel a valid Level from ConfigDefs + */ + public void setLevel(int aLevel); +} diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Rand.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Rand.java new file mode 100644 index 0000000000..041970941f --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Rand.java @@ -0,0 +1,147 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. +package nl.justobjects.pushlet.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.Random; + +/** + * Randomizing routines. + * + * @author Just van den Broecke + * @version $Id: Rand.java,v 1.4 2007/12/07 12:57:40 justb Exp $ + */ +public class Rand { + private static char CHARS[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'v', 'w', 'y', 'z'}; + private static char NON_VOWELS[] = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'z'}; + private static char VOWELS[] = {'a', 'e', 'i', 'o', 'u', 'y'}; + private static Random random = new Random(); + + public static char randomChar() { + return CHARS[randomInt(0, CHARS.length - 1)]; + } + + public static char randomVowel() { + return VOWELS[randomInt(0, VOWELS.length - 1)]; + } + + public static char randomNonVowel() { + return NON_VOWELS[randomInt(0, NON_VOWELS.length - 1)]; + } + + public static File randomTempDir() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oasetest" + File.separator + randomString(12)); + file.mkdirs(); + file.deleteOnExit(); + return file; + } + + public static File randomTempFile() throws Exception { + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "oase-" + randomString(6)); + file.createNewFile(); + file.deleteOnExit(); + return file; + } + + public static File randomBinaryFile(int aSize) throws Exception { + File file = randomTempFile(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(randomBytes(aSize)); + fos.close(); + return file; + } + + public static File randomTextFile(int aSize) throws Exception { + File file = randomTempFile(); + PrintWriter pw = new PrintWriter(new FileOutputStream(file)); + pw.write(randomString(aSize)); + pw.close(); + return file; + } + + public static byte[] randomBytes(int aSize) { + return randomBlob(aSize); + } + + public static byte[] randomBlob(int aSize) { + byte[] retval = new byte[aSize]; + for (int i = 0; i < retval.length; i++) { + retval[i] = randomByte(); + } + return retval; + } + + public static byte randomByte() { + return (byte) random.nextInt(); + } + + public static double randomDouble() { + return random.nextLong(); + } + + + public static int randomInt() { + return random.nextInt(); + } + + public static int randomInt(int min, int max) { + return (int) ((Math.random() * (double) (max + 1 - min)) + min); + } + + public static long randomLong() { + return random.nextLong(); + } + + public static long randomLong(long min, long max) { + return (long) ((Math.random() * (double) (max + 1L - min)) + min); + } + + public static String randomName(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(i % 2 == 0 ? randomNonVowel() : randomVowel()); + } + return sb.toString(); + } + + public static void randomSleep(long min, long max) { + try { + Thread.sleep(randomLong(min, max)); + } catch (InterruptedException ie) { + + } + } + + public static String randomString(int aLength) { + StringBuffer sb = new StringBuffer(aLength); + for (int i = 0; i < aLength; i++) { + sb.append(randomChar()); + } + return sb.toString(); + } + + public static String randomString() { + return "" + randomLong(); + } + + +} + +/* + * $Log: Rand.java,v $ + * Revision 1.4 2007/12/07 12:57:40 justb + * added log4j and make it the default logging method + * + * Revision 1.3 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.2 2004/09/03 22:35:38 justb + * Almost complete rewrite, just checking in now + * + * Revision 1.1 2004/03/10 12:21:27 justb + * *** empty log message *** + * + * + */ \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Servlets.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Servlets.java new file mode 100644 index 0000000000..3b0f20c89f --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Servlets.java @@ -0,0 +1,67 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Servlet utilities. + * + * @author Just van den Broecke - Just Objects © + * @version $Id: Servlets.java,v 1.2 2007/11/23 21:10:17 justb Exp $ + */ +public class Servlets { + + /** + * Get parameter; if not set or empty return null. + */ + public static String getParameter(HttpServletRequest aRequest, String aName) { + return getParameter(aRequest, aName, null); + } + + /** + * Get parameter; if not set or empty return specified default value. + */ + public static String getParameter(HttpServletRequest aRequest, String aName, String aDefault) { + String value = aRequest.getParameter(aName); + if (value == null || value.length() == 0) { + value = aDefault; + } + return value; + } + + /** + * Set HTTP headers to prevent caching. + */ + public static void setNoCacheHeaders(HttpServletResponse aResponse) { + // Set to expire far in the past. + aResponse.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); + + // Set standard HTTP/1.1 no-cache headers. + aResponse.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); + + // Set IE extended HTTP/1.1 no-cache headers (use addHeader). + aResponse.addHeader("Cache-Control", "post-check=0, pre-check=0"); + + // Set standard HTTP/1.0 no-cache header. + aResponse.setHeader("Pragma", "no-cache"); + + } + +} + +/* + * $Log: Servlets.java,v $ + * Revision 1.2 2007/11/23 21:10:17 justb + * add hooks for custom logging (you can override DefaultLogger in pushlet.properties) + * + * Revision 1.1 2004/09/20 22:01:40 justb + * more changes for new protocol + * + * + */ + + diff --git a/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Sys.java b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Sys.java new file mode 100644 index 0000000000..2b72ab55e1 --- /dev/null +++ b/sw/in_progress/pow/pow/src/nl/justobjects/pushlet/util/Sys.java @@ -0,0 +1,113 @@ +// Copyright (c) 2000 Just Objects B.V. +// Distributable under LGPL license. See terms of license at gnu.org. + +package nl.justobjects.pushlet.util; + + +import java.io.FileInputStream; +import java.io.IOException; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Properties; + +/** + * Utilities that interact with the underlying OS/JVM. + * + * @author Just van den Broecke + * @version $Id: Sys.java,v 1.4 2007/11/10 14:17:18 justb Exp $ + */ +public class Sys { + + /** + * Replace characters having special meaning inside HTML tags + * with their escaped equivalents, using character entities such as '&'. + *

      + *

      The escaped characters are : + *

        + *
      • < + *
      • > + *
      • " + *
      • ' + *
      • \ + *
      • & + *
      + *

      + *

      This method ensures that arbitrary text appearing inside a tag does not "confuse" + * the tag. For example, HREF='Blah.do?Page=1&Sort=ASC' + * does not comply with strict HTML because of the ampersand, and should be changed to + * HREF='Blah.do?Page=1&Sort=ASC'. This is commonly seen in building + * query strings. (In JSTL, the c:url tag performs this task automatically.) + */ + static public String forHTMLTag(String aTagFragment) { + final StringBuffer result = new StringBuffer(); + + final StringCharacterIterator iterator = new StringCharacterIterator(aTagFragment); + char character = iterator.current(); + while (character != CharacterIterator.DONE) { + if (character == '<') { + result.append("<"); + } else if (character == '>') { + result.append(">"); + } else if (character == '\"') { + result.append("""); + } else if (character == '\'') { + result.append("'"); + } else if (character == '\\') { + result.append("\"); + } else if (character == '&') { + result.append("&"); + } else { + //the char is not a special one + //add it to the result as is + result.append(character); + } + character = iterator.next(); + } + return result.toString(); + } + + /** + * Load properties file from classpath. + */ + static public Properties loadPropertiesResource(String aResourcePath) throws IOException { + try { + // Use the class loader that loaded our class. + // This is required where for reasons like security + // multiple class loaders exist, e.g. BEA WebLogic. + // Thanks to Lutz Lennemann 29-aug-2000. + ClassLoader classLoader = Sys.class.getClassLoader(); + + Properties properties = new Properties(); + + // Try loading it. + properties.load(classLoader.getResourceAsStream(aResourcePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties resource from " + aResourcePath); + } + } + + /** + * Load properties file from file path. + */ + static public Properties loadPropertiesFile(String aFilePath) throws IOException { + try { + + Properties properties = new Properties(); + + // Try loading it. + properties.load(new FileInputStream(aFilePath)); + return properties; + } catch (Throwable t) { + throw new IOException("failed loading Properties file from " + aFilePath); + } + } + + /** + * Shorthand for current time. + */ + static public long now() { + return System.currentTimeMillis(); + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/AES.java b/sw/in_progress/pow/pow/src/pow/AES.java new file mode 100644 index 0000000000..c54f5f5de4 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/AES.java @@ -0,0 +1,192 @@ +package pow; + +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +//import java.security.spec.KeySpec; + +import javax.crypto.*; +import javax.crypto.spec.*; + +//import org.apache.commons.codec.binary.Hex; + +import java.io.*; + +/** +* implements AES encryption and decryption algorithms +* @see http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html +*/ + +public class AES { + + private byte[] key; + private SecretKeySpec skeySpec; + private Cipher cipher_encrypt; + private Cipher cipher_decrypt; + // + /** + * construct a cipher with a generated 128 bits key + * @throws InvalidParameterSpecException + * @throws InvalidAlgorithmParameterException + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + */ + public AES() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, InvalidAlgorithmParameterException { + // Get the KeyGenerator + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + kgen.init(128); // 192 and 256 bits may not be available + // Generate the secret key specs. + SecretKey skey = kgen.generateKey(); + key = skey.getEncoded(); + skeySpec = new SecretKeySpec(key, "AES"); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec); + byte[] iv = cipher_encrypt.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + } + /** + * construct a cipher from an user specified key + * @param password + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + * @throws InvalidKeyException + * @throws InvalidParameterSpecException + * @throws InvalidAlgorithmParameterException + * @throws InvalidKeySpecException + */ + public AES(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeySpecException { + // autre facon de generer la cle +/* SecureRandom random = new SecureRandom(); + byte salt[] = new byte[8]; + random.nextBytes(salt); + + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256); + SecretKey tmp = factory.generateSecret(spec); + SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); +*/ + // Get the KeyGenerator + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + kgen.init(128); // 192 and 256 bits may not be available + // Generate the secret key specs. + SecretKey skey = kgen.generateKey(); + key = skey.getEncoded(); + skeySpec = new SecretKeySpec(key, "AES"); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec); + byte[] iv = cipher_encrypt.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + } + /** + * construct a cipher from a key and a parameter array + * usefull to create a remote decryption cypher + * @param key + * @param iv parameter of the cipher + * @throws InvalidKeyException + * @throws InvalidAlgorithmParameterException + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + */ + public AES(byte[] key,byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException{ + skeySpec = new SecretKeySpec(key, "AES"); + key = skeySpec.getEncoded(); + cipher_encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_encrypt.init(Cipher.ENCRYPT_MODE, skeySpec,new IvParameterSpec(iv)); + cipher_decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher_decrypt.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv)); + } + /** + * get the init parameter of the cipher object + */ + public byte[] getParamsEncrypt() throws InvalidParameterSpecException{ + AlgorithmParameters params = cipher_encrypt.getParameters(); + byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); + return iv; + } + /** + * get thecipher key + * @return + */ + public byte[] getKey(){return key;} + +/** + * encrypt a byte array with AES algorithm + * @see org.apache.commons.codec.binary.Hex to convert byte Array into hexString + * @param msg + * @return + * @throws IOException + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + public byte[] encrypt(byte[] msg) throws IOException, IllegalBlockSizeException, BadPaddingException{ + ByteArrayInputStream in= new ByteArrayInputStream(msg); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + crypt(in, out, cipher_encrypt); + return out.toByteArray(); + } + /** + * decrypt a byte array with AES algorithm + * @see org.apache.commons.codec.binary.Hex to convert byte Array into hexString + * @param msg + * @return + * @throws IOException + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + public byte[] decrypt(byte[] msg) throws IOException, IllegalBlockSizeException, BadPaddingException{ + ByteArrayInputStream in= new ByteArrayInputStream(msg); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + crypt(in, out, cipher_decrypt); + return out.toByteArray(); + } + /** + * Crypts or decrypts the specified input stream to the specified output + * stream with a given cipher. The crypting or decrypting operation is + * determined by the cipher's state. + * @param cipher The cipher used to crypt the specified input stream to the specified output + * stream. + * @param in the input srteal stream to be encypted or decrypted. + * @param out the output stream to be encypted or decrypted. + * @throws java.io.IOException if an I/O error occurs during crypting the input stream to the output stream. + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + private void crypt(InputStream in, OutputStream out, Cipher cipher) + throws IOException, IllegalBlockSizeException, BadPaddingException + { + int blockSize = cipher.getBlockSize(); + int outputSize = cipher.getOutputSize(blockSize); + byte[] inBytes = new byte[blockSize]; + byte[] outBytes = new byte[outputSize]; + + int inLength = 0; + boolean done = false; + while(!done) + { + inLength = in.read(inBytes); + if(inLength == blockSize) + { + try + { + int outLength = cipher.update(inBytes, 0, blockSize, outBytes); + out.write(outBytes, 0, outLength); + } + catch(ShortBufferException e) + { + e.printStackTrace(); + } + } + else + done = true; + } + + if(inLength > 0) + outBytes = cipher.doFinal(inBytes, 0, inLength); + else + outBytes = cipher.doFinal(); + out.write(outBytes); + + } +} diff --git a/sw/in_progress/pow/pow/src/pow/AcStatus.java b/sw/in_progress/pow/pow/src/pow/AcStatus.java new file mode 100644 index 0000000000..0f387a1011 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/AcStatus.java @@ -0,0 +1,17 @@ +package pow; +/** + * implements the life cycle of a drone when it is detected on the ivy bus + * @author genin + * + */ +public enum AcStatus { + UNKNOWN, + ASKING_IVY_CONF, + IVY_CONF_RECEIVED, + ASKING_WEB_ID, + WEB_ID_RECEIVED, + UPLOADING_CONF, + CONF_OK, + ALIVE, + CONF_NOTOK +} diff --git a/sw/in_progress/pow/pow/src/pow/AlreadyRegisteredUserException.java b/sw/in_progress/pow/pow/src/pow/AlreadyRegisteredUserException.java new file mode 100644 index 0000000000..6da62c1551 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/AlreadyRegisteredUserException.java @@ -0,0 +1,20 @@ +package pow; +/** + * exception to inform that a user cannot be created in the users' file + * because it exists yet + * @author genin + * + */ +public class AlreadyRegisteredUserException extends Exception { + + private User usr; + + public AlreadyRegisteredUserException (User u){ + usr = u; + } + + public String toString() { + return "AlreadyRegisteredUserException : login " + usr.getLogin() + " is already used" ; + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/BusIvy_.java b/sw/in_progress/pow/pow/src/pow/BusIvy_.java new file mode 100644 index 0000000000..af35fb6f00 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/BusIvy_.java @@ -0,0 +1,61 @@ +package pow; +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.Calendar; +/** + * + * inner representation of an ivy bus + * store the drones' information about the drones which belong to this ivy bus + * store the IP adresse of the machine where the ivy bus is working + */ +public class BusIvy_ +{ + private Calendar oCalendar; + private long oTime; + private InetAddress busAddress; + private ArrayList DronesId = new ArrayList(); + + public void setAddress(InetAddress myInetAddress) + { + busAddress = myInetAddress; + } + public void updateTime() + { + oCalendar=Calendar.getInstance(); + oTime = oCalendar.getTimeInMillis(); + } + public void addDrones(int newDroneId) + { + DronesId.add(newDroneId); + } + public ArrayList getDrones() + { + return DronesId; + } + public void displayDrones() + { + System.out.println("Bus Ivy : "); + System.out.println(busAddress); + System.out.println("Drones : "); + for(Integer myDrone : DronesId) + { + System.out.println(DronesId); + } + } + public InetAddress getAddress() + { + return busAddress; + } + public boolean isOwnBy(int myDroneId) + { + return DronesId.contains(myDroneId); + } + public boolean isAlive() + { + Calendar iCalendar = Calendar.getInstance(); + long iTime = iCalendar.getTimeInMillis(); + + return ((iTime - oTime)<10000); // 10 secondes + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/pow/Conf.java b/sw/in_progress/pow/pow/src/pow/Conf.java new file mode 100644 index 0000000000..c3932d7c23 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Conf.java @@ -0,0 +1,231 @@ +package pow; +import java.io.*; +/** + * + * store usefull datas about the server configuration + * reading a specific file on the tomcat server + */ +public class Conf { + + + private String mailAdmin; + private String adminLogin; + /** + * The port in which the module listen. + */ + private int port; + /** + * The dimension of the datagrams received. + */ + private int taille; + /** + * The passWord of the database + */ + private String passWord; + /** + * The userName of the dataBase + */ + private String userName; + /** + * The Name of the dataBase + */ + private String dataBaseName; + /** + * The timeout of the connection + */ + private int timeout; + /** + * The repertory of configuration files + */ + private String flightPlanRep; + /** + * The port in which msg from web are sended to ivy + */ + private int portWebToIvy ; + + public Conf() + { + File oFile = null; + FileReader oFileReader = null; + BufferedReader oBufferedReader = null; + String fileName = "pow.conf"; + + String line; + + try + { + + oFile = new File("./conf/" + fileName); + //oFile = new File("./" + fileName); + oFileReader = new FileReader(oFile); + oBufferedReader = new BufferedReader(oFileReader); + + while((line = oBufferedReader.readLine())!=null) + { + if( (!(line.startsWith("#")))&&(line.length()!= 0) ) + { + if(line.startsWith(""))); + } + if(line.startsWith(""))); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith(""))); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith(""))); + } + } + } + } + catch(IOException ex) + { + System.out.println("No conf file detected"); + ex.printStackTrace(); + } + + } + + public Conf(String default_folder,String conf_filename) + { + File oFile = null; + FileReader oFileReader = null; + BufferedReader oBufferedReader = null; + String fileName = conf_filename; + + String line; + + try + { + + oFile = new File(default_folder+"/conf/" + fileName); + //oFile = new File("./" + fileName); + oFileReader = new FileReader(oFile); + oBufferedReader = new BufferedReader(oFileReader); + + while((line = oBufferedReader.readLine())!=null) + { + if( (!(line.startsWith("#")))&&(line.length()!= 0) ) + { + if(line.startsWith(""))); + } + if(line.startsWith(""))); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith(""))); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith("")); + } + if(line.startsWith(""))); + } + } + } + } + catch(IOException ex) + { + System.out.println("No conf file detected"); + ex.printStackTrace(); + } + } + + public int port() + { + return port; + } + + public int portWebToIvy() + { + return portWebToIvy; + } + public int taille() + { + return taille; + } + public String passWord() + { + return passWord; + } + public String userName() + { + return userName; + } + public String dataBaseName() + { + return dataBaseName; + } + public int timeout() + { + return timeout; + } + public String flightPlanRep() + { + return flightPlanRep; + } + + public String mailAdmin() + { + return mailAdmin; + } + + public String adminLogin(){ + return adminLogin; + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/pow/ConfJSP.java b/sw/in_progress/pow/pow/src/pow/ConfJSP.java new file mode 100644 index 0000000000..275d803d6d --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/ConfJSP.java @@ -0,0 +1,24 @@ +package pow; +/* +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +*/ +/** + * interface which gives access to useful information to a Java Server Page + */ +public class ConfJSP { + + static Conf powConf = new Conf(); + + public static String getAdminLogin() //throws Exception + { + return powConf.adminLogin(); + } + + public static String getAdminMail() //throws Exception + { + return powConf.mailAdmin(); + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/Greeting.java b/sw/in_progress/pow/pow/src/pow/Greeting.java new file mode 100644 index 0000000000..c1a9497469 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Greeting.java @@ -0,0 +1,147 @@ +package pow; + +import java.io.File; +import java.io.PrintWriter; +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.*; +import java.net.*; +import java.util.Iterator; + +/** + * Servlet implementation class Greeting + * Handles the connection request from a new web client + * check the login's information and rights + */ +public class Greeting extends HttpServlet { + private static final long serialVersionUID = 1L; + private String default_folder="blabla"; + + public void init(ServletConfig config) throws ServletException { + super.init(config); // necessaire sinon getServletContext renvoie null dans doPost + default_folder = config.getServletContext().getRealPath(""); + // creation repertoire conf + /* + String filepath = default_folder + "/conf"; + File repository = new File(filepath); + deleteDirectory(repository); + repository = new File(filepath); + if ((!repository.exists()) && (!repository.isDirectory())) { + repository.mkdir(); // exists isDirectory() + } + */ + // creation d'un fichier d'user par defaut si n'existe pas + File def_user_file = new File(default_folder + "/conf/"+"userTable.tbl"); + if (!def_user_file.exists()){ + User usr0 = new User("admin","pwdadmin",Rights.ADMIN); + User usr1 = new User("toto","pwdtoto",Rights.ADMIN); + User usr2 = new User("tata","pwdtata",Rights.USER); + User usr3 = new User("titi","pwdtiti",Rights.USER); + usr2.addDrone("MJ5"); + usr3.addDrone("TJ1"); + usr3.addDrone("MJ5"); + UserTab logTab = new UserTab(); + try{ + logTab.insert(usr0); + logTab.insert(usr1); + logTab.insert(usr2); + logTab.insert(usr3); + } + catch(AlreadyRegisteredUserException e) {} + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + } + } + + public Greeting(){ + super(); + + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // va chercherla session correspondant à la requete et la crée sinon (param true) + HttpSession session = request.getSession(true); + //Cookie c = new Cookie("nom","valeur"); + //response.addCookie(MonCookie); + String login = request.getParameter("login"); + String password; + response.setContentType("text/html;charset=UTF-8"); + PrintWriter out = response.getWriter(); + if (login ==null) + { + login = "VISITOR"; + password=null; + session.setAttribute("login",login); + session.setAttribute("rights","visitor"); + // ok on lance l'interface + out.println(""); + } + else { + // on verifie la validite du mot de passe + login = request.getParameter("login").toString(); + password = request.getParameter("password").toString(); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + if (logTab.checkUser(login, password)){ + + Rights r = logTab.seek(login).getRights(); + session.setAttribute("login",login); + if (r==Rights.ADMIN){ + session.setAttribute("rights","admin"); + } + else if (r==Rights.USER) { + session.setAttribute("rights","user"); + Iterator itr = logTab.getItrUsr(login); + String dronenameallowedtobectl=""; + if (itr!=null){ + while(itr.hasNext()){ + dronenameallowedtobectl+=itr.next()+";"; + // transmettre la liste des avions a la page web + } + } + session.setAttribute("dronectl",dronenameallowedtobectl); + } + else { + session.setAttribute("rights","visitor");// inutile normalement + } + // ok on lance l'interface + out.println(""); + } + else { + // on renvoie une page d'erreur de login + out.println(""); + } + + } + out.close(); + } + + + static private boolean deleteDirectory(File path) { + boolean resultat = true; + + if( path.exists() ) { + File[] files = path.listFiles(); + for(int i=0; i[:port] [passphrase]"); + return; + } + + File file = new File("jssecacerts"); + if (file.isFile() == false) { + char SEP = File.separatorChar; + File dir = new File(System.getProperty("java.home") + SEP + + "lib" + SEP + "security"); + file = new File(dir, "jssecacerts"); + if (file.isFile() == false) { + file = new File(dir, "cacerts"); + } + } + System.out.println("Loading KeyStore " + file + "..."); + InputStream in = new FileInputStream(file); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(in, passphrase); + in.close(); + + SSLContext context = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; + SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); + context.init(null, new TrustManager[] {tm}, null); + SSLSocketFactory factory = context.getSocketFactory(); + + System.out.println("Opening connection to " + host + ":" + port + "..."); + SSLSocket socket = (SSLSocket)factory.createSocket(host, port); + socket.setSoTimeout(10000); + try { + System.out.println("Starting SSL handshake..."); + socket.startHandshake(); + socket.close(); + System.out.println(); + System.out.println("No errors, certificate is already trusted"); + } catch (SSLException e) { + System.out.println(); + e.printStackTrace(System.out); + } + + X509Certificate[] chain = tm.chain; + if (chain == null) { + System.out.println("Could not obtain server certificate chain"); + return; + } + + BufferedReader reader = + new BufferedReader(new InputStreamReader(System.in)); + + System.out.println(); + System.out.println("Server sent " + chain.length + " certificate(s):"); + System.out.println(); + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + for (int i = 0; i < chain.length; i++) { + X509Certificate cert = chain[i]; + System.out.println + (" " + (i + 1) + " Subject " + cert.getSubjectDN()); + System.out.println(" Issuer " + cert.getIssuerDN()); + sha1.update(cert.getEncoded()); + System.out.println(" sha1 " + toHexString(sha1.digest())); + md5.update(cert.getEncoded()); + System.out.println(" md5 " + toHexString(md5.digest())); + System.out.println(); + } + + System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); + String line = reader.readLine().trim(); + int k; + try { + k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; + } catch (NumberFormatException e) { + System.out.println("KeyStore not changed"); + return; + } + + X509Certificate cert = chain[k]; + String alias = host + "-" + (k + 1); + ks.setCertificateEntry(alias, cert); + + OutputStream out = new FileOutputStream("jssecacerts"); + ks.store(out, passphrase); + out.close(); + + System.out.println(); + System.out.println(cert); + System.out.println(); + System.out.println + ("Added certificate to keystore 'jssecacerts' using alias '" + + alias + "'"); + } + + private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); + + private static String toHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 3); + for (int b : bytes) { + b &= 0xff; + sb.append(HEXDIGITS[b >> 4]); + sb.append(HEXDIGITS[b & 15]); + sb.append(' '); + } + return sb.toString(); + } + + private static class SavingTrustManager implements X509TrustManager { + + private final X509TrustManager tm; + private X509Certificate[] chain; + + SavingTrustManager(X509TrustManager tm) { + this.tm = tm; + } + + public X509Certificate[] getAcceptedIssuers() { + throw new UnsupportedOperationException(); + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + this.chain = chain; + tm.checkServerTrusted(chain, authType); + } + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/Ivy2TomcatHttpServer.java b/sw/in_progress/pow/pow/src/pow/Ivy2TomcatHttpServer.java new file mode 100644 index 0000000000..6a25ccad52 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Ivy2TomcatHttpServer.java @@ -0,0 +1,291 @@ +package pow; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.fileupload.*; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +//import org.apache.commons.fileupload.util.Streams; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Iterator; +import java.io.File; +import java.net.InetAddress; +/** + * Handles the connection request from a new ivy bus + * provide a unique id for the ivy bus + * provide a unique id for each new drone on a ivy bus + * handles the uploading of the configuration files for each new drone on a ivy bus + */ +public class Ivy2TomcatHttpServer extends HttpServlet { + private static final long serialVersionUID = 1L; + private static int webIdCount = 1; + private static int droneIdCount = 1; + private String default_folder="blabla"; + private HashMap tableIvySession ;// correspondance webid,session ivy + /** + * + */ + public Ivy2TomcatHttpServer() { + super(); + + } + + public void init(ServletConfig config) throws ServletException { + // + // faire le menage du repertoire upload + //config.getServletContext().getRealPath(""); + //String default_folder=getServletContext().getRealPath("/"); // repertoire de l'appli + default_folder = config.getServletContext().getRealPath(""); + //System.out.println("default appli folder : "+ default_folder); + + String filepath = default_folder + "/upload"; + File repository = new File(filepath); + deleteDirectory(repository); + repository = new File(filepath); + if ((!repository.exists()) && (!repository.isDirectory())) { + repository.mkdir(); // exists isDirectory() + } + tableIvySession = new HashMap(); + // mise a disposition des sessions pour les autres servlet + config.getServletContext().setAttribute("ivySessionTable", tableIvySession); + // creation d'un fichier d'user pour Ivy par defaut si n'existe pas + File def_user_file = new File(default_folder + "/conf/"+"userIvyTable.tbl"); + if (!def_user_file.exists()){ + User usr0 = new User("admin_ivy","pwdadmin_ivy",Rights.IVY); + UserTab logTab = new UserTab(); + try{ + logTab.insert(usr0); + } + catch(AlreadyRegisteredUserException e) {} + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + } + } + + static private boolean deleteDirectory(File path) { + boolean resultat = true; + + if( path.exists() ) { + File[] files = path.listFiles(); + for(int i=0; i"); + out.println("1"); + out.println(""+newWebId+""); + out.println(""+aesKey+""); + out.println(""+aesIv+""); + out.println(""); + InetAddress remoteClient = InetAddress.getByName(request.getRemoteAddr()); + SessionIvy session = new SessionIvy(login,newWebId,cipher_aes,remoteClient); + tableIvySession.put(remoteClient,session); + out.close(); + System.out.println("**************************************"); + System.out.println("Web Id sended = " + newWebId); + System.out.println("remote client = " + request.getRemoteAddr() + " host=" + request.getRemoteHost() + " port=" + request.getRemotePort()); + System.out.println("key sended = " + aesKey ); + System.out.println("iv parameter = " + aesIv ); + System.out.println("**************************************"); + } + catch (Exception ex){ + PrintWriter out = response.getWriter(); + out.println(""); + out.println("2"); + out.println(""); + out.close(); + System.out.println("AES encryption not supported by server!!!\n"); + ex.printStackTrace(); + } + } + else { + PrintWriter out = response.getWriter(); + out.println(""); + out.println("0"); + out.println(""); + out.close(); + System.out.println("Not authorized access attempt from an ivy client!!!"); + } + } + else if (order.equals("reconnect")) + { + + } + else if (order.equals("requestNewDroneWebId")) + {// client has a webId (not in multipart post) yet and wants to do somtheing else than uploading + System.out.println("Drone Web Id for new drone requested !!!"); + String ivyId = request.getParameter("ivyWebId"); + //String ivyDroneId = request.getParameter("ivyDroneId"); + System.out.println("ivyId " + ivyId + " request new Drone Web Id for unknown ivy drone ");// + ivyDroneId); + int webidsession = Integer.parseInt(ivyId); + //int droneivyid = Integer.parseInt(ivyDroneId); + int newdroneWebId = droneIdCount;droneIdCount++; + PrintWriter out = response.getWriter(); + out.println(""); + out.close(); + System.out.println("new drone Web Id sended (dronewebid = "+newdroneWebId+") !!!"); + } + } + else // client has a webId ( in multipart post) yet and wants to upload conf files + { + System.out.println("uploading file requested..."); + String res = uploadFile(request); + PrintWriter out = response.getWriter(); + out.println(""); + out.println(res); + out.println(""); + out.close(); + }// end if check IvyId + + } + + /* for parameter + see http://stackoverflow.com/questions/992019/java-256bit-aes-encryption + + */ + + + + + /* + * handles the upload of a file from a ivy bus to the server via http + */ + private String uploadFile(HttpServletRequest request){ + boolean isMultipart = ServletFileUpload.isMultipartContent(request); + String resu = "-1"; + List items=null; + String webid="zzz"; + String droneid = "yyy"; + String filepath=""; + // String default_folder=getServletContext().getRealPath("/"); + + System.out.println("!!!def upload rep !!! " + default_folder); + File uploadedFile; + if (isMultipart) + { + // System.out.println("is multipart ...."); + // Create a factory for disk-based file items + FileItemFactory factory = new DiskFileItemFactory(); + // Set factory constraints + // factory.setSizeThreshold(yourMaxMemorySize); + // factory.setRepository(yourTempDirectory); + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(factory); + // Set overall request size constraint + // upload.setSizeMax(yourMaxRequestSize); + // Parse the request + try { + items = upload.parseRequest(request); + // Process the uploaded items + // on cherche le web id + // System.out.println("on cherche le web id ...."); + boolean doIt1 = true;boolean doIt2 = true; + Iterator iter = items.iterator(); + while ((doIt1||doIt2) && iter.hasNext()) { + FileItem item = (FileItem) iter.next(); + if (item.isFormField()) { + String fieldName = item.getFieldName(); + if (fieldName.equals("ivyWebId")){ + doIt1 = false ; + webid = item.getString(); + } + else if (fieldName.equals("droneWebId")){ + doIt2 = false; + droneid = item.getString(); + } + } + } + filepath = default_folder +"/upload/"+droneid; + File repository = new File(filepath); + if ((!repository.exists()) && (!repository.isDirectory())) { + boolean res=repository.mkdir(); // exists isDirectory() + System.out.println("repertoire "+filepath+" cree ? " + res); + } + if (!webid.equals("zzz")){ + // on cherche les fichiers + iter = items.iterator(); + while (iter.hasNext()) { + FileItem item = (FileItem) iter.next(); + if (!item.isFormField()) { // on verifie la nature de l'item + String fileName = item.getName(); + //String contentType = item.getContentType(); + //boolean isInMemory = item.isInMemory(); + //long sizeInBytes = item.getSize(); + uploadedFile = new File(filepath+"/"+fileName); + try { + item.write(uploadedFile); + resu = "1"; + System.out.println("file: "+fileName+" for web drone "+droneid+" was uploaded successfully"); + } catch (Exception e) { + resu = "0"; + System.out.println("unable to write file on server : "+droneid+"/"+fileName); + e.printStackTrace(); + } + } //end if + } // end while + } + } catch (FileUploadException e) { + System.out.println("unable to parse client request "); + e.printStackTrace(); + } + } // end if multipart + return resu; + } +} diff --git a/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading.java b/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading.java new file mode 100644 index 0000000000..136728150f --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading.java @@ -0,0 +1,1071 @@ +package pow; + +import java.io.*; +import java.net.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +//import java.util.Vector; + +import fr.dgac.ivy.*; +import java.lang.*; + + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; + +import java.io.StringReader; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +/** + * This aims to send Udp datagram containing information on the active drones + * to the web serveur + * @author jabln, thomas genin + * @version 2.0 + */ +class Ivy2UdpReading implements Runnable{ + private boolean stopThread; + private InetAddress serveur; + private String login; + private String password; + final static int portUdpSend = 8535; + final static int portUdpReceive = 8536; + private Ivy bus,tempsbus; + final static int taille = 1024; + static int maxAircrafts = 1000; // TODO a changer !!! mettre une map ou qqch + static int datagramLength = 17; // modif , on a rajoute la couleur a la fin + private String datagramMatrix[][] = new String[maxAircrafts][datagramLength];// TODO a changer !!! mettre une map ou qqch + private int aircraftNumber = 0; + private Boolean aircraftAlive[] = new Boolean[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int count[] = new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int countSettings[]=new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private HashMap> settingsToBeChanged = new HashMap>(); + private int webId=-999; + private byte[] aesKey ; + private AES aesCipher; + private String url; + private acNetIdStorage acNetIds; + private ConcurrentHashMap dronesStatus; + /* *********************** */ + private static long time2resetWptFilter = 20*60*1000; // on nettoie les filtres tous les 20min !!!!! + private MsgFilter waypointMsgFilter; + private long chrono_start; + private long elapsed_time; + private long chrono_start2; + private long timeToSendValues=60*1000; // on envoie les values d'un drone toutes les 60 secondes + private HashMap lastvaluesMap; + /* ************************ */ + private long num_msg; + private SimpleDateFormat dateformat; + /* ************************* */ + /** + * create an object which listens on the local ivy bus and send messages to the server + */ + public Ivy2UdpReading(String hostname,String login, String password) + { + num_msg = 0; + dateformat = new SimpleDateFormat("d:M:y:HH:mm:ss"); + stopThread = false; + try{ + this.login = login; + this.password = password; + serveur = InetAddress.getByName(hostname); + // ********************************************* // + this.url = "http://"+hostname+":8080/TestServletPow/Ivy2TomcatHttpServer.srv"; + // ********************************************* // + dronesStatus = new ConcurrentHashMap(); + lastvaluesMap = new HashMap(); + // ********************************************* // + waypointMsgFilter = new MsgFilter(); + chrono_start = System.currentTimeMillis(); + chrono_start2 = System.currentTimeMillis(); + // ********************************************* // + bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + } catch (Exception ie) { + System.out.println("Error : cannot connect to server"); + } + } + /** + * create an object which listens on the local ivy bus and send messages to the server + * @param urlObj describes information about the server + * @param login + * @param password + */ + public Ivy2UdpReading(PowUrl urlObj,String login, String password) + { + stopThread = false; + try{ + this.login = login; + this.password = password; + serveur = InetAddress.getByName(urlObj.getServerName()); + // ********************************************* // + this.url = urlObj.getWebUrl(); + // ********************************************* // + dronesStatus = new ConcurrentHashMap(); + lastvaluesMap = new HashMap(); + // ********************************************* // + waypointMsgFilter = new MsgFilter(); + chrono_start = System.currentTimeMillis(); + chrono_start2 = System.currentTimeMillis(); + // ********************************************* // + bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + } catch (Exception ie) { + System.out.println("Error : cannot connect to server"); + } + } + /* ******************************** */ + /* *********** structure de correspondance entre webid et ivyid pour chaque drone ************ */ + /** + * initiate the object which allow to store information about drones + */ + public void setStorage(){ + acNetIds = new acNetIdStorage(webId,bus,url,maxAircrafts,dronesStatus); + } + /** + * + * @return the structure which allow to store information about drones + */ + public acNetIdStorage getStorage(){ + return acNetIds ; + } + /** + * + * @return the unique id of this ivy bus for the server + */ + public int getIvyWebId(){ + return webId; + } + /** + * methode qui interroge le serveur web tomcat pour lui demander un identifiant unique + * methode get + * @SEE http://hc.apache.org/httpclient-3.x/tutorial.html + * @SEE blogs.sun.com/gc/entry/unable_to_find_valid_certification + * @SEE http://blogs.sun.com/andreas/entry/no_more_unable_to_find + */ + public void getWebId() throws IvyConnectionExeption + { + int res = -1; + int statusCode=-1; + // http config + // SSLUtilities.trustAllHostnames(); + // SSLUtilities.trustAllHttpsCertificates() ; + HttpClient client = new HttpClient(); + client.getParams().setParameter("http.useragent", "Ivy request"); + //si https ... + // inutile mais bon pour 1 connection ... + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + + /* + Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); + Protocol.registerProtocol("https", easyhttps); + client.getHostConfiguration().setHost("localhost", 443, easyhttps); + */ + + PostMethod method = new PostMethod(url); + method.addParameter("order", "requestWebId"); + method.addParameter("login", login); + method.addParameter("pwd", password); + try { + System.out.println("### envoie de la requete requestWebId###"); + statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) { + System.err.println("Method failed: " + method.getStatusLine()); + throw new IvyConnectionExeption("Erreur de retour de la requete de connection"); + } + else + { + // Read the response body. + try { + String responseBody = method.getResponseBodyAsString();//getResponseBody();//); + // Deal with the response + try { + // parse response in XML tree + // @SEE http://java.developpez.com/faq/xml/?page=dom + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(new InputSource(new StringReader(responseBody))); + // get login acknowledgment + Element ack_node = (Element)document.getElementsByTagName("ConnectionAck").item(0); + int ack = Integer.parseInt(ack_node.getTextContent()); + if (ack==1){ + // get webid node + Element webid_node = (Element)document.getElementsByTagName("webid").item(0); + webId = Integer.parseInt(webid_node.getTextContent()); + if (webId==-999) {throw new IvyConnectionExeption("unable to have correct webId");} + // get key node + Element aeskey_node= (Element)document.getElementsByTagName("aeskey").item(0); + String str_hex_aeskey = aeskey_node.getTextContent(); + // get match key node + Element aesiv_node= (Element)document.getElementsByTagName("aesiv").item(0); + String str_hex_aesIvParameter = aesiv_node.getTextContent(); + // + aesKey = Hex.decodeHex(str_hex_aeskey.toCharArray()); + byte[] iv = Hex.decodeHex(str_hex_aesIvParameter.toCharArray()); + aesCipher = new AES(aesKey,iv); + // + System.out.println("##########################"); + System.out.println("### connection ok+\t###"); + System.out.println("### web id = "+ webId +"\t###"); + System.out.println("### aes key = "+ str_hex_aeskey +"\t###"); + System.out.println("##########################"); + } + else if (ack==2){ + throw new IvyConnectionExeption("login ok, but aes encryption not supported by server"); + } + else + { + throw new IvyConnectionExeption("login process failed, you're not allowed to access the server"); + } + } + catch(Exception e) { + e.printStackTrace(); + throw new IvyConnectionExeption("unable to read the server response"); + } + } + catch (IOException e) { + System.err.println("IOException : echec execution requete post : request webId"); + e.printStackTrace(); + throw new IvyConnectionExeption("No response from the server"); + } + } + } catch (HttpException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("HttpException : echec execution requete post : request webId"); + } catch (IOException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("IOException : echec execution requete post : request webId"); + } finally { + method.releaseConnection(); // Release the connection. + + } + } + + /** + * This method binds the object to some messages + * of the bus Ivy. Each information that is needed by the web server is put in an + * array. This array is sent to server. + */ + + public void bindMsg2Ivy() throws IvyException { + for (int i = 0; i < countSettings.length; i++) { + countSettings[i] = 0; + } + + for (int i = 0; i < count.length; i++) { + count[i] = 0; + } + for (int i = 0; i < datagramMatrix.length; i++) { + for (int j = 0; j < datagramMatrix[i].length - 1; j++) { + datagramMatrix[i][j] = new String(" "); + } + } + for (int i = 0; i < aircraftAlive.length; i++) { + aircraftAlive[i] = true; + } + // bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + + bus.bindMsg("ground FLIGHT_PARAM ([^ ]*) [^ ]* [^ ]* [^ ]* ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + //int acId = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + //AcStatus droneState = dronesStatus.get(args[0]); + aircraftIdSeeker a ; + //System.out.println("status drones "+args[0] + ": " + droneState); + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][3] = args[1]; + datagramMatrix[acIndex][4] = args[2]; + datagramMatrix[acIndex][5] = args[3]; + datagramMatrix[acIndex][6] = args[4]; + datagramMatrix[acIndex][7] = args[5]; + datagramMatrix[acIndex][8] = args[6]; + datagramMatrix[acIndex][9] = args[7]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process FLIGHT_PARAM information"); + } + + } + }); + + bus.bindMsg("ground ENGINE_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][10] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process ENGINE_STATUS information"); + } + + } + }); + + bus.bindMsg("ground ENGINE_STATUS ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][12] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + }); + + + bus.bindMsg("ground AP_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][11] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + }); + + bus.bindMsg("ground NAV_STATUS ([^ ]*) ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][13] = args[1]; + // + String j2b[] = new String[1]; + j2b[0] = args[1]; + String s = new String("NAV_STATUS"); + //send(acIndex); + send(acIndex,s,j2b); + // + //send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process NAV_STATUS information"); + } + + } + }); + bus.bindMsg("ground DL_VALUES ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + public void receive(IvyClient client, String[] args){ + try{ + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + String[] settingSplited = args[1].split(","); + String settingId = new String (""); + settingId = settingId + countSettings[acIndex]; + datagramMatrix[acIndex][14] = settingId; + datagramMatrix[acIndex][15] = settingSplited[countSettings[acIndex]]; + send(acIndex); + countSettings[acIndex] = (countSettings[acIndex] + 1) % settingSplited.length; + // gestion de l'A/R de DL_SETTING + // on attend que la valeur du setting soit effectivement change pour envoyer l'A/R + if (settingsToBeChanged.containsKey(acIndex)){ + HashMap h = settingsToBeChanged.get(acIndex); + Set k = h.keySet(); + Iterator itr = k.iterator(); + + while(itr.hasNext()){ + int current_settingid = itr.next(); + float value = h.get(current_settingid); + //System.out.println(""+current_settingid+" "+ value +"=?" +settingSplited[current_settingid]); + if(value==Float.parseFloat(settingSplited[current_settingid])){ + h.remove(current_settingid); + String chgSet[] = new String[2]; + chgSet[0] = ""+current_settingid; + chgSet[1] = ""+value; + String s = new String("DL_SETTING_ACK"); + send(acIndex,s,chgSet); + System.out.print("%"); + } + } + } + // gestion de l'envoie de l'ensemble des valeurs de + // setting pour un drone , on envoie la trame par periode timeToSendValues + Long lasttime = lastvaluesMap.get(acIndex); + long nowtime = System.currentTimeMillis(); + boolean firsttime = false; + if (lasttime==null){ + lasttime = nowtime; + lastvaluesMap.put(acIndex,nowtime); + firsttime = true ; + } + + if (firsttime||((nowtime-lasttime)>timeToSendValues)){ + // on envoie la value + String csv[] = new String[1]; + csv[0] = args[1]; + String s = new String("SETTINGS_VALUES"); + send(acIndex,s,csv); + System.out.print("+"); + lastvaluesMap.put(acIndex,nowtime); + } + + + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch(Exception ie) { + System.out.println("Can't process DL_VALUES information"); + System.out.println("acid= "+args[0]); + System.out.println("csv= "+args[1]); + System.out.println("********************\n"+ie.toString()+"\n********************"); + } + } + }); + // on surveille les messages WAYPOINT_MOVED pour traquer l'A/R d'un ordre venant d'un client web + // qui consisterait a deplacer un waypoint + bus.bindMsg("ground WAYPOINT_MOVED ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)",new IvyMessageListener(){ + public void receive(IvyClient client, String[] args){ + try { + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + String mvWp[] = new String[4]; + for (int j = 0;j<4;j++){ + mvWp[j] = args[j+1]; + } + String s = new String("WAYPOINT_MOVED"); + send(i,s,mvWp); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process MOVE_WAYPOINT information"); + } + } + }); + // on traque ce message pour assurer l'A/R d'un ordre venant d'un client web qui viserait + // a modifier un parametre d'un drone + bus.bindMsg("DL_SETTING ([^ ]*) ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + + public void receive(IvyClient client, String[] args){ + try{ + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int indexAircraft = a.getAcId(); + int indexSetting = Integer.parseInt(args[1]); + float valueSetting = Float.parseFloat(args[2]); + // memorisation qu'une requete DL_SETTING a ete faire + // voir traitement dans ground DL_VALUES + if (!settingsToBeChanged.containsKey(indexAircraft)){ + settingsToBeChanged.put(indexAircraft, new HashMap()); + } + settingsToBeChanged.get(indexAircraft).put(indexSetting, valueSetting); + System.out.print("$"); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process DL_SETTING information"); + } + } + }); + + bus.bindMsg("ground TELEMETRY_STATUS ([^ ]*) ([^ ]*)", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + if (i != -1) { + float f = Float.parseFloat(args[1]); + if (aircraftAlive[i] && f > 30) { + aircraftAlive[i] = false; + String s = new String("Plane_Die"); + send(i, s); + } else { + if (!aircraftAlive[i] && f < 30) { + aircraftAlive[i] = true; + String s = new String("Plane_Resurect"); + send(i, s); + } + } + } + } + } catch (Exception ie) { + + System.out.println("Can't process TELEMETRY_STATUS information"); + } + + } + }); + + bus.start(null); + } + + /* + * add usefull info to msg for storage in database + */ + private String add_info_msg(String msg){ + String monHeure = this.dateformat.format(new Date()); + String res = ""+this.webId+" " + this.num_msg + " " + monHeure +" " + msg; + this.num_msg++; + return res; + } + + /** + * This method send to the web server the datagram containing the informations + * about the aircraft + * @param acId Line of the matrix containing the informations about the plane + * @throws java.lang.Exception + */ + public void send(int acId){// throws Exception { + String s = ""; + if (count[acId] == 5) { + // try { + if (aircraftAlive[acId]) { + byte buffer[];// = new byte[taille]; + s = ""; + for (int i = 1; i < 7; i++) { + s = s + datagramMatrix[acId][i] + " "; + } + for(int i = 7; i< 10;i++){ + //StringBuffer str = new StringBuffer(4); + StringBuffer str = new StringBuffer(datagramMatrix[acId][i]); + str.setLength(5); + s = s + str + " "; + } + for(int i = 10; itaille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + System.out.print("#"); + count[acId] = 0; + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch( IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + //} + //catch (IOException ioex){ System.out.println("socket send exception, Can't send message " + s);} + //catch (Exception ie) { + // System.out.println("Can't send message on the web"); + //} + } else { + count[acId]++; + } + } + + + /** + * This method send to the web server a specific order with parameters + * @param acId : Line of the matrix containing the informations about the plane + * @param s : order + * @param as : parameters + */ + + public void send(int acId, String s, String[] as){ + String order = s; + s = s + " " + datagramMatrix[acId][1]+ " "; + for (int i =0; i< as.length;i++){ + s = s + as[i] + " "; + } + byte buffer[];//= new byte[taille]; + //System.out.println(s); + // gestion de l'ecoute ou non des msg waypoint_moved et des autres msg speciaux + + boolean isnew = true; + // on filtre certains messages + if (order.equals("WAYPOINT_MOVED") + ||order.equals("NAV_STATUS")) + { + //System.out.println("elapsed time : "+elapsed_time); + elapsed_time = System.currentTimeMillis() - chrono_start; + if (elapsed_time>time2resetWptFilter) + { + waypointMsgFilter.resetfilter(); + chrono_start = System.currentTimeMillis(); + } + isnew = waypointMsgFilter.isNew(s); + } + if(isnew){ + System.out.print("!"); + s = this.add_info_msg(s); + buffer = s.getBytes(); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch (IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + } + + + + /** + * This method send a particular message about an aircraft + * @param acId line of the matrix containing the informations about the plane + * @param s message that is to be sent to send + */ + public void send(int acId, String s) { + s = s + " " + datagramMatrix[acId][1]; + byte buffer[] ;//= new byte[taille]; + s = this.add_info_msg(s); + buffer = s.getBytes(); + System.out.println(s); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch (IOException ex){System.out.print("cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + + /** + * listen the udp socket to get orders from web clients and send them to ivy + */ + public void run() { + byte[] complete_data ; + int true_length_of_msg ; + int i; + byte[] data_with_no_padding; + + + // getWebId(); + // login procedure + setStorage(); + try{ + bindMsg2Ivy(); + // on lance le reading + try + { + System.out.println("on lance udp writing "); + int portUdpReceive = 8536 ; + DatagramSocket socket = new DatagramSocket(portUdpReceive); + while (true) { + byte buffer[] = new byte[taille]; + DatagramPacket data = new DatagramPacket(buffer, buffer.length); + try{ + socket.receive(data); + System.out.print("data received from server web : "); + String[] messageed; + try{ + complete_data = data.getData(); + true_length_of_msg = data.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + byte[] decrypted_data = aesCipher.decrypt(data_with_no_padding); + //String s = new String(data.getData());System.out.println(s); + String s = new String(decrypted_data);System.out.println(s); + messageed = s.split(" "); + try{ + // creer un objet d'envoie qui connait la correspondance ivyid et webid pour chaque drone + new Ivy2UdpWriting(messageed, getStorage()); + } + catch(IvyException e1){ System.out.println("erreur sending msg to ivy : " + s);} + } + catch(IOException ex){System.out.print("cipher error : cannot decrypt msg : msg not sended to ivy");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(buffer)))); + System.out.print("cannot encrypt msg : msg not sended to server"); + } + } + catch(IOException e){ System.out.println("erreur socket when receive message");} + } + } + catch(SocketException e){ System.out.println("erreur creation de socket server-->ivy ");} + } + catch (IvyException e){ + System.out.println("unable to bind to ivy...connection failed"); + e.printStackTrace(); + System.exit(0); + } + + } + + + /* + * + */ + public static void main(String argv[]) throws IvyException { + // serveur = InetAddress.getByName(argv[0]); + if (argv.length<1){ + System.out.println("failure :1 params required : [server name or url]"); + } + else { + byte[] complete_data ; + int true_length_of_msg ; + int i; + byte[] data_with_no_padding={'z'}; + try { + // seek user login info + String hostname = argv[0]; + PowUrl connectInfo = new PowUrl("http","blanc",8080,"TestServletPow","Ivy2TomcatHttpServer.srv"); + System.out.println("connecting to : "+ connectInfo.getWebUrl()); + + String login="admin_ivy"; + String password = "pwdadmin_ivy"; + Ivy2UdpReading link = new Ivy2UdpReading(connectInfo,login, password); + link.getWebId(); // login procedure + // + link.setStorage(); + + link.bindMsg2Ivy(); + // on lance le reading + try + { + System.out.println("on lance udp writing "); + int portUdpReceive = 8536 ; + DatagramSocket socket = new DatagramSocket(portUdpReceive); + while (true) { + byte buffer[] = new byte[taille]; + DatagramPacket data = new DatagramPacket(buffer, buffer.length); + try{ + socket.receive(data); + System.out.print("data received from server web : "); + String[] messageed; + try{ + complete_data = data.getData(); + true_length_of_msg = data.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + byte[] decrypted_data = link.aesCipher.decrypt(data_with_no_padding); + //String s = new String(data.getData());System.out.println(s); + String s = new String(decrypted_data);System.out.println(s); + messageed = s.split(" "); + try{ + // creer un objet d'envoie qui connait la correspondance ivyid et webid pour chaque drone + new Ivy2UdpWriting(messageed, link.getStorage()); + } + catch(IvyException e1){ System.out.println("erreur sending msg to ivy : " + s);} + } + catch(IOException ex){System.out.print("cipher error : cannot decrypt msg : msg not sended to ivy");ex.printStackTrace();} + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(data_with_no_padding)))); + System.out.print("cannot decrypt msg : msg not sended to server"); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(data_with_no_padding)))); + System.out.print("cannot decrypt msg : msg not sended to server"); + } + } + catch(IOException e){ System.out.println("erreur socket when receive message");} + } + } + catch(SocketException e){ System.out.println("erreur creation de socket server-->ivy ");} + // + } catch (IvyConnectionExeption e) { + System.out.println(e.toString()); + e.printStackTrace(); + System.exit(0); } + } + } + /* + * Inner class which manage to find the index of a plane according to its ivyid + * if the drone is unknown , an identifiant is requested to the server and its conf files are uploaded + */ + class aircraftIdSeeker { + private String droneId; + private int res; + + public aircraftIdSeeker(String s){ + + droneId = s; + res = -1; + } + + public int getAcId() {return res;} + + public void seek(){ + AcStatus droneState = dronesStatus.get(droneId); + int i = 0; + if (droneState==AcStatus.ALIVE){ + while (i < maxAircrafts && !droneId.equals(datagramMatrix[i][0])) { + i++; + } + if (i < aircraftNumber) { + res = (i); + } + else { + // gtrosse erreur + System.out.println("ERROR , ALIVE BUT NOT IN MATRIX !!!"); + } + } + else if (droneState==AcStatus.UNKNOWN) + { + acNetIds.seekAcNetId(droneId); + } + else if (droneState==AcStatus.CONF_OK) { + acNetId ac = acNetIds.getAcNetId(droneId); + datagramMatrix[aircraftNumber][0] = ac.getIdOnIvy(); // id on IvyBus + datagramMatrix[aircraftNumber][1] = ac.getIdOnWeb(); // id on Web Client + datagramMatrix[aircraftNumber][2] = ac.getName(); // name + datagramMatrix[aircraftNumber][16] = ac.getColor(); + dronesStatus.replace(droneId,AcStatus.ALIVE); + // + if (datagramMatrix[aircraftNumber][0].equals(" ")) { + res= (-1); + } else { + aircraftNumber++; + String newPlane = new String("New_Plane"); + String name[] = new String[1]; + name[0] = ac.getName(); + send(aircraftNumber - 1, newPlane,name); + //int acWebId = Integer.parseInt(ac.getIdOnWeb()); + //send(acWebId, newPlane); + res= (aircraftNumber - 1); + } + } + else { + // do thing + } + } + } //fin class acId + +} // fin class ivy2udpreading + + + + + + + diff --git a/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading2.java b/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading2.java new file mode 100644 index 0000000000..4944ee6c23 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Ivy2UdpReading2.java @@ -0,0 +1,915 @@ +package pow; + +import java.io.*; +import java.net.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +//import java.util.Vector; + +import fr.dgac.ivy.*; +import java.lang.*; + + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; + +import java.util.concurrent.Semaphore; + +import java.io.StringReader; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +/** + * This aims to send Udp datagram containing information on the active drones + * to the web serveur + * @author jabln, thomas genin + * @version 2.0 + */ +class Ivy2UdpReading2 { + + static InetAddress serveur; + final static int portUdpSend = 8535; + final static int portUdpReceive = 8536; + private Ivy bus,tempsbus; + final static int taille = 1024; + static int maxAircrafts = 1000; // TODO a changer !!! mettre une map ou qqch + static int datagramLength = 17; // modif , on a rajoute la couleur a la fin + private String datagramMatrix[][] = new String[maxAircrafts][datagramLength];// TODO a changer !!! mettre une map ou qqch + private int aircraftNumber = 0; + private Boolean aircraftAlive[] = new Boolean[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int count[] = new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private int countSettings[]=new int[maxAircrafts];// TODO a changer !!! mettre une map ou qqch + private HashMap> settingsToBeChanged = new HashMap>(); + private int webId=-999; + private byte[] aesKey ; + private AES aesCipher; + private String url; + private acNetIdStorage acNetIds; + private ConcurrentHashMap dronesStatus; + /* *********************** */ + private static long time2resetWptFilter = 20*60*1000; // on nettoie les filtres tous les 20min !!!!! + private MsgFilter waypointMsgFilter; + private long chrono_start; + private long elapsed_time; + private long chrono_start2; + private long timeToSendValues=60*1000; // on envoie les values d'un drone toutes les 60 secondes + private HashMap lastvaluesMap; + + /* *********** structure de correspondance entre webid et ivyid pour chaque drone ************ */ + public void setStorage(){ + acNetIds = new acNetIdStorage(webId,bus,url,maxAircrafts,dronesStatus); + } + + public acNetIdStorage getStorage(){ + return acNetIds ; + } + /* ************************* */ + public Ivy2UdpReading2(String hostname) + { + try{ + serveur = InetAddress.getByName(hostname); + // ********************************************* // + url = "http://"+hostname+":8080/TestServletPow/Ivy2TomcatHttpServer.srv"; + // ********************************************* // + dronesStatus = new ConcurrentHashMap(); + lastvaluesMap = new HashMap(); + // ********************************************* // + waypointMsgFilter = new MsgFilter(); + chrono_start = System.currentTimeMillis(); + chrono_start2 = System.currentTimeMillis(); + // ********************************************* // + bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + } catch (Exception ie) { + System.out.println("Error : cannot connect to server"); + } + } + + public int getIvyWebId(){ + return webId; + } + /** + * methode qui interroge le serveur web tomcat pour lui demander un identifiant unique + * methode get + * @SEE http://hc.apache.org/httpclient-3.x/tutorial.html + */ + public void getWebId(String login , String pwd) throws IvyConnectionExeption + { + int statusCode=-1; + HttpClient client = new HttpClient(); + client.getParams().setParameter("http.useragent", "Ivy request"); + PostMethod method = new PostMethod(url); + /* + NameValuePair[] data = { + new NameValuePair("requestWebId", "xxx"), + new NameValuePair("password", "bloggs") + }; + method.setRequestBody(data); + */ + + // static InetAddress InetAddress.getByAddress(byte[] addr) ; + + method.addParameter("order", "requestWebId"); + method.addParameter("login", login); + method.addParameter("pwd", pwd); + try { + System.out.println("### envoie de la requete requestWebId###"); + statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) { + System.err.println("Method failed: " + method.getStatusLine()); + //System.exit(0);// on clot l'appli + throw new IvyConnectionExeption("Erreur de retour de la requete de connection"); + } + else + { + // Read the response body. + try { + String responseBody = method.getResponseBodyAsString();//getResponseBody();//); + // Deal with the response + try { + // parse response in XML tree + // @SEE http://java.developpez.com/faq/xml/?page=dom + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(new InputSource(new StringReader(responseBody))); + // get login acknowledgment + Element ack_node = (Element)document.getElementsByTagName("ConnectionAck").item(0); + int ack = Integer.parseInt(ack_node.getTextContent()); + if (ack==1){ + // get webid node + Element webid_node = (Element)document.getElementsByTagName("webid").item(0); + webId = Integer.parseInt(webid_node.getTextContent()); + if (webId==-999) {throw new IvyConnectionExeption("unable to have correct webId");} + // get key node + Element aeskey_node= (Element)document.getElementsByTagName("aeskey").item(0); + String str_hex_aeskey = aeskey_node.getTextContent(); + // get match key node + Element aesiv_node= (Element)document.getElementsByTagName("aesiv").item(0); + String str_hex_aesIvParameter = aesiv_node.getTextContent(); + // + aesKey = Hex.decodeHex(str_hex_aeskey.toCharArray()); + byte[] iv = Hex.decodeHex(str_hex_aesIvParameter.toCharArray()); + aesCipher = new AES(aesKey,iv); + // + System.out.println("##########################"); + System.out.println("### connection ok+\t###"); + System.out.println("### web id = "+ webId +"\t###"); + System.out.println("### aes key = "+ str_hex_aeskey +"\t###"); + System.out.println("##########################"); + + } + else if (ack==2){ + throw new IvyConnectionExeption("login ok, but aes encryption not supported by server"); + } + else + { + throw new IvyConnectionExeption("login process failed, you're not allowed to access the server"); + } + + } + catch(Exception e) { + e.printStackTrace(); + throw new IvyConnectionExeption("unable to read the server response"); + } + } + catch (IOException e) { + System.err.println("IOException : echec execution requete post : request webId"); + e.printStackTrace(); + throw new IvyConnectionExeption("No response from the server"); + } + } + } catch (HttpException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("HttpException : echec execution requete post : request webId"); + } catch (IOException e) { + e.printStackTrace(); + throw new IvyConnectionExeption("IOException : echec execution requete post : request webId"); + } finally { + method.releaseConnection(); // Release the connection. + + } + + /* HttpClient client = new HttpClient(); + //client.getState().setCredentials( + // new AuthScope("ivybus", 443, "realm"), + // new UsernamePasswordCredentials("username", "password") + // ); + GetMethod method = new GetMethod(url); + // method.setDoAuthentication( true ); + // Provide custom retry handler is necessary + method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, + new DefaultHttpMethodRetryHandler(3, false)); + */ + } + + + + + + + /** + * This method binds the object to some messages + * of the bus Ivy. Each information that is needed by the web server is put in an + * array. This array is sent to server. + */ + + public void bindMsg2Ivy() throws IvyException { + for (int i = 0; i < countSettings.length; i++) { + countSettings[i] = 0; + } + + for (int i = 0; i < count.length; i++) { + count[i] = 0; + } + for (int i = 0; i < datagramMatrix.length; i++) { + for (int j = 0; j < datagramMatrix[i].length - 1; j++) { + datagramMatrix[i][j] = new String(" "); + } + } + for (int i = 0; i < aircraftAlive.length; i++) { + aircraftAlive[i] = true; + } + // bus = new Ivy("Ivy2Udp", "Ivy2Udp Ready", null); + + bus.bindMsg("ground FLIGHT_PARAM ([^ ]*) [^ ]* [^ ]* [^ ]* ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + //int acId = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + //AcStatus droneState = dronesStatus.get(args[0]); + aircraftIdSeeker a ; + //System.out.println("status drones "+args[0] + ": " + droneState); + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][3] = args[1]; + datagramMatrix[acIndex][4] = args[2]; + datagramMatrix[acIndex][5] = args[3]; + datagramMatrix[acIndex][6] = args[4]; + datagramMatrix[acIndex][7] = args[5]; + datagramMatrix[acIndex][8] = args[6]; + datagramMatrix[acIndex][9] = args[7]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process FLIGHT_PARAM information"); + } + + } + }); + + bus.bindMsg("ground ENGINE_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][10] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process ENGINE_STATUS information"); + } + + } + }); + + bus.bindMsg("ground ENGINE_STATUS ([^ ]*) ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][12] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + }); + + + bus.bindMsg("ground AP_STATUS ([^ ]*) [^ ]* [^ ]* [^ ]* [^ ]* ([^ ]*) .*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][11] = args[1]; + send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process AP_STATUS information"); + } + + } + }); + + bus.bindMsg("ground NAV_STATUS ([^ ]*) ([^ ]*).*", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + datagramMatrix[acIndex][13] = args[1]; + // + String j2b[] = new String[1]; + j2b[0] = args[1]; + String s = new String("NAV_STATUS"); + //send(acIndex); + send(acIndex,s,j2b); + // + //send(acIndex); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch (Exception ie) { + System.out.println("Can't process NAV_STATUS information"); + } + + } + }); + + + bus.bindMsg("ground DL_VALUES ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + + public void receive(IvyClient client, String[] args){ + try{ + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE){ + a = new aircraftIdSeeker(args[0]); + a.seek(); + int acIndex = a.getAcId(); + if (acIndex != -1) { + String[] settingSplited = args[1].split(","); + String settingId = new String (""); + settingId = settingId + countSettings[acIndex]; + datagramMatrix[acIndex][14] = settingId; + datagramMatrix[acIndex][15] = settingSplited[countSettings[acIndex]]; + send(acIndex); + countSettings[acIndex] = (countSettings[acIndex] + 1) % settingSplited.length; + // gestion de l'A/R de DL_SETTING + // on attend que la valeur du setting soit effectivement change pour envoyer l'A/R + if (settingsToBeChanged.containsKey(acIndex)){ + HashMap h = settingsToBeChanged.get(acIndex); + Set k = h.keySet(); + Iterator itr = k.iterator(); + + while(itr.hasNext()){ + int current_settingid = itr.next(); + float value = h.get(current_settingid); + //System.out.println(""+current_settingid+" "+ value +"=?" +settingSplited[current_settingid]); + if(value==Float.parseFloat(settingSplited[current_settingid])){ + h.remove(current_settingid); + String chgSet[] = new String[2]; + chgSet[0] = ""+current_settingid; + chgSet[1] = ""+value; + String s = new String("DL_SETTING_ACK"); + send(acIndex,s,chgSet); + System.out.print("%"); + } + } + } + // gestion de l'envoie de l'ensemble des valeurs de + // setting pour un drone , on envoie la trame par periode timeToSendValues + Long lasttime = lastvaluesMap.get(acIndex); + long nowtime = System.currentTimeMillis(); + boolean firsttime = false; + if (lasttime==null){ + lasttime = nowtime; + lastvaluesMap.put(acIndex,nowtime); + firsttime = true ; + } + + if (firsttime||((nowtime-lasttime)>timeToSendValues)){ + // on envoie la value + String csv[] = new String[1]; + csv[0] = args[1]; + String s = new String("SETTINGS_VALUES"); + send(acIndex,s,csv); + System.out.print("+"); + lastvaluesMap.put(acIndex,nowtime); + } + + + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + } catch(Exception ie) { + System.out.println("Can't process DL_VALUES information"); + System.out.println("acid= "+args[0]); + System.out.println("csv= "+args[1]); + System.out.println("********************\n"+ie.toString()+"\n********************"); + } + } + + + + }); + + + + // bus.bindMsg("MOVE_WAYPOINT ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)",new IvyMessageListener(){ + + // on surveille les messages WAYPOINT_MOVED pour traquer l'A/R d'un ordre venant d'un client web + // qui consisterait a deplacer un waypoint + bus.bindMsg("ground WAYPOINT_MOVED ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)",new IvyMessageListener(){ + public void receive(IvyClient client, String[] args){ + try { + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + String mvWp[] = new String[4]; + for (int j = 0;j<4;j++){ + mvWp[j] = args[j+1]; + } + String s = new String("WAYPOINT_MOVED"); + send(i,s,mvWp); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process MOVE_WAYPOINT information"); + } + } + }); + // on traque ce message pour assurer l'A/R d'un ordre venant d'un client web qui viserait + // a modifier un parametre d'un drone + bus.bindMsg("DL_SETTING ([^ ]*) ([^ ]*) ([^ ]*)", new IvyMessageListener(){ + + public void receive(IvyClient client, String[] args){ + try{ + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int indexAircraft = a.getAcId(); + int indexSetting = Integer.parseInt(args[1]); + float valueSetting = Float.parseFloat(args[2]); + // memorisation qu'une requete DL_SETTING a ete faire + // voir traitement dans ground DL_VALUES + if (!settingsToBeChanged.containsKey(indexAircraft)){ + settingsToBeChanged.put(indexAircraft, new HashMap()); + } + settingsToBeChanged.get(indexAircraft).put(indexSetting, valueSetting); + System.out.print("$"); + } + else // autres etats UNKNOWN,ASKING_IVY_CONF,ASKING_WEB_ID, + { + //do nothing // skip message + } + } + catch (Exception ie){ + System.out.println("Can't process DL_SETTING information"); + } + } + }); + + bus.bindMsg("ground TELEMETRY_STATUS ([^ ]*) ([^ ]*)", new IvyMessageListener() { + + public void receive(IvyClient client, String[] args) { + + try { + //int i = acId(args[0]); + AcStatus droneState=dronesStatus.putIfAbsent(args[0],AcStatus.UNKNOWN); + aircraftIdSeeker a ; + if ((droneState==AcStatus.UNKNOWN)||(droneState==AcStatus.CONF_OK)) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + } + else if (droneState==AcStatus.ALIVE) + { + a = new aircraftIdSeeker(args[0]); + a.seek(); + int i = a.getAcId(); + if (i != -1) { + float f = Float.parseFloat(args[1]); + if (aircraftAlive[i] && f > 30) { + aircraftAlive[i] = false; + String s = new String("Plane_Die"); + send(i, s); + } else { + if (!aircraftAlive[i] && f < 30) { + aircraftAlive[i] = true; + String s = new String("Plane_Resurect"); + send(i, s); + } + } + } + } + } catch (Exception ie) { + + System.out.println("Can't process TELEMETRY_STATUS information"); + } + + } + }); + + bus.start(null); + } + + /** + * This method send to the web server the datagram containing the informations + * about the aircraft + * @param acId Line of the matrix containing the informations about the plane + * @throws java.lang.Exception + */ + public void send(int acId){// throws Exception { + String s = ""; + if (count[acId] == 5) { + // try { + if (aircraftAlive[acId]) { + byte buffer[];// = new byte[taille]; + s = ""; + for (int i = 1; i < 7; i++) { + s = s + datagramMatrix[acId][i] + " "; + } + for(int i = 7; i< 10;i++){ + //StringBuffer str = new StringBuffer(4); + StringBuffer str = new StringBuffer(datagramMatrix[acId][i]); + str.setLength(5); + s = s + str + " "; + } + for(int i = 10; itaille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + System.out.print("#"); + count[acId] = 0; + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch( IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + } + //} + //catch (IOException ioex){ System.out.println("socket send exception, Can't send message " + s);} + //catch (Exception ie) { + // System.out.println("Can't send message on the web"); + //} + } else { + count[acId]++; + } + } + + + /** + * This method send to the web server a specific order with parameters + * @param acId : Line of the matrix containing the informations about the plane + * @param s : order + * @param as : parameters + */ + + public void send(int acId, String s, String[] as){ + String order = s; + s = s + " " + datagramMatrix[acId][1]+ " "; + for (int i =0; i< as.length;i++){ + s = s + as[i] + " "; + } + byte buffer[];//= new byte[taille]; + //System.out.println(s); + // gestion de l'ecoute ou non des msg waypoint_moved et des autres msg speciaux + + boolean isnew = true; + // on filtre certains messages + if (order.equals("WAYPOINT_MOVED") + ||order.equals("NAV_STATUS")) + { + //System.out.println("elapsed time : "+elapsed_time); + elapsed_time = System.currentTimeMillis() - chrono_start; + if (elapsed_time>time2resetWptFilter) + { + waypointMsgFilter.resetfilter(); + chrono_start = System.currentTimeMillis(); + } + isnew = waypointMsgFilter.isNew(s); + } + if(isnew){ + System.out.print("!"); + buffer = s.getBytes(); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch (IOException ex){System.out.print("cipher error : cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + } + } + + + + /** + * This method send a particular message about an aircraft + * @param acId line of the matrix containing the informations about the plane + * @param s message that is to be sent to send + */ + public void send(int acId, String s) { + s = s + " " + datagramMatrix[acId][1]; + byte buffer[] ;//= new byte[taille]; + buffer = s.getBytes(); + System.out.println(s); + try{ + buffer = this.aesCipher.encrypt(buffer); + if (buffer.length>taille){System.out.println("Alerte taille trame udp:"+buffer.length+" !!!!");} + DatagramPacket dataUdp = new DatagramPacket(buffer, buffer.length, serveur, portUdpSend); + try{ + DatagramSocket socketUdp = new DatagramSocket(); + try{ + socketUdp.send(dataUdp); + } + catch(IOException ex){System.out.print("datagram creation error : msg not sended");} + } + catch (SocketException ex){System.out.print("socket error : msg not sended");} + + } + catch (IOException ex){System.out.print("cannot encrypt msg : msg not sended to server");ex.printStackTrace();} + } + + /* + * + */ + public static void main(String argv[]) throws IvyException { + // serveur = InetAddress.getByName(argv[0]); + if (argv.length<1){ + System.out.println("failure :1 params required : [server name or url]"); + } + else { + byte[] complete_data ; + int true_length_of_msg ; + int i; + byte[] data_with_no_padding; + String hostname = argv[0]; + Ivy2UdpReading2 link = new Ivy2UdpReading2(hostname ); + try { + // seek user login info + String login="admin_ivy"; + String password = "pwdadmin_ivy"; + link.getWebId(login, password); // login procedure + // + link.setStorage(); + link.bindMsg2Ivy(); + // on lance le reading + try + { + System.out.println("on lance udp writing "); + int portUdpReceive = 8536 ; + DatagramSocket socket = new DatagramSocket(portUdpReceive); + while (true) { + byte buffer[] = new byte[taille]; + DatagramPacket data = new DatagramPacket(buffer, buffer.length); + try{ + socket.receive(data); + System.out.print("data received from server web : "); + String[] messageed; + try{ + complete_data = data.getData(); + true_length_of_msg = data.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + byte[] decrypted_data = link.aesCipher.decrypt(data_with_no_padding); + //String s = new String(data.getData());System.out.println(s); + String s = new String(decrypted_data);System.out.println(s); + messageed = s.split(" "); + try{ + // creer un objet d'envoie qui connait la correspondance ivyid et webid pour chaque drone + new Ivy2UdpWriting(messageed, link.getStorage()); + } + catch(IvyException e1){ System.out.println("erreur sending msg to ivy : " + s);} + } + catch(IOException ex){System.out.print("cipher error : cannot decrypt msg : msg not sended to ivy");ex.printStackTrace();} + } + catch(IOException e){ System.out.println("erreur socket when receive message");} + } + } + catch(SocketException e){ System.out.println("erreur creation de socket server-->ivy ");} + // + } catch (IvyConnectionExeption e) { + System.out.println(e.toString()); + e.printStackTrace(); + System.exit(0); } + } + } + /* + * Inner class which manage to find the index of a plane according to its ivyid + * if the drone is unknown , an identifiant is requested to the server and its conf files are uploaded + */ + class aircraftIdSeeker { + private String droneId; + private int res; + + public aircraftIdSeeker(String s){ + + droneId = s; + res = -1; + } + + public int getAcId() {return res;} + + public void seek(){ + AcStatus droneState = dronesStatus.get(droneId); + int i = 0; + if (droneState==AcStatus.ALIVE){ + while (i < maxAircrafts && !droneId.equals(datagramMatrix[i][0])) { + i++; + } + if (i < aircraftNumber) { + res = (i); + } + else { + // gtrosse erreur + System.out.println("ERROR , ALIVE BUT NOT IN MATRIX !!!"); + } + } + else if (droneState==AcStatus.UNKNOWN) + { + acNetIds.seekAcNetId(droneId); + } + else if (droneState==AcStatus.CONF_OK) { + acNetId ac = acNetIds.getAcNetId(droneId); + datagramMatrix[aircraftNumber][0] = ac.getIdOnIvy(); // id on IvyBus + datagramMatrix[aircraftNumber][1] = ac.getIdOnWeb(); // id on Web Client + datagramMatrix[aircraftNumber][2] = ac.getName(); // name + datagramMatrix[aircraftNumber][16] = ac.getColor(); + dronesStatus.replace(droneId,AcStatus.ALIVE); + // + if (datagramMatrix[aircraftNumber][0].equals(" ")) { + res= (-1); + } else { + aircraftNumber++; + String newPlane = new String("New_Plane"); + String name[] = new String[1]; + name[0] = ac.getName(); + send(aircraftNumber - 1, newPlane,name); + //int acWebId = Integer.parseInt(ac.getIdOnWeb()); + //send(acWebId, newPlane); + res= (aircraftNumber - 1); + } + } + else { + // do thing + } + } + } //fin class acId +} // fin class ivy2udpreading + + + + + + + diff --git a/sw/in_progress/pow/pow/src/pow/Ivy2UdpWriting.java b/sw/in_progress/pow/pow/src/pow/Ivy2UdpWriting.java new file mode 100644 index 0000000000..9eff025809 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Ivy2UdpWriting.java @@ -0,0 +1,65 @@ +package pow; + +import java.io.*; +import java.net.*; +import fr.dgac.ivy.*; + +/** + * This class aims to give order to the drones according to the datagrams it + * receive from the web + * @author jabln + */ +class Ivy2UdpWriting implements IvyMessageListener { + + //static InetAddress serveur; + // final static int port = 8535; + //final static int taille = 1024; + private Ivy bus; + private acNetIdStorage netIdStorage; + private String[] message; //Array which contains the informations are to be sent on the bus + private String IvyAcId; //Identity of the aircraft on the bus Ivy + + /** + * This constructor of the class binds to the bus Ivy and implements the + * method receive to send on the bus the informations given in parametres + * in an array of string + * @param message Informations that is to be sent on the bus Ivy + * @param storage the object which to do the link between webid and ivyid for each drone + * @throws java.lang.Exception + */ + Ivy2UdpWriting(String[] message, acNetIdStorage storage) throws IvyException { + this.message = message; + netIdStorage = storage; + int acwebid = Integer.parseInt(message[1]); + this.IvyAcId = netIdStorage.getAcIvyId(acwebid); + if ( this.IvyAcId != null) { + bus = new Ivy("Web Writing", "Web Writing ready", null); + bus.start(null); + bus.bindMsg("FLIGHT_PARA.*", this); + } + else + { + System.out.println("enable to make the link between webid on ivyidy"); + } + } + + /** + * This method implements the method receive of the bus Ivy class. It sends + * the informations on the bus and stop the bind + * @param client + * @param args + */ + public void receive(IvyClient client, String args[]) { + try { + String s = "WEB_MSG "; + s = s + message[0] + " " + IvyAcId + " "; + for (int i = 2; i < message.length; i++) { + s = s + message[i] + " "; + } + bus.sendMsg(s); + bus.stop(); + } catch (IvyException ie) { + System.out.println("can't send my message on the bus"); + } + } +} diff --git a/sw/in_progress/pow/pow/src/pow/IvyConnectionExeption.java b/sw/in_progress/pow/pow/src/pow/IvyConnectionExeption.java new file mode 100644 index 0000000000..8fc3c3c7de --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/IvyConnectionExeption.java @@ -0,0 +1,18 @@ +package pow; + +public class IvyConnectionExeption extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1805159521752564076L; + private String reason; + + public IvyConnectionExeption(String res){ + super(); + reason = res; + } + public String toString() { + return "IvyConnectionExeption : "+reason; + } +} diff --git a/sw/in_progress/pow/pow/src/pow/IvyIHM.java b/sw/in_progress/pow/pow/src/pow/IvyIHM.java new file mode 100644 index 0000000000..9d3a61b1fb --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/IvyIHM.java @@ -0,0 +1,299 @@ +package pow; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class IvyIHM { + private JFrame glob_fenetre; + private JLabel login_lbl; + private JTextField login_txtfield; + private JLabel pwd_lbl; + private JPasswordField pwd_txtfield; + private JLabel url_lbl; + private JTextField url_txtfield; + + private Container contenuMore; + private boolean moreIsVisible ; + private JLabel protocol_lbl; + private JComboBox protocol_field; + private JLabel port_lbl; + private JComboBox port_field; + private JLabel site_lbl; + private JTextField site_txtfield; + private JLabel servlet_lbl; + private JTextField servlet_txtfield; + private String[] protocolsStrings = { "http", "https" }; + private String[] portsStrings = { "none", "80","8080","443" }; + private JButton log_btn; + private JButton quit_btn; + private JButton more_btn; + private boolean logged ; + private static int taille_text = 20; + public IvyIHM(){ + logged = false; + glob_fenetre = new JFrame("Connection to POW Server"); + glob_fenetre.setLocation(100,200); + + Container contenuTextField ; + //ensemble des textfiled + JPanel listTextField= new JPanel(); + listTextField.setLayout(new BoxLayout(listTextField, BoxLayout.PAGE_AXIS)); + contenuTextField = new JPanel(new FlowLayout()); + login_lbl = new JLabel("login"); + login_txtfield= new JTextField("",taille_text); + contenuTextField.add(login_lbl); + contenuTextField.add(login_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + pwd_lbl = new JLabel("password"); + pwd_txtfield= new JPasswordField(taille_text); + contenuTextField.add(pwd_lbl); + contenuTextField.add(pwd_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + url_lbl = new JLabel("hostname"); + url_txtfield= new JTextField("",taille_text); + contenuTextField.add(url_lbl); + contenuTextField.add(url_txtfield); + listTextField.add(contenuTextField); + // + listTextField.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + // les deux boutons + + log_btn = new JButton("Log !"); + quit_btn = new JButton("Quit !");; + Container contenuButton = new JPanel(new FlowLayout()); + contenuButton.add(quit_btn); + contenuButton.add(log_btn); + + log_btn.addActionListener(new LogAction()); + quit_btn.addActionListener(new QuitAction()); + // + glob_fenetre.setLayout(new BorderLayout()); + Container contenu = glob_fenetre.getContentPane(); + contenu.add(listTextField,BorderLayout.CENTER); + contenu.add(contenuButton,BorderLayout.SOUTH); + glob_fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + glob_fenetre.pack(); + glob_fenetre.setVisible(true); + } + + public IvyIHM(boolean t){ + logged = false; + glob_fenetre = new JFrame("Connection to POW Server"); + glob_fenetre.setLocation(100,200); + + Container contenuTextField ; + //ensemble des textfiled + JPanel listTextField= new JPanel(); + listTextField.setLayout(new BoxLayout(listTextField, BoxLayout.PAGE_AXIS)); + contenuTextField = new JPanel(new FlowLayout()); + login_lbl = new JLabel("login"); + login_txtfield= new JTextField("admin_ivy",taille_text); + contenuTextField.add(login_lbl); + contenuTextField.add(login_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + pwd_lbl = new JLabel("password"); + pwd_txtfield= new JPasswordField("pwdadmin_ivy",taille_text); + contenuTextField.add(pwd_lbl); + contenuTextField.add(pwd_txtfield); + listTextField.add(contenuTextField); + // + contenuTextField = new JPanel(new FlowLayout()); + url_lbl = new JLabel("hostname"); + url_txtfield= new JTextField("blanc",taille_text); + contenuTextField.add(url_lbl); + contenuTextField.add(url_txtfield); + listTextField.add(contenuTextField); + // + listTextField.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + // les trois boutons + more_btn = new JButton("More..."); + log_btn = new JButton("Log !"); + quit_btn = new JButton("Quit !");; + Container contenuButton = new JPanel(new FlowLayout()); + contenuButton.add(quit_btn); + contenuButton.add(log_btn); + contenuButton.add(more_btn); + more_btn.addActionListener(new MoreAction(glob_fenetre)); + log_btn.addActionListener(new LogAction()); + quit_btn.addActionListener(new QuitAction()); + //le panneau more.... + contenuMore = new JPanel(); + contenuMore.setLayout(new BoxLayout(contenuMore, BoxLayout.PAGE_AXIS)); + + Container contenuMoreMore = new JPanel(new FlowLayout()); + + protocol_field = new JComboBox(protocolsStrings); + protocol_lbl = new JLabel("protocol"); + contenuMoreMore.add(protocol_lbl); + contenuMoreMore.add(protocol_field); + //contenuMore.add(contenuMoreMore); + + //contenuMoreMore = new JPanel(new FlowLayout()); + port_lbl = new JLabel("port"); + port_field = new JComboBox(portsStrings);; + contenuMoreMore.add(port_lbl); + contenuMoreMore.add(port_field); + contenuMore.add(contenuMoreMore); + + contenuMoreMore = new JPanel(new FlowLayout()); + site_lbl= new JLabel("site name"); + site_txtfield= new JTextField("TestServletPow",taille_text); + contenuMoreMore.add(site_lbl); + contenuMoreMore.add(site_txtfield); + contenuMore.add(contenuMoreMore); + + contenuMoreMore = new JPanel(new FlowLayout()); + servlet_lbl= new JLabel("servlet name"); + servlet_txtfield= new JTextField("Ivy2TomcatHttpServer.srv",taille_text); + contenuMoreMore.add(servlet_lbl); + contenuMoreMore.add(servlet_txtfield); + contenuMore.add(contenuMoreMore); + moreIsVisible = false; + contenuMore.setVisible(moreIsVisible); + // + glob_fenetre.setLayout(new BorderLayout()); + Container contenu = glob_fenetre.getContentPane(); + contenu.add(listTextField,BorderLayout.NORTH); + contenu.add(contenuMore,BorderLayout.CENTER); + contenu.add(contenuButton,BorderLayout.SOUTH); + glob_fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + glob_fenetre.pack(); + glob_fenetre.setVisible(true); + } + + public static void main(String[] args) + { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new IvyIHM(true); + } + }); + } + + class QuitAction implements ActionListener { + public void actionPerformed(ActionEvent e){ + Runnable code = new Runnable() { + public void run() { + + System.exit(0); + + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + + } + } + + + class LogAction implements ActionListener { + public void actionPerformed(ActionEvent e){ + if(!logged){ + Runnable code = new Runnable() { + public void run() { + Ivy2UdpReading module; + String login = login_txtfield.getText(); + String host = url_txtfield.getText(); + char[] pwd_array = pwd_txtfield.getPassword(); + String pwd = new String(pwd_array); + if (moreIsVisible){ + String siteName = site_txtfield.getText(); + String servletName = servlet_txtfield.getText(); + String strports ; + strports = portsStrings[port_field.getSelectedIndex()]; + int port=-1; + if (!strports.equals("none")){ + port = Integer.parseInt(strports); + } + String strProto = protocolsStrings[ protocol_field.getSelectedIndex()]; + System.out.println("port : "+port+"\tproto :"+ strProto); + PowUrl info = new PowUrl(strProto,host,port,siteName,servletName); + JOptionPane.showMessageDialog(glob_fenetre, + "you will be connected to "+ info.getWebUrl(), + "logging info", + JOptionPane.INFORMATION_MESSAGE); + module = new Ivy2UdpReading(info,login,pwd); + } + else{ + module = new Ivy2UdpReading(host,login,pwd); + } + + try { + module.getWebId(); + new Thread(module).start(); + } catch (IvyConnectionExeption e) { + // echec du log + //custom title, error icon + System.out.println("erreur de connection : "+e.toString()); + JOptionPane.showMessageDialog(glob_fenetre, + "Your password or your login are not correct, retry please...\n"+ + "Be sure a valid SSL certificat exist in your $JAVA_HOME/jre/lib/security folder,\n"+ + "otherwise use InstallCert [hostname] java programm", + "logging error", + JOptionPane.ERROR_MESSAGE); + + + } + + + // clearing + for(int i = 0; i< pwd_array.length;i++){ + pwd_array[i]='0'; + } + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + } + else{ + JOptionPane.showMessageDialog(glob_fenetre, + "you are already logged and send information to server", + "Info",JOptionPane.WARNING_MESSAGE); + } + } + + } + + + class MoreAction implements ActionListener { + JFrame globalFrame; + + MoreAction(JFrame g){ + globalFrame = g; + } + public void actionPerformed(ActionEvent e){ + Runnable code = new Runnable() { + public void run() { + if(moreIsVisible){ + contenuMore.setVisible(false);moreIsVisible=false;more_btn.setText("More...");} + else { + contenuMore.setVisible(true);moreIsVisible=true;more_btn.setText("Less..."); + } + globalFrame.pack(); + + } + }; + if (SwingUtilities.isEventDispatchThread()) { + code.run(); + } else { + SwingUtilities.invokeLater(code); + } + + } + } + +} + diff --git a/sw/in_progress/pow/pow/src/pow/IvyMsg.java b/sw/in_progress/pow/pow/src/pow/IvyMsg.java new file mode 100644 index 0000000000..c10e823fc4 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/IvyMsg.java @@ -0,0 +1,39 @@ +package pow; + + +public class IvyMsg { + + private int webId; + private long num_msg; + private String timeMsg;//"d:M:y:HH:mm:ss" add 2000 to d + private String ivyMsg; + private dbOrder order; + + public IvyMsg(int wId,long num,String date,String msg,dbOrder order){ + webId = wId; + num_msg = num; + timeMsg = date; + ivyMsg = msg; + this.order = order; + } + + public IvyMsg(int wId,long num,String date,String msg){ + webId = wId; + num_msg = num; + timeMsg = date; + ivyMsg = msg; + this.order = null; + } + + public int getWebId(){return webId;} + public long getNumMsg() {return num_msg;} + public String getTimeMsg() {return timeMsg;} + public String getIvyMsg() {return ivyMsg;} + public dbOrder getOrder() {return order;} + public void setOrder(dbOrder o ) { order=o;} + + public String getSQLQUERY(){ + return ""; + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/Md5.java b/sw/in_progress/pow/pow/src/pow/Md5.java new file mode 100644 index 0000000000..b5619f4c1e --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Md5.java @@ -0,0 +1,83 @@ +package pow; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +/** + * tool class to implemente MD5 encoding + * ( found on the web ) + * + */ +public class Md5 +{ + public static String encode(String password) + { + byte[] uniqueKey = password.getBytes(); + byte[] hash = null; + + try + { + hash = MessageDigest.getInstance("MD5").digest(uniqueKey); + } + catch (NoSuchAlgorithmException e) + { + throw new Error("No MD5 support in this VM."); + } + + StringBuilder hashString = new StringBuilder(); + for (int i = 0; i < hash.length; i++) + { + String hex = Integer.toHexString(hash[i]); + if (hex.length() == 1) + { + hashString.append('0'); + hashString.append(hex.charAt(hex.length() - 1)); + } + else + hashString.append(hex.substring(hex.length() - 2)); + } + return hashString.toString(); + } +/* + public static String hash(String plaintext) { + MessageDigest md = null; + + try { + md = MessageDigest.getInstance("SHA-1"); // SHA-1 generator instance + } catch(NoSuchAlgorithmException e) { + return ""; + } + + try { + //8859_1 ou UTF-8 + md.update(plaintext.getBytes("UTF-8")); // Message summary generation + } catch(UnsupportedEncodingException e) { + return ""; + } + + byte raw[] = md.digest(); // Message summary reception + + try{ + String hash = new String(org.apache.commons.codec.binary.Base64.encodeBase64(raw),"UTF-8"); + //String hash = new String(raw); + return hash; + } + catch (UnsupportedEncodingException use){ + return ""; + } + } + + */ + public static void main(String[] args) + { + if (args.length != 1) + { + System.out.println("Usage: java Md5 "); + return; + } + + String toEncode = args[0]; + + System.out.println("Original string ... " + toEncode); + System.out.println("String MD5 ........ " + encode(toEncode)); + } +} \ No newline at end of file diff --git a/sw/in_progress/pow/pow/src/pow/MsgFilter.java b/sw/in_progress/pow/pow/src/pow/MsgFilter.java new file mode 100644 index 0000000000..55109da2a4 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/MsgFilter.java @@ -0,0 +1,33 @@ +package pow; +import java.util.HashSet; + +/** + * classe permettant de filtrer les messages waypoints inutile + * @author genin + * + */ +public class MsgFilter { + + + private HashSet msgset; + + public MsgFilter(){ + msgset = new HashSet(); + } + /** + * informe si le message est deja contenu dans le filtre + * et l'ajoute le cas echeant + * @param msg + * @return + */ + public boolean isNew(String msg){ + boolean res = msgset.add(msg); + return res; + } + /** + * vide le filtre + */ + public void resetfilter(){ + msgset.clear(); + } +} diff --git a/sw/in_progress/pow/pow/src/pow/PowUrl.java b/sw/in_progress/pow/pow/src/pow/PowUrl.java new file mode 100644 index 0000000000..4044ecafd9 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/PowUrl.java @@ -0,0 +1,24 @@ +package pow; + +public class PowUrl { + private String protocole="http"; + private int port =-1; + private String serverName; + private String webAppName; + private String servletLoginName; + + public PowUrl(String protocol,String server,int port,String webapp,String servletName){ + if (protocol.equals("https")) this.protocole="https"; + this.port = port; + this.serverName =server; + this.webAppName = webapp; + this.servletLoginName = servletName; + } + + public String getServerName() {return serverName;} + public String getWebUrl() { + if (port==-1) return ""+protocole+"://"+serverName+"/"+webAppName+"/"+servletLoginName; + else + return ""+protocole+"://"+serverName+":"+port+"/"+webAppName+"/"+servletLoginName; + } +} diff --git a/sw/in_progress/pow/pow/src/pow/Rights.java b/sw/in_progress/pow/pow/src/pow/Rights.java new file mode 100644 index 0000000000..1e418b45ab --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Rights.java @@ -0,0 +1,12 @@ +package pow; +/** + * describe the different rights a web user can have + * @author genin + * + */ +public enum Rights { + VISITOR, // can only see the drones + ADMIN, // can pilot all the drones and manage user's account and create others administrators + USER, + IVY // specify an ivy user which send data to the server via UDP +} diff --git a/sw/in_progress/pow/pow/src/pow/SGBDfeeder.java b/sw/in_progress/pow/pow/src/pow/SGBDfeeder.java new file mode 100644 index 0000000000..8701c0d600 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/SGBDfeeder.java @@ -0,0 +1,81 @@ +package pow; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; + +//CREATE TABLE connexion(id INTEGER NOT NULL AUTO_INCREMENT,webId INTEGER,login VARCHAR(50),start DATE NOT NULL,end DATE DEFAULT NULL,PRIMARY KEY(id)); + + +public class SGBDfeeder implements Runnable { + + private String dbName; + private String dbLogin; + private String dbPwd; + private Queue fifo; + + public SGBDfeeder(String dbname,String dbuser,String dbpwd){ + fifo = new ConcurrentLinkedQueue(); + //fifo = new LinkedBlockingQueue(); + dbName=dbname; + dbLogin=dbuser; + dbPwd=dbpwd; + } + + public Queue getQueueFIFO(){ + return fifo; + } + + + public void run() { + Connection connection = null; + Statement stmt = null; + ResultSet rs = null; + + String url = "jdbc:mysql://localhost/"+dbName; + //String login = "root"; + //String password = "pwdroot"; + // connect to SGBD + try { + //Connection to the Data Base + Class.forName("com.mysql.jdbc.Driver").newInstance(); + connection = DriverManager.getConnection(url,dbLogin,dbPwd); + // receiving msg + while(true){ + // get msg + + // store it in db + try{ + //connection = DriverManager.getConnection(url,login,password); + stmt = connection.createStatement(); + int res = stmt.executeUpdate("CREATE DATABASE pow_sql"); + res = stmt.executeUpdate("CREATE TABLE connexion (" + + "web_id INTEGER," + + "login VARCHAR(50), " + + "start DATE NOT NULL, " + + "end DATE DEFAULT NULL)"); + } catch (SQLException ex) { + System.out.println("SQLException: " + ex.getMessage()); + System.out.println("SQLState: " + ex.getSQLState()); + System.out.println("VendorError: " + ex.getErrorCode()); + } + } + } + catch (SQLException ex) {System.out.println("unable to connect to db");} + catch (ClassNotFoundException ex) {} + catch (IllegalAccessException ex){} + catch ( InstantiationException ex){} + finally + { + if(connection!=null){try{connection.close();}catch(Exception e){e.printStackTrace();}} + //etc. + } + } + + +} diff --git a/sw/in_progress/pow/pow/src/pow/SSLUtilities.java b/sw/in_progress/pow/pow/src/pow/SSLUtilities.java new file mode 100644 index 0000000000..2d661f232b --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/SSLUtilities.java @@ -0,0 +1,322 @@ +package pow; + +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * This class provide various static methods that relax X509 certificate and + * hostname verification while using the SSL over the HTTP protocol. + * call: + * SSLUtilities.trustAllHostnames() to turn off the default hostname verification on HTTPS connection; + * SSLUtilities.trustAllHttpsCertificates() to turn off the default certificate validation on HTTPS connection. + * + * @see http://en.wikibooks.org/wiki/WebObjects/Web_Services/How_to_Trust_Any_SSL_Certificate + * @author Francis Labrie + */ +public final class SSLUtilities { + + /** + * Hostname verifier for the Sun's deprecated API. + * + * @deprecated see {@link #_hostnameVerifier}. + */ + private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier; + /** + * Thrust managers for the Sun's deprecated API. + * + * @deprecated see {@link #_trustManagers}. + */ + private static com.sun.net.ssl.TrustManager[] __trustManagers; + /** + * Hostname verifier. + */ + private static HostnameVerifier _hostnameVerifier; + /** + * Thrust managers. + */ + private static TrustManager[] _trustManagers; + + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. This method uses the old deprecated API from the + * com.sun.ssl package. + * + * @deprecated see {@link #_trustAllHostnames()}. + */ + private static void __trustAllHostnames() { + // Create a trust manager that does not validate certificate chains + if(__hostnameVerifier == null) { + __hostnameVerifier = new _FakeHostnameVerifier(); + } // if + // Install the all-trusting host name verifier + com.sun.net.ssl.HttpsURLConnection. + setDefaultHostnameVerifier(__hostnameVerifier); + } // __trustAllHttpsCertificates + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. This method uses the + * old deprecated API from the com.sun.ssl package. + * + * @deprecated see {@link #_trustAllHttpsCertificates()}. + */ + private static void __trustAllHttpsCertificates() { + com.sun.net.ssl.SSLContext context; + + // Create a trust manager that does not validate certificate chains + if(__trustManagers == null) { + __trustManagers = new com.sun.net.ssl.TrustManager[] + {new _FakeX509TrustManager()}; + } // if + // Install the all-trusting trust manager + try { + context = com.sun.net.ssl.SSLContext.getInstance("SSL"); + context.init(null, __trustManagers, new SecureRandom()); + } catch(GeneralSecurityException gse) { + throw new IllegalStateException(gse.getMessage()); + } // catch + com.sun.net.ssl.HttpsURLConnection. + setDefaultSSLSocketFactory(context.getSocketFactory()); + } // __trustAllHttpsCertificates + + /** + * Return true if the protocol handler property java. + * protocol.handler.pkgs is set to the Sun's com.sun.net.ssl. + * internal.www.protocol deprecated one, false + * otherwise. + * + * @return true if the protocol handler + * property is set to the Sun's deprecated one, false + * otherwise. + */ + private static boolean isDeprecatedSSLProtocol() { + return("com.sun.net.ssl.internal.www.protocol".equals(System. + getProperty("java.protocol.handler.pkgs"))); + } // isDeprecatedSSLProtocol + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. + */ + private static void _trustAllHostnames() { + // Create a trust manager that does not validate certificate chains + if(_hostnameVerifier == null) { + _hostnameVerifier = new FakeHostnameVerifier(); + } // if + // Install the all-trusting host name verifier: + HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier); + } // _trustAllHttpsCertificates + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. + */ + private static void _trustAllHttpsCertificates() { + SSLContext context; + + // Create a trust manager that does not validate certificate chains + if(_trustManagers == null) { + _trustManagers = new TrustManager[] {new FakeX509TrustManager()}; + } // if + // Install the all-trusting trust manager: + try { + context = SSLContext.getInstance("SSL"); + context.init(null, _trustManagers, new SecureRandom()); + } catch(GeneralSecurityException gse) { + throw new IllegalStateException(gse.getMessage()); + } // catch + HttpsURLConnection.setDefaultSSLSocketFactory(context. + getSocketFactory()); + } // _trustAllHttpsCertificates + + /** + * Set the default Hostname Verifier to an instance of a fake class that + * trust all hostnames. + */ + public static void trustAllHostnames() { + // Is the deprecated protocol setted? + if(isDeprecatedSSLProtocol()) { + __trustAllHostnames(); + } else { + _trustAllHostnames(); + } // else + } // trustAllHostnames + + /** + * Set the default X509 Trust Manager to an instance of a fake class that + * trust all certificates, even the self-signed ones. + */ + public static void trustAllHttpsCertificates() { + // Is the deprecated protocol setted? + if(isDeprecatedSSLProtocol()) { + __trustAllHttpsCertificates(); + } else { + _trustAllHttpsCertificates(); + } // else + } // trustAllHttpsCertificates + + /** + * This class implements a fake hostname verificator, trusting any host + * name. This class uses the old deprecated API from the com.sun. + * ssl package. + * + * @author Francis Labrie + * + * @deprecated see {@link SSLUtilities.FakeHostnameVerifier}. + */ + public static class _FakeHostnameVerifier + implements com.sun.net.ssl.HostnameVerifier { + + /** + * Always return true, indicating that the host name is an + * acceptable match with the server's authentication scheme. + * + * @param hostname the host name. + * @param session the SSL session used on the connection to + * host. + * @return the true boolean value + * indicating the host name is trusted. + */ + public boolean verify(String hostname, String session) { + return(true); + } // verify + } // _FakeHostnameVerifier + + + /** + * This class allow any X509 certificates to be used to authenticate the + * remote side of a secure socket, including self-signed certificates. This + * class uses the old deprecated API from the com.sun.ssl + * package. + * + * @author Francis Labrie + * + * @deprecated see {@link SSLUtilities.FakeX509TrustManager}. + */ + public static class _FakeX509TrustManager + implements com.sun.net.ssl.X509TrustManager { + + /** + * Empty array of certificate authority certificates. + */ + private static final X509Certificate[] _AcceptedIssuers = + new X509Certificate[] {}; + + + /** + * Always return true, trusting for client SSL + * chain peer certificate chain. + * + * @param chain the peer certificate chain. + * @return the true boolean value + * indicating the chain is trusted. + */ + public boolean isClientTrusted(X509Certificate[] chain) { + return(true); + } // checkClientTrusted + + /** + * Always return true, trusting for server SSL + * chain peer certificate chain. + * + * @param chain the peer certificate chain. + * @return the true boolean value + * indicating the chain is trusted. + */ + public boolean isServerTrusted(X509Certificate[] chain) { + return(true); + } // checkServerTrusted + + /** + * Return an empty array of certificate authority certificates which + * are trusted for authenticating peers. + * + * @return a empty array of issuer certificates. + */ + public X509Certificate[] getAcceptedIssuers() { + return(_AcceptedIssuers); + } // getAcceptedIssuers + } // _FakeX509TrustManager + + + /** + * This class implements a fake hostname verificator, trusting any host + * name. + * + * @author Francis Labrie + */ + public static class FakeHostnameVerifier implements HostnameVerifier { + + /** + * Always return true, indicating that the host name is + * an acceptable match with the server's authentication scheme. + * + * @param hostname the host name. + * @param session the SSL session used on the connection to + * host. + * @return the true boolean value + * indicating the host name is trusted. + */ + public boolean verify(String hostname, + javax.net.ssl.SSLSession session) { + return(true); + } // verify + } // FakeHostnameVerifier + + + /** + * This class allow any X509 certificates to be used to authenticate the + * remote side of a secure socket, including self-signed certificates. + * + * @author Francis Labrie + */ + public static class FakeX509TrustManager implements X509TrustManager { + + /** + * Empty array of certificate authority certificates. + */ + private static final X509Certificate[] _AcceptedIssuers = + new X509Certificate[] {}; + + + /** + * Always trust for client SSL chain peer certificate + * chain with any authType authentication types. + * + * @param chain the peer certificate chain. + * @param authType the authentication type based on the client + * certificate. + */ + public void checkClientTrusted(X509Certificate[] chain, + String authType) { + } // checkClientTrusted + + /** + * Always trust for server SSL chain peer certificate + * chain with any authType exchange algorithm types. + * + * @param chain the peer certificate chain. + * @param authType the key exchange algorithm used. + */ + public void checkServerTrusted(X509Certificate[] chain, + String authType) { + } // checkServerTrusted + + /** + * Return an empty array of certificate authority certificates which + * are trusted for authenticating peers. + * + * @return a empty array of issuer certificates. + */ + public X509Certificate[] getAcceptedIssuers() { + return(_AcceptedIssuers); + } // getAcceptedIssuers + } // FakeX509TrustManager +} // SSLUtilities diff --git a/sw/in_progress/pow/pow/src/pow/Serveur.java b/sw/in_progress/pow/pow/src/pow/Serveur.java new file mode 100644 index 0000000000..30455022d6 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/Serveur.java @@ -0,0 +1,693 @@ +package pow; + +import nl.justobjects.pushlet.core.Dispatcher; +import nl.justobjects.pushlet.core.Event; +import nl.justobjects.pushlet.core.EventSource; +import java.io.*; +import java.net.*; +/* +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +*/ +import java.util.*; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.servlet.ServletContext; +//import javax.servlet.*; +//import javax.servlet.http.*; +import pow.Conf; + +import org.apache.commons.codec.binary.Hex; +import org.jdom.*; +import org.jdom.input.*; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; +import org.jdom.filter.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Iterator; + +import java.util.Date; + +/** + * Class which receive a datagramm from ivy bus via udp + * transforms it into a pushlet event and send it to the pushlet server + * in order that it will be sended to web clients + * @author genin + * + */ +public class Serveur { +static public class IvyEventSource implements EventSource , Runnable { + + private ServletContext srvCtxt; + private String default_folder = "blabla"; + + Thread thread = null; + volatile boolean active = false; + private int restarts = 1; + /* *********************** */ + private static log myLog; + private static Conf myConf; + /* *********************** */ + private DatagramSocket socket; + private int newBusTest; + private ArrayList busesIvy; // Tableau identifiant les busIvy et les drones + private ArrayList deadBusesIvy; // Tableau identifiant les busIvy deconnectes + private String[] myDataSplited; // Tableau contenant toutes les donnees envoyees + /* *********************** */ + private static long time2resetFilters = 100000; // on nettoie les filtres ms !!!!! + /* *********************** */ + private MsgFilter waypointMsgFilter; + /* to retreive aes cipher for a specific ivy bus*/ + private HashMap tableIvySession; + /* ********* */ + private IvyMsg currentIvyMsg=null; + /* ********* */ + + public IvyEventSource() { + System.out.println(" Thread de recuperation des données IVY"); + waypointMsgFilter = new MsgFilter(); + } + /* *********************************** */ + /* EventSource specific functions */ + /* *********************************** */ + /** + * Activate the event source. + */ + synchronized public void activate() { + System.out.println("activating the event source...."); + // Stop a possibly running thread + stopThread(); + // Start new thread and + thread = new Thread(this, "DATA FROM IVY " + (restarts++)); + active = true; + thread.start(); + System.out.println("event source activated !!!"); + } + + /** + * Deactivate the event source. + */ + synchronized public void passivate() { + // inform the other servlet + this.srvCtxt.removeAttribute("list_bus_ivy"); + // + active = false; + stopThread(); + } + + /** + * Deactivate the event source. + */ + synchronized public void stop() { + } + + private void stopThread() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + /* + * load configuration from a specific configuration file on the server + * and initiates a log file to. + */ + private void loadingConfiguration() throws Exception + { + myConf = new Conf(default_folder,"pow.conf"); + myLog.write("Loading Configuration !"); + myLog.write(""); + myLog.write("Configuration Details :"); + myLog.write("Port : " + myConf.port()); + myLog.write("Size of Datagrams : " + myConf.taille()); + myLog.write("DataBase used : " + myConf.dataBaseName()); + myLog.write(""); + } + + /** + * This procedure convert the byte array into a String and returns an array containing all the + * the datas separately. + * extract also the information concerning the sender to send them to data base + * @param Data The raw of byte containing udp msg which will be processed + * @return An array containing all the datas separately + */ + public static String[] dataProcessing(byte[] data) //throws Exception + { + // This array contain all the datas transmitted + String[] myDataSplited; + // Number of datas transmitted + int nbr_datas; + // Data separator + String sep_datas = " "; + // The datagram is converted into String + String myData = new String(data); + + myDataSplited = myData.split(sep_datas,4); // 4 = number of substring + int webid = Integer.parseInt(myDataSplited[0]); + long num_msg = Long.parseLong(myDataSplited[1]); + String timeMsg = myDataSplited[2]; + String ivymsg = myDataSplited[3]; + myDataSplited = myDataSplited[3].split(sep_datas); + //System.out.println("##############################"); + //for(int i = 0; i(); + // Tableau identifiant les busIvy deconnectes + deadBusesIvy = new ArrayList (); + + try {loadingConfiguration();} catch (Exception e) { + System.out.println("erreur loading configuration"); + e.printStackTrace();} + + // inform the other servlet + this.srvCtxt.setAttribute("list_bus_ivy", busesIvy); + // + + //The server is launched and listen on port number 8535 + try{ + socket = new DatagramSocket(myConf.port()); + socket.setSoTimeout(myConf.timeout()); + // System.out.println(" ecriture log"); + myLog.write("Server launched !"); + // System.out.println("Server launched !"); + + //The module wait the reception of datagrams + chrono_start = System.currentTimeMillis(); + while(true) + { + // + // decryptage AES + // si je recois un paquet via udp c'est qu'il y a eu login d'un client ivy + // et donc je peux recupere la table des sessions + if (firsttime){ + tableIvySession = (HashMap) this.srvCtxt.getAttribute("ivySessionTable"); + } + if (tableIvySession!=null){ + firsttime =false; + }// fin if tableSession!=null + newBusTest = 0; + + byte buffer[] = new byte[myConf.taille()]; + DatagramPacket dataReceived = new DatagramPacket(buffer,buffer.length); + try + { + socket.receive(dataReceived); + if(dataReceived != null){ + if (firsttime){ + tableIvySession = (HashMap) this.srvCtxt.getAttribute("ivySessionTable"); + } + if (tableIvySession!=null){ + firsttime =false; + System.out.print("d"); + //The module checks if there is a new Bus Ivy incoming + SessionIvy clientIvy = tableIvySession.get(dataReceived.getAddress()); + if (clientIvy!=null){ + BusIvy_ current_bus = clientIvy.getBusIvy(); + if (current_bus==null){ + current_bus = new BusIvy_(); + current_bus.setAddress(dataReceived.getAddress()); + current_bus.updateTime(); + clientIvy.setBusIvy(current_bus); + myLog.write("New Ivy Connection detected : " + dataReceived.getAddress()); + } + else + { + current_bus.updateTime(); + } + // check dead buses (after 10sec of inactivity) + // TODO could be perform less often.... + Iterator> itr = tableIvySession.entrySet().iterator(); + BusIvy_ checked_bus; + while(itr.hasNext()){ + checked_bus = itr.next().getValue().getBusIvy(); + if(!(checked_bus.isAlive())){ + myLog.write("Ivy Connection deconnected : " + checked_bus.getAddress()); + for(Integer deadDrone : checked_bus.getDrones()) + { + deconnectDrone(deadDrone); + } + } + } + // + /* + if(busesIvy.isEmpty()) + { + BusIvy_ oNewBus = new BusIvy_(); + oNewBus.setAddress(dataReceived.getAddress()); + oNewBus.updateTime(); + busesIvy.add(oNewBus); + myLog.write("New Ivy Connection detected : " + dataReceived.getAddress()); + } + else + { + for(BusIvy_ myBus : busesIvy) + { + if(myBus.getAddress().equals(dataReceived.getAddress())) + { + newBusTest = 1; + myBus.updateTime(); // to avoid being not alive and be removed + } + + if(!(myBus.isAlive())) + { + myLog.write("Ivy Connection deconnected : " + myBus.getAddress()); + for(Integer deadDrone : myBus.getDrones()) + { + deconnectDrone(deadDrone); + } + deadBusesIvy.add(myBus); + } + + } + if(!(deadBusesIvy.isEmpty())) + { + for(BusIvy_ deadBus : deadBusesIvy) + { + busesIvy.remove(deadBus); + } + deadBusesIvy.removeAll(deadBusesIvy); + } + if(newBusTest == 0) + { + BusIvy_ newBus = new BusIvy_(); + newBus.setAddress(dataReceived.getAddress()); + newBus.updateTime(); + busesIvy.add(newBus); + myLog.write("New Ivy Connection detected : " + dataReceived.getAddress()); + } + } + */ + AES cipher = clientIvy.getCipher(); + try{ + complete_data = dataReceived.getData(); // on recupere toute la trame utile + true_length_of_msg = dataReceived.getLength(); + data_with_no_padding = new byte[true_length_of_msg]; // on recupere que les infos utiles + for(i=0;i< true_length_of_msg;i++){ + data_with_no_padding[i]=complete_data[i]; + } + try{ + byte[] decrypted_data = cipher.decrypt(data_with_no_padding); + + //The datagram is processed + myDataSplited = dataProcessing(decrypted_data); + // switch .... + if((myDataSplited[0].equals("New_Plane")) + ||(myDataSplited[0].equals("Plane_Die")) + ||(myDataSplited[0].equals("Plane_Resurect")) + ||(myDataSplited[0].equals("DL_SETTING_ACK")) + ||(myDataSplited[0].equals("WAYPOINT_MOVED")) + ||(myDataSplited[0].equals("NAV_STATUS")) + ||(myDataSplited[0].equals("SETTINGS_VALUES"))) + { + myLog.write("Order Received From : " + dataReceived.getAddress() + " ---> " + new String(decrypted_data)); + + sendOrderToServer(myDataSplited); + if(!(current_bus.isOwnBy(Integer.parseInt(myDataSplited[1])))) + { + current_bus.addDrones(Integer.parseInt(myDataSplited[1])); + } + /* + for(BusIvy_ myBus : busesIvy) + { + if( myBus.getAddress().equals(dataReceived.getAddress())) + { + if(!(myBus.isOwnBy(Integer.parseInt(myDataSplited[1])))) + { + myBus.addDrones(Integer.parseInt(myDataSplited[1])); + } + + } + }*/ + } + else + { + sendDataToServer(myDataSplited); + if(!(current_bus.isOwnBy(Integer.parseInt(myDataSplited[0])))) + { + current_bus.addDrones(Integer.parseInt(myDataSplited[0])); + } + /* + for(BusIvy_ myBus : busesIvy) + { + if( myBus.getAddress().equals(dataReceived.getAddress())) + { + if(!(myBus.isOwnBy(Integer.parseInt(myDataSplited[0])))) + { + myBus.addDrones(Integer.parseInt(myDataSplited[0])); + } + } + }*/ + } + + + System.out.print("."); + } + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("msg no padding := "+(new String(Hex.encodeHex(data_with_no_padding)))); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("msg no padding := "+(new String(Hex.encodeHex(data_with_no_padding)))); + } + } + catch(IOException ex){ + System.out.print("pbm decrypting msg"); + System.out.print(ex.toString()); + } + }// fin if ivyclient != null + else + { + System.out.print("no ivy client stored for this datagramm from "+dataReceived.getAddress()); + } + } // fin if tablesession != null + else + { + // on a recu un diagramme mais il n'y a pas de session recorded donc on + // doit envoyer un message au sender comme quoi il doit se relogger + // TODO + System.out.println("no session recorder "+dataReceived.getAddress()+ "should relog to server"); + } + }// fin if datareceived!=null + }// fin du try socket received + catch(SocketTimeoutException ex) + { + if(!(busesIvy.isEmpty())) + { + for(BusIvy_ myBus : busesIvy) + { + myLog.write("Ivy Connection deconnected : " + myBus.getAddress()); + for(Integer deadDrone : myBus.getDrones()) + { + deconnectDrone(deadDrone); + } + } + + busesIvy.removeAll(busesIvy); + myLog.write("No Bus Ivy connected..."); + } + dataReceived = null; + } + catch(IOException ex){ + System.out.println("exception socket receive serveur.java"); + ex.printStackTrace(); + } + + }// fin while true + } catch (SocketException soe){ + System.out.print("Socket Exception !"); + soe.printStackTrace(); + } + //} + //catch(Exception e){ + // System.out.println("Non handled exception ... plantage...."); + // System.out.println("***************************************"); + // System.out.println(""+e.toString()); + // System.out.println("***************************************"); + //} + + } + + /** + * send a iskill event when a drone has disappeared from an ivy bus + * @param droneId + * @throws Exception + */ + public void deconnectDrone(int droneId) + { + Event event = Event.createDataEvent("/data/drone/iskill"); + event.setField("aircraftId",droneId); + event.setField("iskill", 1 + "" ); // 1 ==true + Dispatcher.getInstance().multicast(event); + //TODO effacer les fichiers de conf associés ???? + } + + + /** + * send a datagramm containing all useful information on a drone + * @param myDataSplited + * @throws Exception + */ + public void sendDataToServer(String myDataSplited[])// throws Exception + { + int i; + int nbr_datas = myDataSplited.length; + String[] myDataName = new String[nbr_datas]; + // try{ + // id of the drone + myDataName[0] = "id"; + // name of the drone + myDataName[1] = "dbName"; + // latitude + myDataName[2] = "dbLatitude"; + // longitude + myDataName[3] = "dbLongitude"; + // speed + myDataName[4] = "dbSpeed";// + // bearing + myDataName[5] = "dbCourse"; + // amsl + myDataName[6] = "dbAmsl";// + // vertical speed + myDataName[7] = "dbVert_speed";// + // agl + myDataName[8] = "dbAgl";// + // battery load + myDataName[9] = "dbStat_battery";// + // gps_status + myDataName[10] = "dbStat_gps";// + // Engine status + myDataName[11] = "dbEngine_status";// + // active block + myDataName[12] = "dbActive_block";// + // id of the setting + myDataName[13] = "dbId_Setting";// + // value of the setting + myDataName[14] = "dbSetting_Value";// + // color of the drone , rajout thomas + myDataName[15] = "drone_color";// + + Event event = Event.createDataEvent("/data/drones_maj"); + event.setField("aircraftId",myDataSplited[0]); + for(i=1;i listbusesIvy) throws Exception + { + byte buffer[] = new byte[myConf.taille()]; + for(BusIvy_ myBus : listbusesIvy) + { + if(myBus.isOwnBy(aircraftWebId)) + { + InetAddress address = myBus.getAddress(); + buffer = order.getBytes(); + DatagramPacket DataEmitted = new DatagramPacket(buffer, buffer.length, address, myConf.port()); + socket.send(DataEmitted); + myLog.write("Order Emitted To : " + DataEmitted.getAddress() + " ---> " + new String(DataEmitted.getData())); + System.out.print("*"); + } + } + } + + + /** + * This procedure write the orders given by the bus Ivy in the DataBase. + * @param myDataSplited The array containing one order + */ + + private void sendOrderToServer(String myDataSplited[]) //throws Exception + { + //try{ + if(myDataSplited[0].equals("WAYPOINT_MOVED")) + { + Event event = Event.createDataEvent("/data/order/waypoint_moved"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + event.setField("waypointId", myDataSplited[2] ); + event.setField("latitude", myDataSplited[3] ); + event.setField("longitude", myDataSplited[4] ); + event.setField("altitude", myDataSplited[5] ); + updateXML_FPL_file(myDataSplited[1],myDataSplited[2],myDataSplited[3],myDataSplited[4],myDataSplited[5]); + Dispatcher.getInstance().multicast(event); + } + else if(myDataSplited[0].equals("NAV_STATUS")) + { + //System.out.println(""+myDataSplited.toString()); + Event event = Event.createDataEvent("/data/order/block_changed"); + event.setField("order",myDataSplited[0]);//System.out.println("1"); + event.setField("aircraftId",myDataSplited[1]);//System.out.println("2"); + event.setField("currentBlockId", myDataSplited[2] );//System.out.println("3"); + Dispatcher.getInstance().multicast(event);//System.out.println("4"); + } + else if(myDataSplited[0].equals("DL_SETTING_ACK")) + { + Event event = Event.createDataEvent("/data/order/change_setting"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + event.setField("settingId", myDataSplited[2]); + event.setField("settingValue", myDataSplited[3]); + Dispatcher.getInstance().multicast(event); + } + else if(myDataSplited[0].equals("Plane_Die")) + { + Event event = Event.createDataEvent("/data/order/plane_die"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + Dispatcher.getInstance().multicast(event); + } + else if(myDataSplited[0].equals("Plane_Resurect")) + { + //TODO TRAITER CE CAS ???? + Event event = Event.createDataEvent("/data/order/plane_resurect"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + Dispatcher.getInstance().multicast(event); + } + else if(myDataSplited[0].equals("New_Plane")) + { + Event event = Event.createDataEvent("/data/order/new_plane"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + event.setField("aircraftName",myDataSplited[2]); + Dispatcher.getInstance().multicast(event); + } + else if(myDataSplited[0].equals("SETTINGS_VALUES")) + { + Event event = Event.createDataEvent("/data/order/settings"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + event.setField("csv",myDataSplited[2]); + Dispatcher.getInstance().multicast(event); + } + else + { + Event event = Event.createDataEvent("/data/order/other"); + event.setField("order",myDataSplited[0]); + event.setField("aircraftId",myDataSplited[1]); + Dispatcher.getInstance().multicast(event); + } + /*} + catch(Exception ex){ + System.out.println("exception dans sendOrderToServer : "); + System.out.println(""+ex.toString()); + throw new Exception(ex); + }*/ + } + + /** + * method qui renseigne la source sur la servlet qui l'a appelé + * modification de la librairie pushlet + * Pushlet.java + * EventSource.java + * EventSourceManager.java + */ + + public void setServletContext(ServletContext srvCtxt) { + this.srvCtxt = srvCtxt; + default_folder = srvCtxt.getRealPath(""); + } + + private void updateXML_FPL_file(String acId,String wpId,String lat,String lon,String alt){ + // change XML file on server + // http://cynober.developpez.com/tutoriel/java/xml/jdom/ + String default_folder = this.srvCtxt.getRealPath(""); + try + { + String filepath = default_folder+"/upload/"+acId+"/flight_plan.xml"; + //System.out.println("attempt to modify xml fpl for drone : " +acId); + Document document; + SAXBuilder sxb = new SAXBuilder(); + Element racine; + document = sxb.build(new File(filepath));// charge le fichier + //On initialise un nouvel élément racine avec l'élément racine du document. + racine = document.getRootElement(); + List list_wpt = racine.getChild("flight_plan").getChild("waypoints").getChildren("waypoint"); + Iterator i = list_wpt.iterator(); + boolean doIt = true; + int cpt_wpt=0; + while(i.hasNext()&&doIt) //parcours des waypoints + { + Element courant = (Element)i.next(); + if (cpt_wpt==(Integer.parseInt(wpId)-1)){ //TODO verifier que ca coincide bien !!! cf waypoint fictif ivy + String name = courant.getAttributeValue("name"); + // if(name.equals(wpt_name)) { + System.out.println("wpt changed : "+ name + " for drone "+ acId +" id="+cpt_wpt+" with\tlat="+lat + "\tlon="+lon); + doIt= false; + courant.removeAttribute("x"); // on enleve les coordonnées relative en x et y + courant.removeAttribute("y"); // si elles sont présentes + courant.setAttribute("lat", lat); + courant.setAttribute("long", lon); + courant.setAttribute("alt", alt); + } + cpt_wpt++; + } + // enregistre le nouveau fichier + XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat()); + sortie.output(document, new FileOutputStream(filepath)); + //System.out.println("xml filed updated on server for drone : " +acId); + } + catch(Exception e){System.out.println("error : unable to load xml file");} + + } +} +} diff --git a/sw/in_progress/pow/pow/src/pow/SessionIvy.java b/sw/in_progress/pow/pow/src/pow/SessionIvy.java new file mode 100644 index 0000000000..882906c1a7 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/SessionIvy.java @@ -0,0 +1,39 @@ +package pow; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class SessionIvy { + + private String login; + private int webId; + private AES cipherAES; + private InetAddress IvyHostName; + private BusIvy_ busIvy; + + public SessionIvy(String l,int w, AES c,InetAddress IvyAddr) throws UnknownHostException{ + this.login = l; + this.webId = w; + this.cipherAES = c; + this.IvyHostName = IvyAddr; + busIvy = null; + } + + public InetAddress getIvyInetAddress(){ + return this.IvyHostName; + } + + public void setIvyInetAddress(InetAddress addr){ + this.IvyHostName=addr; + } + + public AES getCipher() {return cipherAES;} + + public BusIvy_ getBusIvy(){ + return this.busIvy; + } + + public void setBusIvy( BusIvy_ b){ + this.busIvy = b; + } +} diff --git a/sw/in_progress/pow/pow/src/pow/StrictSSLProtocolSocketFactory.java b/sw/in_progress/pow/pow/src/pow/StrictSSLProtocolSocketFactory.java new file mode 100644 index 0000000000..602a55316d --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/StrictSSLProtocolSocketFactory.java @@ -0,0 +1,339 @@ +/* + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java,v 1.5 2004/06/10 18:25:24 olegk Exp $ + * $Revision: 480424 $ + * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ + * + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * [Additional notices, if required by prior licensing conditions] + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Lesser General Public License Version 2 or later + * (the "LGPL"), in which case the provisions of the LGPL are + * applicable instead of those above. See terms of LGPL at + * . + * If you wish to allow use of your version of this file only under + * the terms of the LGPL and not to allow others to use your version + * of this file under the Apache Software License, indicate your + * decision by deleting the provisions above and replace them with + * the notice and other provisions required by the LGPL. If you do + * not delete the provisions above, a recipient may use your version + * of this file under either the Apache Software License or the LGPL. + */ + +package pow; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.UnknownHostException; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.security.cert.X509Certificate; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A SecureProtocolSocketFactory that uses JSSE to create + * SSL sockets. It will also support host name verification to help preventing + * man-in-the-middle attacks. Host name verification is turned on by + * default but one will be able to turn it off, which might be a useful feature + * during development. Host name verification will make sure the SSL sessions + * server host name matches with the the host name returned in the + * server certificates "Common Name" field of the "SubjectDN" entry. + * + * @author Sebastian Hauer + *

      + * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

      + */ +public class StrictSSLProtocolSocketFactory + implements SecureProtocolSocketFactory { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(StrictSSLProtocolSocketFactory.class); + + /** Host name verify flag. */ + private boolean verifyHostname = true; + + + /** + * Constructor for StrictSSLProtocolSocketFactory. + * @param verifyHostname The host name verification flag. If set to + * true the SSL sessions server host name will be compared + * to the host name returned in the server certificates "Common Name" + * field of the "SubjectDN" entry. If these names do not match a + * Exception is thrown to indicate this. Enabling host name verification + * will help to prevent from man-in-the-middle attacks. If set to + * false host name verification is turned off. + * + * Code sample: + * + *
      + * Protocol stricthttps = new Protocol( + * "https", new StrictSSLProtocolSocketFactory(true), 443); + * + * HttpClient client = new HttpClient(); + * client.getHostConfiguration().setHost("localhost", 443, stricthttps); + *
      + * + */ + public StrictSSLProtocolSocketFactory(boolean verifyHostname) { + super(); + this.verifyHostname = verifyHostname; + } + + /** + * Constructor for StrictSSLProtocolSocketFactory. + * Host name verification will be enabled by default. + */ + public StrictSSLProtocolSocketFactory() { + super(); + } + + /** + * Set the host name verification flag. + * + * @param verifyHostname The host name verification flag. If set to + * true the SSL sessions server host name will be compared + * to the host name returned in the server certificates "Common Name" + * field of the "SubjectDN" entry. If these names do not match a + * Exception is thrown to indicate this. Enabling host name verification + * will help to prevent from man-in-the-middle attacks. If set to + * false host name verification is turned off. + */ + public void setHostnameVerification(boolean verifyHostname) { + this.verifyHostname = verifyHostname; + } + + /** + * Gets the status of the host name verification flag. + * + * @return Host name verification flag. Either true if host + * name verification is turned on, or false if host name + * verification is turned off. + */ + public boolean getHostnameVerification() { + return verifyHostname; + } + + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket(String host, int port, + InetAddress clientHost, int clientPort) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port, + clientHost, + clientPort); + verifyHostname(sslSocket); + + return sslSocket; + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

      + * This method employs several techniques to circumvent the limitations of older JREs that + * do not support connect timeout. When running in JRE 1.4 or above reflection is used to + * call Socket#connect(SocketAddress endpoint, int timeout) method. When executing in older + * JREs a controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the timeout + * expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

      + * + * @param host the host name/IP + * @param port the port on the host + * @param clientHost the local host name/IP to bind the socket to + * @param clientPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + Socket socket = null; + + SocketFactory socketfactory = SSLSocketFactory.getDefault(); + if (timeout == 0) { + socket = socketfactory.createSocket(host, port, localAddress, localPort); + } else { + socket = socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + socket.bind(localaddr); + socket.connect(remoteaddr, timeout); + } + verifyHostname((SSLSocket)socket); + return socket; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(host, port); + verifyHostname(sslSocket); + + return sslSocket; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket(Socket socket, String host, int port, + boolean autoClose) + throws IOException, UnknownHostException { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) sf.createSocket(socket, host, + port, autoClose); + verifyHostname(sslSocket); + + return sslSocket; + } + + + /** + * Describe verifyHostname method here. + * + * @param socket a SSLSocket value + * @exception SSLPeerUnverifiedException If there are problems obtaining + * the server certificates from the SSL session, or the server host name + * does not match with the "Common Name" in the server certificates + * SubjectDN. + * @exception UnknownHostException If we are not able to resolve + * the SSL sessions returned server host name. + */ + private void verifyHostname(SSLSocket socket) + throws SSLPeerUnverifiedException, UnknownHostException { + if (! verifyHostname) + return; + + SSLSession session = socket.getSession(); + String hostname = session.getPeerHost(); + try { + InetAddress addr = InetAddress.getByName(hostname); + } catch (UnknownHostException uhe) { + throw new UnknownHostException("Could not resolve SSL sessions " + + "server hostname: " + hostname); + } + + X509Certificate[] certs = session.getPeerCertificateChain(); + if (certs == null || certs.length == 0) + throw new SSLPeerUnverifiedException("No server certificates found!"); + + //get the servers DN in its string representation + String dn = certs[0].getSubjectDN().getName(); + + //might be useful to print out all certificates we receive from the + //server, in case one has to debug a problem with the installed certs. + if (LOG.isDebugEnabled()) { + LOG.debug("Server certificate chain:"); + for (int i = 0; i < certs.length; i++) { + LOG.debug("X509Certificate[" + i + "]=" + certs[i]); + } + } + //get the common name from the first cert + String cn = getCN(dn); + if (hostname.equalsIgnoreCase(cn)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Target hostname valid: " + cn); + } + } else { + throw new SSLPeerUnverifiedException( + "HTTPS hostname invalid: expected '" + hostname + "', received '" + cn + "'"); + } + } + + + /** + * Parses a X.500 distinguished name for the value of the + * "Common Name" field. + * This is done a bit sloppy right now and should probably be done a bit + * more according to RFC 2253. + * + * @param dn a X.500 distinguished name. + * @return the value of the "Common Name" field. + */ + private String getCN(String dn) { + int i = 0; + i = dn.indexOf("CN="); + if (i == -1) { + return null; + } + //get the remaining DN without CN= + dn = dn.substring(i + 3); + // System.out.println("dn=" + dn); + char[] dncs = dn.toCharArray(); + for (i = 0; i < dncs.length; i++) { + if (dncs[i] == ',' && i > 0 && dncs[i - 1] != '\\') { + break; + } + } + return dn.substring(0, i); + } + + public boolean equals(Object obj) { + if ((obj != null) && obj.getClass().equals(StrictSSLProtocolSocketFactory.class)) { + return ((StrictSSLProtocolSocketFactory) obj).getHostnameVerification() + == this.verifyHostname; + } else { + return false; + } + } + + public int hashCode() { + return StrictSSLProtocolSocketFactory.class.hashCode(); + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/User.java b/sw/in_progress/pow/pow/src/pow/User.java new file mode 100644 index 0000000000..8ab7e30b1f --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/User.java @@ -0,0 +1,76 @@ +package pow; +import java.util.HashSet; +import java.util.Iterator; + + +public class User implements java.io.Serializable { + private String login = ""; + private String password = ""; + private HashSet dronesNamePermitted; + private Rights right; + + public User(String log, String pwd,Rights rght) { + this.login = log; + this.password = Md5.encode(pwd); + this.right = rght; + this.dronesNamePermitted = new HashSet(); + } + + public Iterator getSetItr(){ + return dronesNamePermitted.iterator(); + } + + public void clearListDrone(){ + dronesNamePermitted.clear(); + } + + public String getListDrone(){ + Iterator itr = dronesNamePermitted.iterator(); + String res = ""; + while(itr.hasNext()){ + res = res + itr.next() + ";"; + } + return res; + } + + public void addDrone(String d){ + dronesNamePermitted.add(d); + } + + public boolean canControl(String droneName) + { + if ((right == Rights.ADMIN)|| ((right==Rights.USER)&&dronesNamePermitted.contains(droneName))) + { return true; } + else + { return false; } + } + + public Rights getRights(){ + return this.right; + } + + public void setRights(Rights r){ + this.right=r; + } + + public String getLogin() { + return login; + } + + public void setNom(String log) { + this.login = log; + } + + public String getPassword() { + return password; + } + + public void setPwd(String pwd) { + this.password = Md5.encode(pwd); + } + + public boolean IsPwdTrue(String pwd) { + return this.password.equals(Md5.encode(pwd)); + } +} + diff --git a/sw/in_progress/pow/pow/src/pow/UserTab.java b/sw/in_progress/pow/pow/src/pow/UserTab.java new file mode 100644 index 0000000000..8468b955b3 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/UserTab.java @@ -0,0 +1,122 @@ +package pow; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.io.*; + +public class UserTab implements java.io.Serializable { + + private HashMap tabUser; + /** + * create a empty list of users + */ + public UserTab(){ + tabUser = new HashMap(); + } + /** + * insert a user in the list + * @param u + * @throws AlreadyRegisteredUserException + */ + public void insert(User u) throws AlreadyRegisteredUserException { + String log = u.getLogin(); + if (!tabUser.containsKey(log)) tabUser.put(u.getLogin(),u); + else { throw new AlreadyRegisteredUserException(u) ;} + } + /** + * remove the user with the spefied login + * @param log + */ + public void remove(String log){ + tabUser.remove(log) ; + } + /** + * return the user corresponding to the given login + * @param log + * @return + */ + public User seek(String log){ + return tabUser.get(log); + } + /** + * check if an user with this logging exists yet + * @param log + * @return + */ + public boolean isInside(String log){ + return tabUser.containsKey(log); + } + + /** + * Check if the login is correct + * @param log + * @param pwd + * @return + */ + public boolean checkUser(String log,String pwd){ + boolean res = false; + User usr = tabUser.get(log); + if (usr!=null){ + res=usr.IsPwdTrue(pwd); + } + return res; + } + /** + * return the list of all drone which may be controled by the user + * @param log + * @return + */ + public Iterator getItrUsr(String log){ + Iterator res = null; + User usr = tabUser.get(log); + if (usr!=null){ + res=usr.getSetItr(); + } + return res; + } + /** + * return the iterator on all login in the list + * @param log + * @return + */ + public Iterator getLoginIterator(){ + return tabUser.keySet().iterator(); + } + /** + * Save the object in a file + * @param nomfichier + */ + public void serialize(String nomfichier){ + try { + FileOutputStream fichier = new FileOutputStream(nomfichier); + ObjectOutputStream oos = new ObjectOutputStream(fichier); + oos.writeObject(this); + oos.flush(); + oos.close(); + } + catch (java.io.IOException e) { + e.printStackTrace(); + } + } + /** + * load the object from a file + * @param nomfichier + * @return + */ + public static UserTab unserialize(String nomfichier) { + try { + FileInputStream fichier = new FileInputStream(nomfichier); + ObjectInputStream ois = new ObjectInputStream(fichier); + UserTab usrtab = (UserTab) ois.readObject(); + return usrtab; + } + catch (java.io.IOException e) { + e.printStackTrace(); + } + catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/sw/in_progress/pow/pow/src/pow/acNetId.java b/sw/in_progress/pow/pow/src/pow/acNetId.java new file mode 100644 index 0000000000..b0fd964b33 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/acNetId.java @@ -0,0 +1,89 @@ +package pow; +/** + * this object represents the data concerning a drone extracted from Ivy + * @author genin + * + */ +public class acNetId { + private int idOfBusIvy; + private String idOnIvy; + private String nameOnIvy; + private String idOnWeb; + private String flightplan_path; + private String setting_path; + private String color; + private int maxAircrafts; /// + + public acNetId(int idBusIvy,String idIvy,String n,String pln,String s,String c,int maxACOnIvy){ + idOfBusIvy= idBusIvy; + idOnIvy=idIvy; + nameOnIvy=n; + flightplan_path = pln; + setting_path= s; + color = c; + maxAircrafts = maxACOnIvy; + idOnWeb = generateIdOnWeb(); + + } + + public acNetId(int idBusIvy,String droneWebId,String idIvy,String n,String pln,String s,String c,int maxACOnIvy){ + idOfBusIvy= idBusIvy; + idOnIvy=idIvy; + nameOnIvy=n; + flightplan_path = pln; + setting_path= s; + color = c; + maxAircrafts = maxACOnIvy; + idOnWeb = droneWebId; + + } + /** + * + * @return the id number of the drone on its ivy bus + */ + public String getIdOnIvy() {return idOnIvy;} + /** + * + * @return the name of the drone on its ivy bus + */ + public String getName() {return nameOnIvy;} + /** + * + * @return the single id number of the drone on the web server + */ + public String getIdOnWeb() {return idOnWeb;} + /** + * + * @return the full path of the flight plan config file on the GCS station + */ + public String getPlnPath() {return flightplan_path;} + /** + * + * @return the full path of the settings file on the GCS station + */ + public String getSettingPath() {return setting_path;} + /** + * + * @return the color of the drone on the GCS station (either in string or in hexadecimal) + */ + public String getColor() {return color;} + + private String generateIdOnWeb() { + //String newId = "" + (Integer.parseInt(idOnIvy) * ((int)Math.pow(maxAircrafts,idOfBusIvy))); + String newId = "" + (Integer.parseInt(idOnIvy) +maxAircrafts*idOfBusIvy*10); + System.out.println("### new Id generated : " + newId + " ###"); + return newId; + } + /** + * @return information about the drone in a string format + */ + public String toString(){ + return "id on ivy :\t" + idOnIvy + + "\nname :\t" + nameOnIvy + + "\nid on web :\t" + idOnWeb + + "\nfpl file :\t" + flightplan_path + + "\nsetting file :\t" + setting_path + + "\ncolor :\t" + color ; + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/acNetIdStorage.java b/sw/in_progress/pow/pow/src/pow/acNetIdStorage.java new file mode 100644 index 0000000000..e540be41e5 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/acNetIdStorage.java @@ -0,0 +1,312 @@ +package pow; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.StringReader; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +import fr.dgac.ivy.*; +/** + * this structure memorize all the drone which exist on the ivy bus + * @author genin + * + */ +public class acNetIdStorage { + + private int ivyWebId; + private Ivy bus; + String url; // @server to upload + private HashMap acNetIdMap; + ConcurrentHashMap dronesStates; + private int maxAircrafts; + private acNetId resultat; + + public acNetIdStorage(int ii,Ivy b,String u,int maxAC, ConcurrentHashMap states ){ + bus = b; + ivyWebId=ii; + acNetIdMap= new HashMap(); + url = u; + maxAircrafts = maxAC; + dronesStates = states; + } + /** + * Return the identifiant of the drone on the web + * @param idOnIvy + * @return + */ + public acNetId getAcNetId(String idOnIvy) + { + return acNetIdMap.get(idOnIvy); + } + /** + * Return the identifiant of the drone on the ivy bus + * @param idOnWeb + * @return + */ + public String getAcIvyId(int idOnWeb) + { String res = null; + boolean doIt = true; + Collection col = acNetIdMap.values(); + Iterator it = col.iterator(); + while(it.hasNext()&& doIt) + { + acNetId ac=it.next(); + if (Integer.parseInt(ac.getIdOnWeb())==idOnWeb){ doIt=false; res = ac.getIdOnIvy();} + } + return res; + } + /** + * search the drone net id of a drone from its ivy id + * if the drone is a new one, a new net id is requested to the server + * @param s the ivy id of the drone + */ + public void seekAcNetId(String s) { + String droneWebId; + acNetId res = acNetIdMap.get(s); + if (res==null){ + try { + AcStatus acs = dronesStates.get(s); + if (acs==AcStatus.UNKNOWN) + { + dronesStates.replace(s,AcStatus.ASKING_WEB_ID); + droneWebId = getNewDroneWebId(s); + dronesStates.replace(s,AcStatus.WEB_ID_RECEIVED); + // lance message sur ivy pour recuperer conf, name et creer un obj acNetId + String rqst_id = bus.getWBUId(); + String msgSend2Ivy = ivyWebId + " " + rqst_id + " CONFIG_REQ " + s + ""; + String msgtoBind= rqst_id +" (.*) CONFIG (.*) file://(.*) file://(.*) file://(.*) file://(.*) (.*) (.*)"; + try { + bus.bindMsgOnce(msgtoBind, new myListener(droneWebId)); + try { + dronesStates.replace(s,AcStatus.ASKING_IVY_CONF); + bus.sendMsg(msgSend2Ivy); + } catch (IvyException e) { + e.printStackTrace(); + System.out.println("### IvyException : can't send request msg ###"); + } + } catch (IvyException e) { + e.printStackTrace(); + } + } + } catch (IvyConnectionExeption e) { + System.out.println("### ERREUR on WEBID REQUEST for drone " +s+" ###"); + e.printStackTrace(); + } + } + } + + + /** + * upload de fichier de conf sur le serveur + * verifier que ca marche sur long fichier + * si probleme changer avec : + * factory.setSizeThreshold(yourMaxMemorySize); + * factory.setRepository(yourTempDirectory); + * upload.setSizeMax(yourMaxRequestSize); + * @throws InterruptedException + * @throws FileNotFoundException + */ + + public boolean uploadConfFile(acNetId ac) throws FileNotFoundException { + boolean res=false ; + String pathFPL = ac.getPlnPath(); + String pathSetting = ac.getSettingPath(); + String droneWebId = ac.getIdOnWeb(); + File f1 = new File(pathFPL); + File f2 = new File(pathSetting); + FilePart fp1 = new FilePart(f1.getName(), f1); + FilePart fp2 = new FilePart(f2.getName(), f2); + + // System.out.println("File1 Length = " + f1.length()); + //System.out.println("File2 Length = " + f2.length()); + + PostMethod filePost = new PostMethod(url); + + // filePost.addParameter("requestWebId", ""+webId); + + Part[] parts = { + new StringPart("order", "uploadConfFile"), + new StringPart("ivyWebId", ""+ivyWebId), + new StringPart("droneWebId", ""+droneWebId), + fp1, + fp2 + }; + filePost.setRequestEntity( + new MultipartRequestEntity(parts, filePost.getParams()) + ); + //filePost.addParameter("requestWebId", ""+webId); + HttpClient client = new HttpClient(); + // inutile mais bon pour 1 connection de temps en temps ... + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + // + try { + int status = client.executeMethod(filePost); + System.out.println("reponse de la methode post uploading " + HttpStatus.getStatusText(status)); + if (status != HttpStatus.SC_OK) { + System.err.println("Method failed: "); + } + else{ + String responseBody = filePost.getResponseBodyAsString(); + try{ + DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = parser.parse(new InputSource(new StringReader(responseBody))); + Element ack_node = (Element)document.getElementsByTagName("UploadAck").item(0); + int ack = Integer.parseInt(ack_node.getTextContent()); + if (ack==1){ + System.out.println("uploading ok for " +ack_node.getAttribute("iddrone")); + res = true; + } + else{ + System.out.println("uploading notok for " +ack_node.getAttribute("iddrone")); + res = false; + } + } + catch(Exception e){ + System.err.println("error during the parsing of xml response to a upload request"); + e.printStackTrace(); + } + + } + } catch (HttpException e) { + System.err.println("HttpException : echec execution requete post : uploading"); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException : echec execution requete post : uploading"); + e.printStackTrace(); + } finally { + // Release the connection. + filePost.releaseConnection(); + } + return res; + } + /** + * ask a unique new web id to the server for a new drone detected on the ivy bus + * @param IvyDroneId + * @return the new web drone id + * @throws IvyConnectionExeption + */ + public String getNewDroneWebId(String IvyDroneId) throws IvyConnectionExeption + { + String newDroneId = "#errorWebID#"; + int statusCode=-1; + HttpClient client = new HttpClient(); + client.getParams().setParameter("http.useragent", "Ivy request"); + // inutile mais bon pour 1 connection de temps en temps... + Protocol stricthttps = new Protocol("https", (ProtocolSocketFactory)new StrictSSLProtocolSocketFactory(true), 443); + client.getHostConfiguration().setHost("localhost", 443, stricthttps); + // + PostMethod method = new PostMethod(url); + method.addParameter("order", "requestNewDroneWebId"); + method.addParameter("ivyWebId", ""+ivyWebId); + //method.addParameter("ivyDroneId",IvyDroneId); + try { + statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) { + System.err.println("Method failed: " + method.getStatusLine()); + } + else + { + String responseBody = method.getResponseBodyAsString();//getResponseBody();//); + //System.out.println(responseBody); + if(responseBody.startsWith("")); + } + else + { + throw new IvyConnectionExeption("unable to reach server to get new drone webId"); + } + } + } catch (HttpException e) { + System.err.println("HttpException : echec execution requete post : request new drone webId"); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IOException : echec execution requete post : request new drone webId"); + e.printStackTrace(); + } finally { + // Release the connection. + method.releaseConnection(); + } + return newDroneId; + } + /** + * inner class + * seems requested so that the ivy send method works + * @author genin + * + */ + class myListener implements IvyMessageListener { + private String droneWebId; + + myListener(String dwi){ + droneWebId=dwi; + } + @Override + public void receive(IvyClient arg0, String[] args) { + dronesStates.replace(args[1],AcStatus.IVY_CONF_RECEIVED); + System.out.println("message rqst CONFIG received from ivy for drone "+args[1]); + String idOnIvy = args[1]; + String flightplan_path = args[2]; + String setting_path = args[5]; + String drone_name = args[7]; + String color_drone = checkColor(args[6]); + acNetId ac = new acNetId(ivyWebId,droneWebId,idOnIvy,drone_name,flightplan_path,setting_path,color_drone,maxAircrafts); + acNetIdMap.put(idOnIvy, ac); + // upload des fichiers de conf sur le serveur + try { + dronesStates.replace(args[1],AcStatus.UPLOADING_CONF); + boolean res = uploadConfFile(ac); + if(res) {dronesStates.replace(args[1],AcStatus.CONF_OK);} + else { + dronesStates.replace(args[1],AcStatus.CONF_NOTOK); + System.out.println("conf files upload of drone "+idOnIvy+" impossible, messages will be skipped");} + //seekAcNetId(idOnIvy); // on recommence la recherche qui cette fois aboutira + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.out.println("### FileNotFoundException ###"); + } + } + /* + * on ivy drone color can be either in text format or in hexa format + * this function send the color in an hex rgb format + */ + private String checkColor(String color){ + String res = ""; + if ((color.length()==7)&&(color.charAt(0)=='#')){ + res = color; + } + else + { + if(color.equals("blue")){ res = "#0000FF"; } + else if (color.equals("red")){ res = "#FF0000"; } + else if (color.equals("green")){ res = "#00FF00"; } + else {res = "#0F0F0F";} + } + return res; + } + + }// fin inner class + +} diff --git a/sw/in_progress/pow/pow/src/pow/ajaxRqst.java b/sw/in_progress/pow/pow/src/pow/ajaxRqst.java new file mode 100644 index 0000000000..0842bce187 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/ajaxRqst.java @@ -0,0 +1,484 @@ +package pow; + + +import java.io.*; +import java.net.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +// SEE http://java.developpez.com/faq/xml/?page=dom +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.*; +import javax.xml.transform.stream.*; + +import org.w3c.dom.*; +import org.xml.sax.*; + +import org.apache.commons.codec.binary.Hex; +import org.apache.xml.serialize.XMLSerializer; + +/*import org.jdom.*; +import org.jdom.input.*; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; +import org.jdom.filter.*; +*/ +import java.util.*; + +import pow.Conf; + +/** + * Servlet implementation class ajaxRqst + * handles the different request from a web client which wants to give orders to a drone + */ +public class ajaxRqst extends HttpServlet { + private static final long serialVersionUID = 1L; + private String default_folder="blabla"; + private ServletContext srvCtxt; + /** + * @see HttpServlet#HttpServlet() + */ + public ajaxRqst() { + super(); + } + + /** + * init the servlet + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); // necessaire sinon getServletContext renvoie null dans doPost + default_folder = config.getServletContext().getRealPath(""); + srvCtxt = config.getServletContext(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // TODO Auto-generated method stub + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpSession session = request.getSession(true); + // recupere les parametres + PrintWriter out = response.getWriter(); + String order = request.getParameter("order"); // fpl_update... + if(order!=null) { + if (order.equals("fpl_update")) + { + System.out.println("move waypoint requested !!!"); + String wpt_name = request.getParameter("wpt_name"); + String aircraft_id = request.getParameter("aircraft_id"); + String wpt_id = request.getParameter("wpt_id"); + String new_alt = request.getParameter("new_alt"); + String new_lat = request.getParameter("new_lat"); + String new_lon = request.getParameter("new_lon"); + String new_alt_for_fpl = request.getParameter("new_alt_for_fpl"); + String dragged = request.getParameter("dragged"); + doFplUpdate(wpt_name,aircraft_id, wpt_id,new_alt, new_lat, new_lon, new_alt_for_fpl); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + + } + else if (order.equals("activate_block")){ + System.out.println("block activation requested !!!"); + String block_id = request.getParameter("block_id"); + String aircraft_id = request.getParameter("aircraft_id"); + doActivateBlock(block_id ,aircraft_id); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("modif_setting")){ + System.out.println("modif setting requested !!!"); + String aircraft_id = request.getParameter("aircraft_id"); + String setting_id = request.getParameter("setting_id"); + String newsetting_value = request.getParameter("value"); + doModifSetting(aircraft_id,setting_id,newsetting_value); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("create_user")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + String right = request.getParameter("right"); + HashSet set_of_drone = null; + if (right.equals("user")){ + String liste_drone = request.getParameter("immats"); + StringTokenizer st = new StringTokenizer(liste_drone,";"); + set_of_drone = new HashSet(); + try{ + while (st.hasMoreTokens()) { + set_of_drone.add( st.nextToken()); + } + } + catch (NoSuchElementException ex){} + } + boolean res = doCreateUser(login,pwd,right,set_of_drone); + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + } + else if (order.equals("delete_user")){ + String login = request.getParameter("login"); + boolean res = doDeleteUser(login); + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + } + else if (order.equals("info_user")){ + String login = request.getParameter("login"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + User usr = logTab.seek(login); + String right = getRight(usr.getRights()); + String liste = usr.getListDrone(); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("modify_user")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + String right = request.getParameter("right"); + String liste_drone = request.getParameter("liste_drone"); + StringTokenizer st = new StringTokenizer(liste_drone,";"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + User usr = logTab.seek(login); + if (!pwd.equals("")) {usr.setPwd(pwd);} + usr.setRights(getRight(right)); + usr.clearListDrone(); + try{ + while (st.hasMoreTokens()) { + usr.addDrone(st.nextToken()); + } + } + catch (NoSuchElementException ex){} + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + else if (order.equals("delete_drone")){ + String name = request.getParameter("name"); + try{ + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + // création d'un constructeur de documents + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // lecture du contenu d'un fichier XML avec DOM + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + NodeList dronenameList = document.getElementsByTagName("drone"); + Element root= (Element) document.getElementsByTagName("immat").item(0); + int i = 0; + boolean doIt = true; + // removing node + while(i"); + + if(!doIt) out.println(""); + else out.println(""); + + out.println(""); + }catch(ParserConfigurationException pce){ + System.out.println("Erreur de configuration du parseur DOM"); + System.out.println("lors de l'appel à fabrique.newDocumentBuilder();"); + }catch(SAXException se){ + System.out.println("Erreur lors du parsing du document"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + }catch(IOException ioe){ + System.out.println("Erreur d'entrée/sortie"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + } + } + else if (order.equals("add_drone")){ + String name = request.getParameter("name"); + try{ + DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); + // création d'un constructeur de documents + DocumentBuilder constructeur = fabrique.newDocumentBuilder(); + // lecture du contenu d'un fichier XML avec DOM + File xml = new File(default_folder + "/conf/"+"immat.xml"); + Document document = constructeur.parse(xml); + Element root= (Element) document.getElementsByTagName("immat").item(0); + // inserting node + Element dronename = document.createElement("drone"); + dronename.setAttribute("name",name); + root.appendChild(dronename); + // save + writeXmlFile(document, default_folder + "/conf/"+"immat.xml"); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } catch(ParserConfigurationException pce){ + System.out.println("Erreur de configuration du parseur DOM"); + System.out.println("lors de l'appel à fabrique.newDocumentBuilder();"); + }catch(SAXException se){ + System.out.println("Erreur lors du parsing du document"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + }catch(IOException ioe){ + System.out.println("Erreur d'entrée/sortie"); + System.out.println("lors de l'appel à construteur.parse(xml)"); + } + + } + else if (order.equals("delete_ivyusr")){ + String name = request.getParameter("login"); + boolean res ; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + logTab.remove(name); + res = !logTab.isInside(name); + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + + response.setContentType("text/xml"); + out.println(""); + if(res){ + out.println(""); + } + else{ + out.println(""); + } + out.println(""); + + } + else if (order.equals("add_ivyusr")){ + String login = request.getParameter("login"); + String pwd = request.getParameter("pwd"); + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userIvyTable.tbl"); + User n = new User(login,pwd,Rights.IVY); + try{ + logTab.insert(n); + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } catch(AlreadyRegisteredUserException e){ + response.setContentType("text/xml"); + out.println(""); + out.println(""); + out.println(""); + } + logTab.serialize(default_folder + "/conf/"+"userIvyTable.tbl"); + } + } + out.close(); + // on envoie la reponse au client + /* response.setContentType("text/xml"); + response.setHeader("Cache-Control", "no-cache"); + PrintWriter out = response.getWriter(); + out.write("msg sended"); + out.close(); + */ + } + /* + * translate the right from string to a class + */ + private Rights getRight(String r) + { + if (r.equals("admin")) {return Rights.ADMIN;} + else if (r.equals("user")) {return Rights.USER;} + else {return Rights.VISITOR;} + } + /* + * translate the right from a class to a string + */ + private String getRight(Rights r) + { + if (r== Rights.ADMIN) {return "admin";} + else if (r== Rights.USER) {return "user";} + else {return "visitor";} + } + /* + * delete an user from the file which stores the users + */ + private boolean doDeleteUser(String login){ + boolean res ; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + logTab.remove(login); + res = !logTab.isInside(login); + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + return res; + } + /* + * create an user in the file which stores the users + */ + private boolean doCreateUser(String login, String pwd,String right,Set set_of_drone){ + boolean res; + UserTab logTab = UserTab.unserialize(default_folder + "/conf/"+"userTable.tbl"); + Rights rght = this.getRight(right); + User usr = new User(login,pwd,rght); + if (rght==Rights.USER){ + Iterator itr = set_of_drone.iterator(); + while (itr.hasNext()){ + usr.addDrone(itr.next()); + } + } + try{ + logTab.insert(usr); + res = true; + logTab.serialize(default_folder + "/conf/"+"userTable.tbl"); + } + catch (AlreadyRegisteredUserException ex){ // existe deja + res = false; + } + return res; + + } + /* + * send an order to modif a setting of a drone which belongs to a specific ivy bus + */ + private void doModifSetting(String aircraft_web_id,String setting_id,String newsetting_value){ + String order = "DL_SETTING "+ aircraft_web_id + " " + setting_id + " " + newsetting_value; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + } + /* + * send an order to jump to a new block for a drone which belongs to a specific ivy bus + */ + private void doActivateBlock(String block_id,String aircraft_web_id){ + // send msg via serveur.java + String order = "JUMP_TO_BLOCK " + aircraft_web_id + " " + block_id ; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + } + /* + * send an order to move to a new waypoint for a drone which belongs to a specific ivy bus + */ + private void doFplUpdate(String wpt_name,String aircraft_web_id, String wpt_id, + String new_alt, String new_lat, String new_lon,String new_alt_for_fpl) { + // send msg via serveur.java + String order = "MOVE_WAYPOINT " + aircraft_web_id + " " + wpt_id + " " + new_lat + " " + new_lon + " " + new_alt ; + sendOrder2Ivy(Integer.parseInt(aircraft_web_id),order); + }// end method + + + // This method writes a DOM document to a file + private static void writeXmlFile(Document doc, String filename) + { + try { + // Prepare the DOM document for writing + Source source = new DOMSource(doc); + // Prepare the output file + File file = new File(filename); + Result result = new StreamResult(file); + // Write the DOM document to the file + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.transform(source, result); } + catch (TransformerConfigurationException e) { } + catch (TransformerException e) { } + } + + + /* + * send an order to a specific ivybus via udp + */ + private void sendOrder2Ivy(int ac_web_id,String order) + { Conf myConf = new Conf(default_folder,"pow.conf"); + DatagramSocket socket; + try { + System.out.println("attempt to send order to ivy"); + socket = new DatagramSocket(myConf.portWebToIvy()); + socket.setSoTimeout(myConf.timeout()); + ServletContext srvCtxt = getServletContext(); + if (srvCtxt==null) System.out.println("srvCtxt null !!?"); + HashMap tableIvySession = (HashMap) srvCtxt.getAttribute("ivySessionTable"); + if ((socket!=null)&&(tableIvySession!=null)){ + byte buffer[] = new byte[myConf.taille()]; + Iterator> itr = tableIvySession.entrySet().iterator(); + BusIvy_ checked_bus=null; + boolean doIt=true; + while(itr.hasNext()&&doIt){ + checked_bus = itr.next().getValue().getBusIvy(); + if(checked_bus.isOwnBy(ac_web_id)){ + doIt = false ; + } + } + if(!doIt){ + InetAddress address = checked_bus.getAddress(); + SessionIvy session = tableIvySession.get(address); + AES aesCipher = session.getCipher(); + try{ + buffer = aesCipher.encrypt(order.getBytes()); + DatagramPacket DataEmitted = new DatagramPacket(buffer, buffer.length, address, myConf.portWebToIvy()); + try { + socket.send(DataEmitted); + System.out.println(" msg sended to ivy "+ address.toString()+":"+myConf.portWebToIvy()); + System.out.println("\t"+order); + //System.out.print("*"); + } catch (IOException e) { + System.out.println("erreur msg not sended to " +address.toString()+":"+myConf.portWebToIvy()); + e.printStackTrace(); + } + } catch (IOException e) { + System.out.println("erreur in encryption, msg not sended to " +address.toString()+":"+myConf.portWebToIvy()); + e.printStackTrace(); + } + catch(BadPaddingException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(order.getBytes())))); + } + catch(IllegalBlockSizeException ex){ + ex.printStackTrace(); + System.out.println("order := "+(new String(Hex.encodeHex(order.getBytes())))); + } + } + } + else + { + // error + System.out.println("unable to know socket udp or session "); + } + socket.close(); + } catch (SocketException e1) { + System.out.println("unable to open socket webtoIvy for an user request"); + e1.printStackTrace(); + } + } + +} diff --git a/sw/in_progress/pow/pow/src/pow/dbOrder.java b/sw/in_progress/pow/pow/src/pow/dbOrder.java new file mode 100644 index 0000000000..9997edae3c --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/dbOrder.java @@ -0,0 +1,14 @@ +package pow; +/** + * represents 3 kind of message stored in database + * CONNECT first connection of an ivy bus --> inform db + * DECONNECT ivy bus deconnected --> inform db + * ADD add message to db + * @author genin + * + */ +public enum dbOrder { + CONNECT, + DECONNECT, + ADD +} diff --git a/sw/in_progress/pow/pow/src/pow/log.java b/sw/in_progress/pow/pow/src/pow/log.java new file mode 100644 index 0000000000..3d93e5a685 --- /dev/null +++ b/sw/in_progress/pow/pow/src/pow/log.java @@ -0,0 +1,69 @@ +package pow; +import java.io.*; +import java.util.Calendar; +/** + * Handles the writing of a log in a file + * @author genin + * + */ +public class log { + + private File oFile = null; + private FileWriter oFileWriter = null; + private BufferedWriter oBufferedWriter = null; + + public log(String path) + { + Calendar Today = Calendar.getInstance(); + String fileName = String.valueOf(Today.get(Calendar.DAY_OF_MONTH)) + + String.valueOf(Today.get(Calendar.MONTH)) + + String.valueOf(Today.get(Calendar.YEAR)) + + String.valueOf(Today.get(Calendar.HOUR_OF_DAY)) + + String.valueOf(Today.get(Calendar.MINUTE)) + + String.valueOf(Today.get(Calendar.SECOND)) + + ".log"; + + try + { + oFile = new File(path+"/log/" + fileName); + //System.out.println("log file to be created "); + oFile.createNewFile(); + //System.out.println("log file created "); + oFileWriter = new FileWriter(oFile); + oBufferedWriter = new BufferedWriter(oFileWriter); + + oBufferedWriter.write("##########################################"); oBufferedWriter.newLine(); + oBufferedWriter.write("########## PAPARAZZI ON THE WEB ##########"); oBufferedWriter.newLine(); + oBufferedWriter.write("##########################################"); oBufferedWriter.newLine(); + oBufferedWriter.newLine(); + oBufferedWriter.write("Beginning of log : "); oBufferedWriter.newLine(); + oBufferedWriter.newLine(); + oBufferedWriter.flush(); + } + catch(IOException ex) + { + System.out.println("No log file created "); + ex.printStackTrace(); + } + } + + public void write(String writing) + { + Calendar Now = Calendar.getInstance(); + String Time = String.valueOf(Now.get(Calendar.HOUR_OF_DAY)) + ":" + + String.valueOf(Now.get(Calendar.MINUTE)) + ":" + + String.valueOf(Now.get(Calendar.SECOND)); + writing = writing.trim(); + try + { + oBufferedWriter.write(Time + " -> " + writing); oBufferedWriter.newLine(); + oBufferedWriter.flush(); + System.out.println("log at : " + Time + " -> " + writing); + } + catch(IOException ex) + { + System.out.println(ex.getMessage()); + } + + } +} \ No newline at end of file