[kune-commits] r1869 - in trunk: . debian src/main/java/cc/kune/core/server/rpc src/main/java/cc/kune/gspace/client/viewers src/main/java/cc/kune/wave/client src/main/java/cc/kune/wave/server src/main/resources src/test/java/cc/kune/core/server/integration

Vicente J. Ruiz Jurado vjrj_ at ourproject.org
Sun May 20 23:01:15 CEST 2012


Author: vjrj_
Date: 2012-05-20 23:01:15 +0200 (Sun, 20 May 2012)
New Revision: 1869

Modified:
   trunk/.classpath
   trunk/debian/changelog
   trunk/pom.xml
   trunk/src/main/java/cc/kune/core/server/rpc/ContentRPC.java
   trunk/src/main/java/cc/kune/gspace/client/viewers/ContentViewerPanel.java
   trunk/src/main/java/cc/kune/wave/client/KuneStagesProvider.java
   trunk/src/main/java/cc/kune/wave/client/WebClient.java
   trunk/src/main/java/cc/kune/wave/server/CustomAuthenticationServlet.java
   trunk/src/main/java/cc/kune/wave/server/CustomUserRegistrationServlet.java
   trunk/src/main/java/cc/kune/wave/server/CustomWaveClientServlet.java
   trunk/src/main/java/cc/kune/wave/server/WaveMain.java
   trunk/src/main/resources/wave-server-production.properties
   trunk/src/main/resources/wave-server-testing.properties
   trunk/src/main/resources/wave-server.properties
   trunk/src/test/java/cc/kune/core/server/integration/IntegrationTestHelper.java
Log:
Wave code updated

Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/.classpath	2012-05-20 21:01:15 UTC (rev 1869)
@@ -10,25 +10,25 @@
   <classpathentry kind="var" path="M2_REPO/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar" sourcepath="M2_REPO/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar"/>
   <classpathentry kind="var" path="M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0.jar" sourcepath="M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/api/0.3.15/api-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/api-src/0.3.15/api-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/api/0.3.16/api-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/api-src/0.3.16/api-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/avalon-framework/avalon-framework/4.1.3/avalon-framework-4.1.3.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/avro/avro/1.5.1/avro-1.5.1.jar" sourcepath="M2_REPO/org/apache/avro/avro/1.5.1/avro-1.5.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.jar" sourcepath="M2_REPO/backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/box/0.3.15/box-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/box-src/0.3.15/box-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/box/0.3.16/box-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/box-src/0.3.16/box-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/beanshell/bsh/2.0b4/bsh-2.0b4.jar"/>
   <classpathentry kind="var" path="M2_REPO/c3p0/c3p0/0.9.1/c3p0-0.9.1.jar" sourcepath="M2_REPO/c3p0/c3p0/0.9.1/c3p0-0.9.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar" sourcepath="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/classworlds/classworlds/1.1/classworlds-1.1.jar" sourcepath="M2_REPO/classworlds/classworlds/1.1/classworlds-1.1-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client/0.3.15/client-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-common/0.3.15/client-common-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-common-src/0.3.15/client-common-src-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-scheduler/0.3.15/client-scheduler-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-scheduler-src/0.3.15/client-scheduler-src-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-src/0.3.15/client-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client/0.3.16/client-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-common/0.3.16/client-common-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-common-src/0.3.16/client-common-src-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-scheduler/0.3.16/client-scheduler-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-scheduler-src/0.3.16/client-scheduler-src-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/client-src/0.3.16/client-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/cobogw/gwt/cobogw/1.3.1/cobogw-1.3.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/common-src/0.3.15/common-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/common-src/0.3.16/common-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar" sourcepath="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/commons-cli/commons-cli/1.2/commons-cli-1.2.jar" sourcepath="M2_REPO/commons-cli/commons-cli/1.2/commons-cli-1.2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" sourcepath="M2_REPO/commons-codec/commons-codec/1.4/commons-codec-1.4-sources.jar"/>
@@ -38,10 +38,10 @@
   <classpathentry kind="var" path="M2_REPO/commons-io/commons-io/1.3.1/commons-io-1.3.1.jar" sourcepath="M2_REPO/commons-io/commons-io/1.3.1/commons-io-1.3.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/commons-lang/commons-lang/2.5/commons-lang-2.5.jar" sourcepath="M2_REPO/commons-lang/commons-lang/2.5/commons-lang-2.5-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging/1.1/commons-logging-1.1.jar" sourcepath="M2_REPO/commons-logging/commons-logging/1.1/commons-logging-1.1-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/communication-src/0.3.15/communication-src-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/concurrencycontrol-src/0.3.15/concurrencycontrol-src-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/crypto/0.3.15/crypto-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/crypto-src/0.3.15/crypto-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/communication-src/0.3.16/communication-src-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/concurrencycontrol-src/0.3.16/concurrencycontrol-src-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/crypto/0.3.16/crypto-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/crypto-src/0.3.16/crypto-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/net/sourceforge/cssparser/cssparser/0.9.5/cssparser-0.9.5.jar" sourcepath="M2_REPO/net/sourceforge/cssparser/cssparser/0.9.5/cssparser-0.9.5-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/netbeans/lib/cvsclient/20060125/cvsclient-20060125.jar"/>
   <classpathentry kind="var" path="M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar" sourcepath="M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1-sources.jar"/>
@@ -70,7 +70,7 @@
   <classpathentry kind="var" path="M2_REPO/com/allen_sauer/gwt/log/gwt-log/gwt-log/3.0.1/gwt-log-3.0.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/google/gwt/gwt-servlet/2.1.1/gwt-servlet-2.1.1.jar" sourcepath="M2_REPO/com/google/gwt/gwt-servlet/2.1.1/gwt-servlet-2.1.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/google/gwt/gwt-user/2.1.1/gwt-user-2.1.1.jar" sourcepath="M2_REPO/com/google/gwt/gwt-user/2.1.1/gwt-user-2.1.1-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/gwt-util-src/0.3.15/gwt-util-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/gwt-util-src/0.3.16/gwt-util-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/allen_sauer/gwt/voices/gwt-voices/gwt-voices/2.0.0/gwt-voices-2.0.0.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/gwtplatform/gwtp-all/0.5/gwtp-all-0.5.jar" sourcepath="M2_REPO/com/gwtplatform/gwtp-all/0.5/gwtp-all-0.5-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/gwtplatform/gwtp-clients-common/0.5/gwtp-clients-common-0.5.jar" sourcepath="M2_REPO/com/gwtplatform/gwtp-clients-common/0.5/gwtp-clients-common-0.5-sources.jar"/>
@@ -180,11 +180,11 @@
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/scm/maven-scm-provider-tfs/1.6/maven-scm-provider-tfs-1.6.jar" sourcepath="M2_REPO/org/apache/maven/scm/maven-scm-provider-tfs/1.6/maven-scm-provider-tfs-1.6-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/scm/maven-scm-provider-vss/1.6/maven-scm-provider-vss-1.6.jar" sourcepath="M2_REPO/org/apache/maven/scm/maven-scm-provider-vss/1.6/maven-scm-provider-vss-1.6-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/maven-settings/2.0.9/maven-settings-2.0.9.jar" sourcepath="M2_REPO/org/apache/maven/maven-settings/2.0.9/maven-settings-2.0.9-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/media-src/0.3.15/media-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/media-src/0.3.16/media-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/com/mks/api/mksapi-jar/4.10.9049/mksapi-jar-4.10.9049.jar" sourcepath="M2_REPO/com/mks/api/mksapi-jar/4.10.9049/mksapi-jar-4.10.9049-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/mockito/mockito-core/1.8.5/mockito-core-1.8.5.jar" sourcepath="M2_REPO/org/mockito/mockito-core/1.8.5/mockito-core-1.8.5-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/model/0.3.15/model-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/model-src/0.3.15/model-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/model/0.3.16/model-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/model-src/0.3.16/model-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/mvel/mvel2/2.0.16/mvel2-2.0.16.jar" sourcepath="M2_REPO/org/mvel/mvel2/2.0.16/mvel2-2.0.16-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/mysql/mysql-connector-java/5.1.13/mysql-connector-java-5.1.13.jar"/>
   <classpathentry kind="var" path="M2_REPO/net/sourceforge/nekohtml/nekohtml/1.9.15/nekohtml-1.9.15.jar" sourcepath="M2_REPO/net/sourceforge/nekohtml/nekohtml/1.9.15/nekohtml-1.9.15-sources.jar"/>
@@ -196,7 +196,7 @@
   <classpathentry kind="var" path="M2_REPO/org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.jar" sourcepath="M2_REPO/org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar" sourcepath="M2_REPO/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.jar" sourcepath="M2_REPO/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/proto-msg/0.3.15/proto-msg-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/proto-msg/0.3.16/proto-msg-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/quartz-scheduler/quartz/2.1.0/quartz-2.1.0.jar" sourcepath="M2_REPO/org/quartz-scheduler/quartz/2.1.0/quartz-2.1.0-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/regexp/regexp/1.3/regexp-1.3.jar" sourcepath="M2_REPO/regexp/regexp/1.3/regexp-1.3-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/w3c/css/sac/1.3/sac-1.3.jar" sourcepath="M2_REPO/org/w3c/css/sac/1.3/sac-1.3-sources.jar"/>
@@ -228,8 +228,8 @@
   <classpathentry kind="var" path="M2_REPO/stax/stax-api/1.0.1/stax-api-1.0.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/testng/testng/6.2.1/testng-6.2.1.jar" sourcepath="M2_REPO/org/testng/testng/6.2.1/testng-6.2.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/tigase/tigase-xmltools/3.3.5/tigase-xmltools-3.3.5.jar" sourcepath="M2_REPO/tigase/tigase-xmltools/3.3.5/tigase-xmltools-3.3.5-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/util/0.3.15/util-0.3.15.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/util-src/0.3.15/util-src-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/util/0.3.16/util-0.3.16.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/util-src/0.3.16/util-src-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-file/1.0-beta-2/wagon-file-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-file/1.0-beta-2/wagon-file-1.0-beta-2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-http-lightweight/1.0-beta-2/wagon-http-lightweight-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-http-lightweight/1.0-beta-2/wagon-http-lightweight-1.0-beta-2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-http-shared/1.0-beta-2/wagon-http-shared-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-http-shared/1.0-beta-2/wagon-http-shared-1.0-beta-2-sources.jar"/>
@@ -238,7 +238,7 @@
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-ssh-common/1.0-beta-2/wagon-ssh-common-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-ssh-common/1.0-beta-2/wagon-ssh-common-1.0-beta-2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-ssh-external/1.0-beta-2/wagon-ssh-external-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-ssh-external/1.0-beta-2/wagon-ssh-external-1.0-beta-2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar" sourcepath="M2_REPO/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2-sources.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/waveinabox-server-0.3/0.3.15/waveinabox-server-0.3-0.3.15.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/waveprotocol/waveinabox-server-0.3/0.3.16/waveinabox-server-0.3-0.3.16.jar"/>
   <classpathentry kind="var" path="M2_REPO/xalan/xalan/2.7.1/xalan-2.7.1.jar" sourcepath="M2_REPO/xalan/xalan/2.7.1/xalan-2.7.1-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04.jar" sourcepath="M2_REPO/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04-sources.jar"/>

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/debian/changelog	2012-05-20 21:01:15 UTC (rev 1869)
@@ -1,3 +1,10 @@
+kune (0.2.0+b6) unstable; urgency=low
+
+  * Wave code updated (changes: search via lucene, ctrl-k for links, etc)
+  * Hibernate updated (and also lucene)
+
+ -- Vicente J. Ruiz Jurado <vjrj at ourproject.org>  Sun, 20 May 2012 22:55:28 +0200
+
 kune (0.2.0+b5) unstable; urgency=low
 
   * Some UI improvements (header and sitebar reorganization, etc)

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/pom.xml	2012-05-20 21:01:15 UTC (rev 1869)
@@ -22,7 +22,7 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <slf4j.version>1.6.1</slf4j.version>
     <openjpa.version>2.0.1</openjpa.version>
-    <wiab.version>0.3.15</wiab.version>
+    <wiab.version>0.3.16</wiab.version>
     <jetty.version>8.1.1.v20120215</jetty.version>
     <skipTests>true</skipTests>
   </properties>

Modified: trunk/src/main/java/cc/kune/core/server/rpc/ContentRPC.java
===================================================================
--- trunk/src/main/java/cc/kune/core/server/rpc/ContentRPC.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/core/server/rpc/ContentRPC.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -130,7 +130,7 @@
 
   @Override
   @Authenticated
-  @Authorizated(actionLevel = ActionLevel.container, accessRolRequired = AccessRol.Administrator, mustCheckMembership = false)
+  @Authorizated(actionLevel = ActionLevel.container, accessRolRequired = AccessRol.Editor, mustCheckMembership = false)
   @KuneTransactional
   public StateContentDTO addContent(final String userHash, final StateToken parentToken,
       final String title, final String typeId) throws DefaultException {

Modified: trunk/src/main/java/cc/kune/gspace/client/viewers/ContentViewerPanel.java
===================================================================
--- trunk/src/main/java/cc/kune/gspace/client/viewers/ContentViewerPanel.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/gspace/client/viewers/ContentViewerPanel.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -23,6 +23,7 @@
 import org.waveprotocol.box.webclient.client.RemoteViewServiceMultiplexer;
 import org.waveprotocol.box.webclient.client.SimpleWaveStore;
 import org.waveprotocol.box.webclient.search.WaveStore;
+import org.waveprotocol.box.webclient.widget.frame.FramedPanel;
 import org.waveprotocol.wave.client.account.ProfileManager;
 import org.waveprotocol.wave.client.widget.common.ImplPanel;
 import org.waveprotocol.wave.model.id.IdGenerator;
@@ -60,6 +61,7 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.DeckPanel;
 import com.google.gwt.user.client.ui.InlineHTML;
+import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.inject.Inject;
 import com.gwtplatform.mvp.client.ViewImpl;
@@ -100,6 +102,8 @@
 
   private final Widget widget;
 
+  private FramedPanel dummyWaveFrame;
+
   @Inject
   public ContentViewerPanel(final GSpaceArmor wsArmor, final WaveClientProvider waveClient,
       final ContentCapabilitiesRegistry capabilitiesRegistry, final I18nTranslationService i18n,
@@ -172,6 +176,7 @@
       final WaveClientView webClient = waveClientProv.get();
       loading = webClient.getLoading();
       waveHolder = webClient.getWaveHolder();
+      dummyWaveFrame = new FramedPanel();
       dropController.init(waveHolder);
       channel = webClient.getChannel();
       profiles = webClient.getProfiles();
@@ -223,7 +228,7 @@
       // UIObject.setVisible(waveFrame.getElement(), true);
       waveHolder.getElement().appendChild(loading);
       final Element holder = waveHolder.getElement().appendChild(Document.get().createDivElement());
-      final KuneStagesProvider wave = new KuneStagesProvider(holder, waveHolder, waveRef, channel,
+      final KuneStagesProvider wave = new KuneStagesProvider(holder, (com.google.gwt.dom.client.Element) new Label().getElement(), waveHolder, dummyWaveFrame, waveRef, channel,
           idGenerator, profiles, waveStore, isNewWave,
           org.waveprotocol.box.webclient.client.Session.get().getDomain(), true, i18n);
       this.wave = wave;

Modified: trunk/src/main/java/cc/kune/wave/client/KuneStagesProvider.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/client/KuneStagesProvider.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/client/KuneStagesProvider.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -1,3 +1,4 @@
+// @formatter:off
 /**
  * Copyright 2010 Google Inc.
  *
@@ -18,9 +19,12 @@
 package cc.kune.wave.client;
 
 import org.waveprotocol.box.webclient.client.RemoteViewServiceMultiplexer;
+import org.waveprotocol.box.webclient.client.SavedStateIndicator;
 import org.waveprotocol.box.webclient.client.StageTwoProvider;
+import org.waveprotocol.box.webclient.client.WindowTitleHandler;
 import org.waveprotocol.box.webclient.search.WaveContext;
 import org.waveprotocol.box.webclient.search.WaveStore;
+import org.waveprotocol.box.webclient.widget.frame.FramedPanel;
 import org.waveprotocol.wave.client.StageOne;
 import org.waveprotocol.wave.client.StageThree;
 import org.waveprotocol.wave.client.StageTwo;
@@ -69,61 +73,50 @@
 
   private final static AsyncHolder<Object> HALT = new AsyncHolder<Object>() {
     @Override
-    public void call(final Accessor<Object> accessor) {
+    public void call(Accessor<Object> accessor) {
       // Never ready, so never notify the accessor.
     }
   };
-
-  /**
-   * Finds the blip that should receive the focus and selects it.
-   */
-  private static void selectAndFocusOnBlip(final Reader reader, final ModelAsViewProvider views,
-      final ConversationView wave, final FocusFramePresenter focusFrame, final WaveRef waveRef) {
-    final FocusBlipSelector blipSelector = FocusBlipSelector.create(wave, views, reader,
-        new ViewTraverser());
-    final BlipView blipUi = blipSelector.selectBlipByWaveRef(waveRef);
-    // Focus on the selected blip.
-    if (blipUi != null) {
-      focusFrame.focus(blipUi);
-    }
-  }
+  
+  private final Element wavePanelElement;
+  private final Element unsavedIndicatorElement;
+  private final FramedPanel waveFrame;
+  private final LogicalPanel rootPanel;
+  private final WaveRef waveRef;
   private final RemoteViewServiceMultiplexer channel;
-  private boolean closed;
-  private final I18nTranslationService i18n;
   private final IdGenerator idGenerator;
+  private final ProfileManager profiles;
+  private final WaveStore waveStore;
   private final boolean isNewWave;
   private final String localDomain;
+
+  private boolean closed;
   private StageOne one;
-  private final ProfileManager profiles;
-  private final LogicalPanel rootPanel;
-  private final boolean showParticipantsPanel;
-
+  private StageTwo two;
   private StageThree three;
-  private StageTwo two;
   private WaveContext wave;
-  private final Element wavePanelElement;
-  private final WaveRef waveRef;
-  private final WaveStore waveStore;
+  private final boolean showParticipantsPanel;
+  private final I18nTranslationService i18n;
 
   /**
-   * @param wavePanelElement
-   *          The dom element to become the wave panel
-   * @param rootPanel
-   *          A panel that this an ancestor of wavePanelElement. This is used
-   *          for adopting to the GWT widget tree.
-   * @param waveRef
-   *          the id of the wave to open. If null, it means, create a new wave.
-   * @param channel
-   *          communication channel.
-   * @param isNewWave
-   *          true if the wave is a new client-created wave
+   * @param wavePanelElement the DOM element to become the wave panel.
+   * @param unsavedIndicatorElement the element that displays the wave saved state.
+   * @param rootPanel a panel that this an ancestor of wavePanelElement. This is
+   *        used for adopting to the GWT widget tree.
+   * @param waveFrame the wave frame.
+   * @param waveRef the id of the wave to open. If null, it means, create a new
+   *        wave.
+   * @param channel the communication channel.
+   * @param isNewWave true if the wave is a new client-created wave
    * @param idGenerator
    */
-  public KuneStagesProvider(final Element wavePanelElement, final LogicalPanel rootPanel,
-      final WaveRef waveRef, final RemoteViewServiceMultiplexer channel, final IdGenerator idGenerator,
-      final ProfileManager profiles, final WaveStore store, final boolean isNewWave,
-      final String localDomain, final boolean showParticipantsPanel, final I18nTranslationService i18n) {
+  public KuneStagesProvider(Element wavePanelElement, Element unsavedIndicatorElement,
+      LogicalPanel rootPanel, FramedPanel waveFrame, WaveRef waveRef, RemoteViewServiceMultiplexer channel,
+      IdGenerator idGenerator, ProfileManager profiles, WaveStore store, boolean isNewWave,
+      String localDomain, boolean showParticipantsPanel, I18nTranslationService i18n) {
     this.wavePanelElement = wavePanelElement;
+    this.unsavedIndicatorElement = unsavedIndicatorElement;
+    this.waveFrame = waveFrame;
     this.rootPanel = rootPanel;
     this.waveRef = waveRef;
     this.channel = channel;
@@ -137,21 +130,46 @@
   }
 
   @Override
-  protected AsyncHolder<StageOne> createStageOneLoader(final StageZero zero) {
+  protected AsyncHolder<StageZero> createStageZeroLoader() {
+    return haltIfClosed(super.createStageZeroLoader());
+  }
+
+  @Override
+  protected AsyncHolder<StageOne> createStageOneLoader(StageZero zero) {
     return haltIfClosed(new StageOne.DefaultProvider(zero) {
       @Override
-      protected LogicalPanel createWaveContainer() {
-        return rootPanel;
+      protected Element createWaveHolder() {
+        return wavePanelElement;
       }
 
       @Override
-      protected Element createWaveHolder() {
-        return wavePanelElement;
+      protected LogicalPanel createWaveContainer() {
+        return rootPanel;
       }
     });
   }
 
   @Override
+  protected AsyncHolder<StageTwo> createStageTwoLoader(StageOne one) {
+    return haltIfClosed(new StageTwoProvider(this.one = one, waveRef, channel, isNewWave, 
+       idGenerator, profiles, new SavedStateIndicator(unsavedIndicatorElement)) {
+      // Kune patch
+      @Override
+      protected DomRenderer createRenderer() {
+        return KuneFullDomWaveRendererImpl.create(getConversations(), getProfileManager(),
+            getBlipDetailer(), getViewIdMapper(), getBlipQueue(), getThreadReadStateMonitor(),
+            createViewFactories(), showParticipantsPanel);
+        
+        // Warning: this run into issue #73
+        // @Override
+        // protected void installFeatures() {
+        // WavePanelResourceLoader.loadCss();
+        // // KuneWavePanelResourceLoader.loadCss();
+        // }
+
+      }});}
+  
+  @Override
   protected AsyncHolder<StageThree> createStageThreeLoader(final StageTwo two) {
     return haltIfClosed(new StageThree.DefaultProvider(this.two = two) {
       @Override
@@ -159,7 +177,7 @@
         // Prepend an init wave flow onto the stage continuation.
         super.create(new Accessor<StageThree>() {
           @Override
-          public void use(final StageThree x) {
+          public void use(StageThree x) {
             onStageThreeLoaded(x, whenReady);
           }
         });
@@ -172,6 +190,7 @@
 
       @Override
       protected void install() {
+        // FIXME kune revise this
         EditorStaticDeps.setPopupProvider(PopupFactory.getProvider());
         EditorStaticDeps.setPopupChromeProvider(PopupChromeFactory.getProvider());
 
@@ -194,35 +213,56 @@
         KeepFocusInView.install(edit, panel);
         stageTwo.getDiffController().upgrade(edit);
       }
+      
     });
   }
 
-  @Override
-  protected AsyncHolder<StageTwo> createStageTwoLoader(final StageOne one) {
-    return haltIfClosed(new StageTwoProvider(this.one = one, waveRef, channel, isNewWave, idGenerator,
-        profiles) {
-      // Kune patch
-      @Override
-      protected DomRenderer createRenderer() {
-        return KuneFullDomWaveRendererImpl.create(getConversations(), getProfileManager(),
-            getBlipDetailer(), getViewIdMapper(), getBlipQueue(), getThreadReadStateMonitor(),
-            createViewFactories(), showParticipantsPanel);
-      }
+  private void onStageThreeLoaded(StageThree x, Accessor<StageThree> whenReady) {
+    if (closed) {
+      // Stop the loading process.
+      return;
+    }
+    three = x;
+    if (isNewWave) {
+      initNewWave(x);
+    } else {
+      handleExistingWave(x);
+    }
+    wave = new WaveContext(
+				two.getWave(), two.getConversations(), two.getSupplement(), two.getReadMonitor());
+    waveStore.add(wave);
+    install();
+    whenReady.use(x);
+  }
+  
+  private void initNewWave(StageThree three) {
+    // Do the new-wave flow.
+    ModelAsViewProvider views = two.getModelAsViewProvider();
+    BlipQueueRenderer blipQueue = two.getBlipQueue();
+    ConversationView wave = two.getConversations();
 
-      // Warning: this run into issue #73
-      // @Override
-      // protected void installFeatures() {
-      // WavePanelResourceLoader.loadCss();
-      // // KuneWavePanelResourceLoader.loadCss();
-      // }
-    });
+    // Force rendering to finish.
+    blipQueue.flush();
+    BlipView blipUi = views.getBlipView(wave.getRoot().getRootThread().getFirstBlip());
+    three.getEditActions().startEditing(blipUi);
   }
 
-  @Override
-  protected AsyncHolder<StageZero> createStageZeroLoader() {
-    return haltIfClosed(super.createStageZeroLoader());
+  private void handleExistingWave(StageThree three) {
+  if (waveRef.hasDocumentId()) {
+    BlipQueueRenderer blipQueue = two.getBlipQueue();
+    blipQueue.flush();
+    selectAndFocusOnBlip(two.getReader(), two.getModelAsViewProvider(), two.getConversations(),
+        one.getFocusFrame(), waveRef);
   }
+  }
 
+  /**
+ * A hook to install features that are not dependent an a certain stage.
+ */
+  protected void install() {
+  WindowTitleHandler.install(waveStore, waveFrame);
+  }
+
   public void destroy() {
     if (wave != null) {
       waveStore.remove(wave);
@@ -254,52 +294,26 @@
     }
     closed = true;
   }
+  /**
+   * Finds the blip that should receive the focus and selects it.
+   */
+  private static void selectAndFocusOnBlip(Reader reader, ModelAsViewProvider views,
+      ConversationView wave, FocusFramePresenter focusFrame, WaveRef waveRef) {
+    FocusBlipSelector blipSelector =
+        FocusBlipSelector.create(wave, views, reader, new ViewTraverser());
+    BlipView blipUi = blipSelector.selectBlipByWaveRef(waveRef);
+    // Focus on the selected blip.
+    if (blipUi != null) {
+      focusFrame.focus(blipUi);
+    }
+  }
 
   /**
    * @return a halting provider if this stage is closed. Otherwise, returns the
    *         given provider.
    */
-  @SuppressWarnings("unchecked")
-  // HALT is safe as a holder for any type
-  private <T> AsyncHolder<T> haltIfClosed(final AsyncHolder<T> provider) {
+  @SuppressWarnings("unchecked") // HALT is safe as a holder for any type
+  private <T> AsyncHolder<T> haltIfClosed(AsyncHolder<T> provider) {
     return closed ? (AsyncHolder<T>) HALT : provider;
   }
-
-  private void handleExistingWave(final StageThree three) {
-    if (waveRef.hasDocumentId()) {
-      final BlipQueueRenderer blipQueue = two.getBlipQueue();
-      blipQueue.flush();
-      selectAndFocusOnBlip(two.getReader(), two.getModelAsViewProvider(), two.getConversations(),
-          one.getFocusFrame(), waveRef);
-    }
-  }
-
-  private void initNewWave(final StageThree three) {
-    // Do the new-wave flow.
-    final ModelAsViewProvider views = two.getModelAsViewProvider();
-    final BlipQueueRenderer blipQueue = two.getBlipQueue();
-    final ConversationView wave = two.getConversations();
-
-    // Force rendering to finish.
-    blipQueue.flush();
-    final BlipView blipUi = views.getBlipView(wave.getRoot().getRootThread().getFirstBlip());
-    three.getEditActions().startEditing(blipUi);
-  }
-
-  private void onStageThreeLoaded(final StageThree x, final Accessor<StageThree> whenReady) {
-    if (closed) {
-      // Stop the loading process.
-      return;
-    }
-    three = x;
-    if (isNewWave) {
-      initNewWave(x);
-    } else {
-      handleExistingWave(x);
-    }
-    wave = new WaveContext(two.getWave(), two.getConversations(), two.getSupplement(),
-        two.getReadMonitor());
-    waveStore.add(wave);
-    whenReady.use(x);
-  }
 }

Modified: trunk/src/main/java/cc/kune/wave/client/WebClient.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/client/WebClient.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/client/WebClient.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -92,6 +92,7 @@
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DockLayoutPanel;
 import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.SplitLayoutPanel;
 import com.google.gwt.user.client.ui.UIObject;
 import com.google.inject.Inject;
@@ -105,111 +106,12 @@
   interface Binder extends UiBinder<DockLayoutPanel, WebClient> {
   }
 
-  /**
-   * An exception handler that reports exceptions using a <em>shiny banner</em>
-   * (an alert placed on the top of the screen). Once the stack trace is
-   * prepared, it is revealed in the banner via a link.
-   */
-  public static class ErrorHandler implements UncaughtExceptionHandler {
-    public static void getStackTraceAsync(final Throwable t, final Accessor<SafeHtml> whenReady) {
-      // TODO: Request stack-trace de-obfuscation. For now, just use the
-      // javascript stack trace.
-      //
-      // Use minimal services here, in order to avoid the chance that reporting
-      // the error produces more errors. In particular, do not use WIAB's
-      // scheduler to run this command.
-      // Also, this code could potentially be put behind a runAsync boundary, to
-      // save whatever dependencies it uses from the initial download.
-      new Timer() {
-        @Override
-        public void run() {
-          final SafeHtmlBuilder stack = new SafeHtmlBuilder();
-
-          Throwable error = t;
-          while (error != null) {
-            final String token = String.valueOf((new Date()).getTime());
-            stack.appendHtmlConstant("Token:  " + token + "<br> ");
-            stack.appendEscaped(String.valueOf(error.getMessage())).appendHtmlConstant("<br>");
-            for (final StackTraceElement elt : error.getStackTrace()) {
-              stack.appendHtmlConstant("  ")
-                  .appendEscaped(maybe(elt.getClassName(), "??")).appendHtmlConstant(".") //
-                  .appendEscaped(maybe(elt.getMethodName(), "??")).appendHtmlConstant(" (") //
-                  .appendEscaped(maybe(elt.getFileName(), "??")).appendHtmlConstant(":") //
-                  .appendEscaped(maybe(elt.getLineNumber(), "??")).appendHtmlConstant(")") //
-                  .appendHtmlConstant("<br>");
-            }
-            error = error.getCause();
-            if (error != null) {
-              stack.appendHtmlConstant("Caused by: ");
-            }
-          }
-
-          whenReady.use(stack.toSafeHtml());
-        }
-      }.schedule(1);
-    }
-
-    public static void install() {
-    GWT.setUncaughtExceptionHandler(new ErrorHandler(GWT.getUncaughtExceptionHandler()));
-    }
-
-    private static String maybe(final int value, final String otherwise) {
-      return value != -1 ? String.valueOf(value) : otherwise;
-    }
-
-    private static String maybe(final String value, final String otherwise) {
-      return value != null ? value : otherwise;
-    }
-
-    /**
-     * Indicates whether an error has already been reported (at most one error
-     * is ever reported by this handler).
-     */
-    private boolean hasFired;
-
-    /** Next handler in the handler chain. */
-    private final UncaughtExceptionHandler next;
-
-    private ErrorHandler(final UncaughtExceptionHandler next) {
-      this.next = next;
-    }
-
-    @Override
-    public void onUncaughtException(final Throwable e) {
-      if (!hasFired) {
-        hasFired = true;
-      //  final ErrorIndicatorPresenter error =
-        //    ErrorIndicatorPresenter.create(RootPanel.get("banner"));
-        getStackTraceAsync(e, new Accessor<SafeHtml>() {
-          @Override
-          public void use(final SafeHtml stack) {
-          //  error.addDetail(stack, null);
-            // REMOTE_LOG.severe(stack.asString().replace("<br>", "\n"));
-            final String message = stack.asString().replace("<br>", "\n");
-            REMOTE_LOG.severe(message);
-            NotifyUser.logError(message);
-            NotifyUser.showProgress("Error");
-            new Timer() {
-              @Override
-              public void run() {
-                NotifyUser.hideProgress();
-              }}.schedule(5000);
-          }
-        });
-      }
-
-      if (next != null) {
-        next.onUncaughtException(e);
-      }
-    }
-  }
-
   interface Style extends CssResource {
   }
 
   private static final Binder BINDER = GWT.create(Binder.class);
-  static Log LOG = Log.get(WebClient.class);
 
+  static Log LOG = Log.get(WebClient.class);
   // Use of GWT logging is only intended for sending exception reports to the
   // server, nothing else in the client should use java.util.logging.
   // Please also see WebClientDemo.gwt.xml.
@@ -217,8 +119,8 @@
 
   /** Creates a popup that warns about network disconnects. */
   private static UniversalPopup createTurbulencePopup() {
-    final PopupChrome chrome = PopupChromeFactory.createPopupChrome();
-    final UniversalPopup popup =
+    PopupChrome chrome = PopupChromeFactory.createPopupChrome();
+    UniversalPopup popup =
         PopupFactory.createPopup(null, new CenterPopupPositioner(), chrome, true);
     popup.add(new HTML("<div style='color: red; padding: 5px; text-align: center;'>"
         + "<b>A turbulence detected!<br></br>"
@@ -371,22 +273,7 @@
   public ImplPanel getWaveHolder() {
     return waveHolder;
   }
-
   @Override
-  public WaveWebSocketClient getWebSocket() {
-    return websocket;
-  }
-
-  /**
-   * Returns <code>ws(s)://yourhost[:port]/</code>.
-   */
-  // XXX check formatting wrt GPE
-  private native String getWebSocketBaseUrl(String moduleBase) /*-{
-		return ((window.location.protocol == "https:") ? "wss" : "ws")
-				+ /:\/\/[^\/]+/.exec(moduleBase)[0] + "/";
-  }-*/;
-
-  @Override
   public void login() {
     loginImpl();
   }
@@ -400,12 +287,6 @@
     }
   }
 
-  /**
-   */
-  private void loginToServer() {
-    assert loggedInUser != null;
-    channel = new RemoteViewServiceMultiplexer(websocket, loggedInUser.getAddress());
-  }
 
   @Override
   public void logout() {
@@ -416,13 +297,130 @@
     clear();
   }
 
+  @Override
+  public void setMaximized(final boolean maximized) {
+    splitPanel.setWidgetSize(searchPanel, maximized ? 0 : 400);    
+  }
+
+  private void setupUi() {
+    // Set up UI
+    DockLayoutPanel self = BINDER.createAndBindUi(this);
+    // kune-patch
+    // RootPanel.get("app").add(self);
+    initWidget(self);
+    waveHolder = new ImplPanel("");
+    waveHolder.addStyleName("k-waveHolder");
+    waveFrame.add(waveHolder);
+    // DockLayoutPanel forcibly conflicts with sensible layout control, and
+    // sticks inline styles on elements without permission. They must be
+    // cleared.
+    self.getElement().getStyle().clearPosition();
+    splitPanel.setWidgetMinSize(searchPanel, 300);
+  
+    if (LogLevel.showDebug()) {
+      logPanel.enable();
+    } else {
+      logPanel.removeFromParent();
+    }
+  
+    setupSearchPanel();
+    setupWavePanel();
+  }
+
+  @Override
+  public WaveWebSocketClient getWebSocket() {
+    return websocket;
+  }
+
+  private void setupSearchPanel() {
+    // On wave action fire an event.
+    SearchPresenter.WaveActionHandler actionHandler =
+        new SearchPresenter.WaveActionHandler() {
+          @Override
+          public void onCreateWave() {
+            ClientEvents.get().fireEvent(WaveCreationEvent.CREATE_NEW_WAVE);
+          }
+
+          @Override
+          public void onWaveSelected(WaveId id) {
+            ClientEvents.get().fireEvent(new WaveSelectionEvent(WaveRef.of(id)));
+          }
+        };
+    Search search = SimpleSearch.create(RemoteSearchService.create(), waveStore);
+    search.addListener(inboxCount.getSearchListener());
+    SearchPresenter.create(search, searchPanel, actionHandler, profiles);
+  }
+
+  private void setupWavePanel() {
+    // Hide the frame until waves start getting opened.
+    UIObject.setVisible(waveFrame.getElement(), false);
+
+    // Handles opening waves.
+    ClientEvents.get().addWaveSelectionEventHandler(new WaveSelectionEventHandler() {
+      @Override
+      public void onSelection(WaveRef waveRef) {
+        openWave(waveRef, false);
+      }
+    });
+  }
+  
+  private void setupConnectionIndicator() {
+    ClientEvents.get().addNetworkStatusEventHandler(new NetworkStatusEventHandler() {
+
+      boolean isTurbulenceDetected = false;
+
+      @Override
+      public void onNetworkStatus(NetworkStatusEvent event) {
+        Element element = Document.get().getElementById("netstatus");
+        if (element != null) {
+          switch (event.getStatus()) {
+            case CONNECTED:
+            case RECONNECTED:
+              element.setInnerText("Online");
+              element.setClassName("online");
+              isTurbulenceDetected = false;
+              turbulencePopup.hide();
+              break;
+            case DISCONNECTED:
+              element.setInnerText("Offline");
+              element.setClassName("offline");
+              if (!isTurbulenceDetected) {
+                isTurbulenceDetected = true;
+                turbulencePopup.show();
+              }
+              break;
+            case RECONNECTING:
+              element.setInnerText("Connecting...");
+              element.setClassName("connecting");
+              break;
+          }
+        }
+      }
+    });
+  }
+
   /**
+   * Returns <code>ws(s)://yourhost[:port]/</code>.
+   */
+  // XXX check formatting wrt GPE
+  private native String getWebSocketBaseUrl(String moduleBase) /*-{return ((window.location.protocol == "https:") ? "wss" : "ws") + /:\/\/[^\/]+/.exec(moduleBase)[0] + "/";}-*/;
+  
+  private native boolean useSocketIO() /*-{ return !window.WebSocket }-*/;
+  
+  /**
+   */
+  private void loginToServer() {
+    assert loggedInUser != null;
+    channel = new RemoteViewServiceMultiplexer(websocket, loggedInUser.getAddress());
+  }
+
+  /**
    * Shows a wave in a wave panel.
    *
    * @param waveRef wave id to open
    * @param isNewWave whether the wave is being created by this client session.
    */
-  private void openWave(final WaveRef waveRef, final boolean isNewWave) {
+  private void openWave(WaveRef waveRef, boolean isNewWave) {
     LOG.info("WebClient.openWave()");
 
     WaveClientClearEvent.fire(eventBus);
@@ -432,9 +430,9 @@
     // Release the display:none.
     UIObject.setVisible(waveFrame.getElement(), true);
     waveHolder.getElement().appendChild(loading);
-    final Element holder = waveHolder.getElement().appendChild(Document.get().createDivElement());
-    final KuneStagesProvider wave = new KuneStagesProvider(
-        holder, waveHolder, waveRef, channel, idGenerator, profiles, waveStore, isNewWave, Session.get().getDomain(), true, i18n);
+    Element holder = waveHolder.getElement().appendChild(Document.get().createDivElement());
+    KuneStagesProvider wave = new KuneStagesProvider(
+        holder, (com.google.gwt.dom.client.Element) new Label().getElement(), waveHolder, waveFrame, waveRef, channel, idGenerator, profiles, waveStore, isNewWave, Session.get().getDomain(), true, i18n);
     this.wave = wave;
     wave.load(new Command() {
       @Override
@@ -448,7 +446,7 @@
       WaveRef fromWaveRef;
       try {
         fromWaveRef = GwtWaverefEncoder.decodeWaveRefFromPath(encodedToken);
-      } catch (final InvalidWaveRefException e) {
+      } catch (InvalidWaveRefException e) {
         LOG.info("History token contains invalid path: " + encodedToken);
         return;
       }
@@ -463,103 +461,102 @@
     SpaceConfEvent.fire(eventBus, Space.userSpace, tokenFromWaveref);
     History.newItem(tokenFromWaveref, false);
   }
+  /**
+   * An exception handler that reports exceptions using a <em>shiny banner</em>
+   * (an alert placed on the top of the screen). Once the stack trace is
+   * prepared, it is revealed in the banner via a link.
+   */
+  public static class ErrorHandler implements UncaughtExceptionHandler {
+    public static void getStackTraceAsync(final Throwable t, final Accessor<SafeHtml> whenReady) {
+      // TODO: Request stack-trace de-obfuscation. For now, just use the
+      // javascript stack trace.
+      //
+      // Use minimal services here, in order to avoid the chance that reporting
+      // the error produces more errors. In particular, do not use WIAB's
+      // scheduler to run this command.
+      // Also, this code could potentially be put behind a runAsync boundary, to
+      // save whatever dependencies it uses from the initial download.
+      new Timer() {
+        @Override
+        public void run() {
+          SafeHtmlBuilder stack = new SafeHtmlBuilder();
 
-  @Override
-  public void setMaximized(final boolean maximized) {
-    splitPanel.setWidgetSize(searchPanel, maximized ? 0 : 400);    
-  }
+          Throwable error = t;
+          while (error != null) {
+            String token = String.valueOf((new Date()).getTime());
+            stack.appendHtmlConstant("Token:  " + token + "<br> ");
+            stack.appendEscaped(String.valueOf(error.getMessage())).appendHtmlConstant("<br>");
+            for (StackTraceElement elt : error.getStackTrace()) {
+              stack.appendHtmlConstant("  ")
+                  .appendEscaped(maybe(elt.getClassName(), "??")).appendHtmlConstant(".") //
+                  .appendEscaped(maybe(elt.getMethodName(), "??")).appendHtmlConstant(" (") //
+                  .appendEscaped(maybe(elt.getFileName(), "??")).appendHtmlConstant(":") //
+                  .appendEscaped(maybe(elt.getLineNumber(), "??")).appendHtmlConstant(")") //
+                  .appendHtmlConstant("<br>");
+            }
+            error = error.getCause();
+            if (error != null) {
+              stack.appendHtmlConstant("Caused by: ");
+            }
+          }
 
-  private void setupConnectionIndicator() {
-    ClientEvents.get().addNetworkStatusEventHandler(new NetworkStatusEventHandler() {
+          whenReady.use(stack.toSafeHtml());
+        }
+      }.schedule(1);
+    }
 
-      boolean isTurbulenceDetected = false;
+    public static void install() {
+    GWT.setUncaughtExceptionHandler(new ErrorHandler(GWT.getUncaughtExceptionHandler()));
+    }
 
-      @Override
-      public void onNetworkStatus(final NetworkStatusEvent event) {
-        final Element element = Document.get().getElementById("netstatus");
-        if (element != null) {
-          switch (event.getStatus()) {
-            case CONNECTED:
-            case RECONNECTED:
-              element.setInnerText("Online");
-              element.setClassName("online");
-              isTurbulenceDetected = false;
-              turbulencePopup.hide();
-              break;
-            case DISCONNECTED:
-              element.setInnerText("Offline");
-              element.setClassName("offline");
-              if (!isTurbulenceDetected) {
-                isTurbulenceDetected = true;
-                turbulencePopup.show();
-              }
-              break;
-            case RECONNECTING:
-              element.setInnerText("Connecting...");
-              element.setClassName("connecting");
-              break;
-          }
-        }
-      }
-    });
-  }
-private void setupSearchPanel() {
-  // On wave action fire an event.
-  final SearchPresenter.WaveActionHandler actionHandler =
-      new SearchPresenter.WaveActionHandler() {
-        @Override
-        public void onCreateWave() {
-          ClientEvents.get().fireEvent(WaveCreationEvent.CREATE_NEW_WAVE);
-        }
+    private static String maybe(final int value, final String otherwise) {
+      return value != -1 ? String.valueOf(value) : otherwise;
+    }
 
-        @Override
-        public void onWaveSelected(final WaveId id) {
-          ClientEvents.get().fireEvent(new WaveSelectionEvent(WaveRef.of(id)));
-        }
-      };
-  final Search search = SimpleSearch.create(RemoteSearchService.create(), waveStore);
-  search.addListener(inboxCount.getSearchListener());
-  SearchPresenter.create(search, searchPanel, actionHandler, profiles);
-}
-  private void setupUi() {
-    // Set up UI
-    final DockLayoutPanel self = BINDER.createAndBindUi(this);
-    // kune-patch
-    // RootPanel.get("app").add(self);
-    initWidget(self);
-    waveHolder = new ImplPanel("");
-    waveHolder.addStyleName("k-waveHolder");
-    waveFrame.add(waveHolder);
-    // DockLayoutPanel forcibly conflicts with sensible layout control, and
-    // sticks inline styles on elements without permission. They must be
-    // cleared.
-    self.getElement().getStyle().clearPosition();
-    splitPanel.setWidgetMinSize(searchPanel, 300);
-  
-    if (LogLevel.showDebug()) {
-      logPanel.enable();
-    } else {
-      logPanel.removeFromParent();
+    private static String maybe(final String value, final String otherwise) {
+      return value != null ? value : otherwise;
     }
-  
-    setupSearchPanel();
-    setupWavePanel();
-  }
 
-  private void setupWavePanel() {
-    // Hide the frame until waves start getting opened.
-    UIObject.setVisible(waveFrame.getElement(), false);
+    /**
+     * Indicates whether an error has already been reported (at most one error
+     * is ever reported by this handler).
+     */
+    private boolean hasFired;
 
-    // Handles opening waves.
-    ClientEvents.get().addWaveSelectionEventHandler(new WaveSelectionEventHandler() {
-      @Override
-      public void onSelection(final WaveRef waveRef) {
-        openWave(waveRef, false);
+    /** Next handler in the handler chain. */
+    private final UncaughtExceptionHandler next;
+
+    private ErrorHandler(final UncaughtExceptionHandler next) {
+      this.next = next;
+    }
+
+    @Override
+    public void onUncaughtException(final Throwable e) {
+      if (!hasFired) {
+        hasFired = true;
+      //  final ErrorIndicatorPresenter error =
+        //    ErrorIndicatorPresenter.create(RootPanel.get("banner"));
+        getStackTraceAsync(e, new Accessor<SafeHtml>() {
+          @Override
+          public void use(final SafeHtml stack) {
+          //  error.addDetail(stack, null);
+            // REMOTE_LOG.severe(stack.asString().replace("<br>", "\n"));
+            final String message = stack.asString().replace("<br>", "\n");
+            REMOTE_LOG.severe(message);
+            NotifyUser.logError(message);
+            NotifyUser.showProgress("Error");
+            new Timer() {
+              @Override
+              public void run() {
+                NotifyUser.hideProgress();
+              }}.schedule(5000);
+          }
+        });
       }
-    });
-  }
 
-  private native boolean useSocketIO() /*-{
-		return !window.WebSocket
-  }-*/;
+      if (next != null) {
+        next.onUncaughtException(e);
+      }
+    }
+  }
 }

Modified: trunk/src/main/java/cc/kune/wave/server/CustomAuthenticationServlet.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/CustomAuthenticationServlet.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/server/CustomAuthenticationServlet.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -1,21 +1,19 @@
-/*
+// @formatter:off
+/**
+ * Copyright 2010 Google Inc.
  *
- * Copyright (C) 2007-2011 The kune development team (see CREDITS for details)
- * This file is part of kune.
+ *  Licensed 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
  *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
+ *  http://www.apache.org/licenses/LICENSE-2.0
  *
- * This program 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 Affero General Public License for more details.
+ *  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.
  *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
  */
 package cc.kune.wave.server;
 
@@ -58,6 +56,7 @@
 import com.google.common.base.Strings;
 import com.google.gxp.base.GxpContext;
 import com.google.inject.Inject;
+import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 
 /**
@@ -66,47 +65,64 @@
  * 
  * @author josephg at gmail.com (Joseph Gentle)
  */
+ at SuppressWarnings("serial")
+ at Singleton
+// FIXME: Use AuthtenticationServlet (patched with public login)
 public class CustomAuthenticationServlet extends HttpServlet {
     private static final String DEFAULT_REDIRECT_URL = "/";
-    private static final Log LOG = Log.get(CustomAuthenticationServlet.class);
+    public static final String RESPONSE_STATUS_NONE = "NONE";
     public static final String RESPONSE_STATUS_FAILED = "FAILED";
-    public static final String RESPONSE_STATUS_NONE = "NONE";
-
     public static final String RESPONSE_STATUS_SUCCESS = "SUCCESS";
 
+    private static final Log LOG = Log.get(CustomAuthenticationServlet.class);
+
     private final Configuration configuration;
+    private final SessionManager sessionManager;
     private final String domain;
-    private final SessionManager sessionManager;
+  private final String analyticsAccount;
 
     @Inject
-    public CustomAuthenticationServlet(final Configuration configuration, final SessionManager sessionManager,
-            @Named(CoreSettings.WAVE_SERVER_DOMAIN) final String domain) {
+    public CustomAuthenticationServlet(Configuration configuration, SessionManager sessionManager,
+            @Named(CoreSettings.WAVE_SERVER_DOMAIN) String domain,
+      @Named(CoreSettings.ANALYTICS_ACCOUNT) String analyticsAccount) {
         Preconditions.checkNotNull(configuration, "Configuration is null");
         Preconditions.checkNotNull(sessionManager, "Session manager is null");
         this.configuration = configuration;
         this.sessionManager = sessionManager;
         this.domain = domain.toLowerCase();
+    this.analyticsAccount = analyticsAccount;
     }
 
-    /**
-     * On GET, present a login form if the user isn't authenticated.
-     */
-    @Override
-    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
-        // If the user is already logged in, we'll try to redirect them
-        // immediately.
-        resp.setCharacterEncoding("UTF-8");
-        req.setCharacterEncoding("UTF-8");
-        final HttpSession session = req.getSession(false);
-        final ParticipantId user = sessionManager.getLoggedInUser(session);
+    @SuppressWarnings("unchecked")
+    public LoginContext login(BufferedReader body) throws IOException, LoginException {
+        try {
+            Subject subject = new Subject();
 
-        if (user != null) {
-            redirectLoggedInUser(req, resp);
-        } else {
-            resp.setStatus(HttpServletResponse.SC_OK);
-            resp.setContentType("text/html;charset=utf-8");
-            AuthenticationPage.write(resp.getWriter(), new GxpContext(req.getLocale()), domain, "",
-                    RESPONSE_STATUS_NONE);
+            String parametersLine = body.readLine();
+            // Throws UnsupportedEncodingException.
+            byte[] utf8Bytes = parametersLine.getBytes("UTF-8");
+
+            CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
+            utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
+            utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+
+            // Throws CharacterCodingException.
+            CharBuffer parsed = utf8Decoder.decode(ByteBuffer.wrap(utf8Bytes));
+            parametersLine = parsed.toString();
+
+            MultiMap<String> parameters = new UrlEncoded(parametersLine);
+            CallbackHandler callbackHandler = new HttpRequestBasedCallbackHandler(parameters);
+
+            LoginContext context = new LoginContext("Wave", subject, callbackHandler, configuration);
+
+            // If authentication fails, login() will throw a LoginException.
+            context.login();
+            return context;
+        } catch (CharacterCodingException cce) {
+      throw new LoginException("Character coding exception (not utf-8): "
+          + cce.getLocalizedMessage());
+    } catch (UnsupportedEncodingException uee) {
+            throw new LoginException("ad character encoding specification: " + uee.getLocalizedMessage());
         }
     }
 
@@ -114,46 +130,46 @@
      * The POST request should have all the fields required for authentication.
      */
     @Override
-    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
         req.setCharacterEncoding("UTF-8");
         LoginContext context;
         try {
             context = login(req.getReader());
-        } catch (final LoginException e) {
-            final String message = "The username or password you entered is incorrect.";
-            final String responseType = RESPONSE_STATUS_FAILED;
+        } catch (LoginException e) {
+            String message = "The username or password you entered is incorrect.";
+            String responseType = RESPONSE_STATUS_FAILED;
             LOG.info("User authentication failed: " + e.getLocalizedMessage());
             resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
-            AuthenticationPage.write(resp.getWriter(), new GxpContext(req.getLocale()), domain, message, responseType);
+            AuthenticationPage.write(resp.getWriter(), new GxpContext(req.getLocale()), domain, message, 
+          analyticsAccount, responseType);
             return;
         }
 
-        final Subject subject = context.getSubject();
+        Subject subject = context.getSubject();
 
         ParticipantId loggedInAddress;
         try {
             loggedInAddress = getLoggedInUser(subject);
-        } catch (final InvalidParticipantAddress e1) {
-            throw new IllegalStateException("The user provided valid authentication information, but the username"
+        } catch (InvalidParticipantAddress e1) {
+            throw new IllegalStateException(
+         "The user provided valid authentication information, but the username"
                     + " isn't a valid user address.");
         }
 
         if (loggedInAddress == null) {
             try {
                 context.logout();
-            } catch (final LoginException e) {
-                // Logout failed. Absorb the error, since we're about to throw
-                // an
+            } catch (LoginException e) {
+                // Logout failed. Absorb the error, since we're about to throw an
                 // illegal state exception anyway.
             }
-            throw new IllegalStateException("The user provided valid authentication information, but we don't "
+            throw new IllegalStateException(
+                 "The user provided valid authentication information, but we don't "
                     + "know how to map their identity to a wave user address.");
         }
 
-        final HttpSession session = req.getSession(true);
+        HttpSession session = req.getSession(true);
         sessionManager.setLoggedInUser(session, loggedInAddress);
-        // The context needs to be notified when the user logs out.
-        session.setAttribute("context", context);
         LOG.info("Authenticated user " + loggedInAddress);
 
         redirectLoggedInUser(req, resp);
@@ -166,17 +182,14 @@
      * authentication types are added, this method will need to be updated to
      * support their principal types.
      * 
-     * @throws InvalidParticipantAddress
-     *             The subject's address is invalid
+   * @throws InvalidParticipantAddress The subject's address is invalid
      */
-    private ParticipantId getLoggedInUser(final Subject subject) throws InvalidParticipantAddress {
+    private ParticipantId getLoggedInUser(Subject subject) throws InvalidParticipantAddress {
         String address = null;
 
-        for (final Principal p : subject.getPrincipals()) {
-            // TODO(josephg): When we support other authentication types (LDAP,
-            // etc),
-            // this method will need to read the address portion out of the
-            // other principal types.
+        for (Principal p : subject.getPrincipals()) {
+            // TODO(josephg): When we support other authentication types (LDAP, etc),
+            // this method will need to read the address portion out of the other principal types.
             if (p instanceof ParticipantPrincipal) {
                 address = ((ParticipantPrincipal) p).getName();
                 break;
@@ -186,35 +199,24 @@
         return address == null ? null : ParticipantId.of(address);
     }
 
-    @SuppressWarnings("unchecked")
-    public LoginContext login(final BufferedReader body) throws IOException, LoginException {
-        try {
-            final Subject subject = new Subject();
+    /**
+     * On GET, present a login form if the user isn't authenticated.
+     */
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        // If the user is already logged in, we'll try to redirect them immediately.
+        resp.setCharacterEncoding("UTF-8");
+        req.setCharacterEncoding("UTF-8");
+        HttpSession session = req.getSession(false);
+        ParticipantId user = sessionManager.getLoggedInUser(session);
 
-            String parametersLine = body.readLine();
-            // Throws UnsupportedEncodingException.
-            final byte[] utf8Bytes = parametersLine.getBytes("UTF-8");
-
-            final CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
-            utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
-            utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
-
-            // Throws CharacterCodingException.
-            final CharBuffer parsed = utf8Decoder.decode(ByteBuffer.wrap(utf8Bytes));
-            parametersLine = parsed.toString();
-
-            final MultiMap<String> parameters = new UrlEncoded(parametersLine);
-            final CallbackHandler callbackHandler = new HttpRequestBasedCallbackHandler(parameters);
-
-            final LoginContext context = new LoginContext("Wave", subject, callbackHandler, configuration);
-
-            // If authentication fails, login() will throw a LoginException.
-            context.login();
-            return context;
-        } catch (final CharacterCodingException cce) {
-            throw new LoginException("Character coding exception (not utf-8): " + cce.getLocalizedMessage());
-        } catch (final UnsupportedEncodingException uee) {
-            throw new LoginException("ad character encoding specification: " + uee.getLocalizedMessage());
+        if (user != null) {
+            redirectLoggedInUser(req, resp);
+        } else {
+            resp.setStatus(HttpServletResponse.SC_OK);
+            resp.setContentType("text/html;charset=utf-8");
+            AuthenticationPage.write(resp.getWriter(), new GxpContext(req.getLocale()), domain, "",
+          RESPONSE_STATUS_NONE, analyticsAccount);
         }
     }
 
@@ -226,30 +228,29 @@
      * 
      * @throws IOException
      */
-    private void redirectLoggedInUser(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
+  private void redirectLoggedInUser(HttpServletRequest req, HttpServletResponse resp)
+      throws IOException {
         Preconditions.checkState(sessionManager.getLoggedInUser(req.getSession(false)) != null,
                 "The user is not logged in");
-        final String query = req.getQueryString();
+        String query = req.getQueryString();
 
-        // Not using req.getParameter() for this because calling that method
-        // might parse the password
-        // sitting in POST data into a String, where it could be read by another
-        // process after the
+        // Not using req.getParameter() for this because calling that method might parse the password
+        // sitting in POST data into a String, where it could be read by another process after the
         // string is garbage collected.
         if (query == null || !query.startsWith("r=")) {
             resp.sendRedirect(DEFAULT_REDIRECT_URL);
             return;
         }
 
-        final String encoded_url = query.substring("r=".length());
-        final String path = URLDecoder.decode(encoded_url, "UTF-8");
+        String encoded_url = query.substring("r=".length());
+        String path = URLDecoder.decode(encoded_url, "UTF-8");
 
         // The URL must not be an absolute URL to prevent people using this as a
         // generic redirection service.
         URI uri;
         try {
             uri = new URI(path);
-        } catch (final URISyntaxException e) {
+        } catch (URISyntaxException e) {
             // The redirect URL is invalid.
             resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
             return;

Modified: trunk/src/main/java/cc/kune/wave/server/CustomUserRegistrationServlet.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/CustomUserRegistrationServlet.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/server/CustomUserRegistrationServlet.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -54,17 +54,20 @@
   private final AccountStore accountStore;
   private final String domain;
   private final boolean registrationDisabled;
+  private final String analyticsAccount;
 
   private final Log LOG = Log.get(CustomUserRegistrationServlet.class);
 
   @Inject
   public CustomUserRegistrationServlet(AccountStore accountStore,
       @Named(CoreSettings.WAVE_SERVER_DOMAIN) String domain,
-      @Named(CoreSettings.DISABLE_REGISTRATION) boolean registrationDisabled) {
+      @Named(CoreSettings.DISABLE_REGISTRATION) boolean registrationDisabled,
+      @Named(CoreSettings.ANALYTICS_ACCOUNT) String analyticsAccount) {
     this.accountStore = accountStore;
     this.domain = domain;
   //  this.welcomeBot = welcomeBot;
     this.registrationDisabled = registrationDisabled;
+    this.analyticsAccount = analyticsAccount;
   }
 
   @Override
@@ -75,6 +78,7 @@
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
     req.setCharacterEncoding("UTF-8");
+
     String message = null;
     String responseType;
     String password = req.getParameter(HttpRequestBasedCallbackHandler.PASSWORD_FIELD);
@@ -149,11 +153,11 @@
       LOG.severe("Failed to create new account for " + id, e);
       return "An unexpected error occured while trying to create the account";
     }
-//    try {
+    // try {
     //  welcomeBot.greet(account.getId());
-//    } catch (IOException e) {
-//      LOG.warning("Failed to create a welcome wavelet for " + id, e);
-//    }
+    // } catch (IOException e) {
+      // LOG.warning("Failed to create a welcome wavelet for " + id, e);
+    // }
     return null;
   }
 
@@ -162,6 +166,6 @@
     dest.setCharacterEncoding("UTF-8");
     dest.setContentType("text/html;charset=utf-8");
     UserRegistrationPage.write(dest.getWriter(), new GxpContext(locale), domain, message,
-        responseType, registrationDisabled);
+        responseType, registrationDisabled, analyticsAccount);
   }
 }

Modified: trunk/src/main/java/cc/kune/wave/server/CustomWaveClientServlet.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/CustomWaveClientServlet.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/server/CustomWaveClientServlet.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -70,6 +70,7 @@
 
   private final String domain;
   private final Boolean useSocketIO;
+  private final String analyticsAccount;
   private final SessionManager sessionManager;
 
   /**
@@ -79,9 +80,11 @@
   public CustomWaveClientServlet(
       @Named(CoreSettings.WAVE_SERVER_DOMAIN) String domain,
       @Named(CoreSettings.USE_SOCKETIO) Boolean useSocketIO,
+      @Named(CoreSettings.ANALYTICS_ACCOUNT) String analyticsAccount,
       SessionManager sessionManager) {
     this.domain = domain;
     this.useSocketIO = useSocketIO;
+    this.analyticsAccount = analyticsAccount;
     this.sessionManager = sessionManager;
   }
 
@@ -109,7 +112,7 @@
     try {
       WaveClientPage.write(response.getWriter(), new GxpContext(request.getLocale()),
           getSessionJson(request.getSession(false)), getClientFlags(request),
-          TopBar.getGxpClosure(username, userDomain), useSocketIO);
+          TopBar.getGxpClosure(username, userDomain), useSocketIO, analyticsAccount);
     } catch (IOException e) {
       LOG.warning("Failed to write GXP for request " + request, e);
       response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

Modified: trunk/src/main/java/cc/kune/wave/server/WaveMain.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/WaveMain.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/java/cc/kune/wave/server/WaveMain.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -33,6 +33,7 @@
 import org.eclipse.jetty.servlets.ProxyServlet;
 import org.waveprotocol.box.common.comms.WaveClientRpc.ProtocolWaveClientRpc;
 import org.waveprotocol.box.server.CoreSettings;
+import org.waveprotocol.box.server.SearchModule;
 import org.waveprotocol.box.server.ServerModule;
 import org.waveprotocol.box.server.authentication.AccountStoreHolder;
 import org.waveprotocol.box.server.authentication.SessionManager;
@@ -54,15 +55,20 @@
 import org.waveprotocol.box.server.rpc.AuthenticationServlet;
 import org.waveprotocol.box.server.rpc.FetchProfilesServlet;
 import org.waveprotocol.box.server.rpc.FetchServlet;
+import org.waveprotocol.box.server.rpc.NotificationServlet;
 import org.waveprotocol.box.server.rpc.SearchServlet;
 import org.waveprotocol.box.server.rpc.ServerRpcProvider;
 import org.waveprotocol.box.server.rpc.SignOutServlet;
 import org.waveprotocol.box.server.rpc.UserRegistrationServlet;
 import org.waveprotocol.box.server.rpc.WaveRefServlet;
 import org.waveprotocol.box.server.waveserver.CustomImportServlet;
+import org.waveprotocol.box.server.waveserver.PerUserWaveViewBus;
+import org.waveprotocol.box.server.waveserver.PerUserWaveViewDistpatcher;
 import org.waveprotocol.box.server.waveserver.WaveBus;
+import org.waveprotocol.box.server.waveserver.WaveIndexer;
 import org.waveprotocol.box.server.waveserver.WaveServerException;
 import org.waveprotocol.box.server.waveserver.WaveletProvider;
+import org.waveprotocol.box.server.waveserver.WaveletStateException;
 import org.waveprotocol.wave.crypto.CertPathStore;
 import org.waveprotocol.wave.federation.FederationSettings;
 import org.waveprotocol.wave.federation.FederationTransport;
@@ -147,6 +153,10 @@
         Names.named(CoreSettings.WAVELET_LOAD_EXECUTOR_THREAD_COUNT)));
     int deltaPersistCount = settingsInjector.getInstance(Key.get(Integer.class,
         Names.named(CoreSettings.DELTA_PERSIST_EXECUTOR_THREAD_COUNT)));
+    int storageContinuationCount = settingsInjector.getInstance(Key.get(Integer.class,
+        Names.named(CoreSettings.STORAGE_CONTINUATION_EXECUTOR_THREAD_COUNT)));
+    int lookupCount = settingsInjector.getInstance(Key.get(Integer.class,
+        Names.named(CoreSettings.LOOKUP_EXECUTOR_THREAD_COUNT)));
 
     if (enableFederation) {
       Module federationSettings =
@@ -157,10 +167,11 @@
 
     Module federationModule = buildFederationModule(settingsInjector, enableFederation);
     PersistenceModule persistenceModule = settingsInjector.getInstance(PersistenceModule.class);
+    Module searchModule = settingsInjector.getInstance(SearchModule.class);
     Injector injector =
         settingsInjector.createChildInjector(new ServerModule(enableFederation, listenerCount,
-            waveletLoadCount, deltaPersistCount), new RobotApiModule(), federationModule,
-	persistenceModule);
+            waveletLoadCount, deltaPersistCount, storageContinuationCount, lookupCount),
+               new RobotApiModule(), federationModule, persistenceModule, searchModule); 
 
     ServerRpcProvider server = injector.getInstance(ServerRpcProvider.class);
     WaveBus waveBus = injector.getInstance(WaveBus.class);
@@ -177,6 +188,7 @@
     initializeRobots(injector, waveBus);
     initializeFrontend(injector, server, waveBus);
     initializeFederation(injector);
+    initializeSearch(injector, waveBus);
 
     LOG.info("Starting server");
     server.startWebSocketServer(injector);
@@ -217,9 +229,9 @@
     server.addServlet(SessionManager.SIGN_IN_URL, injector.getInstance(AuthenticationServlet.class));
     server.addServlet("/auth/signout", injector.getInstance(SignOutServlet.class));
     server.addServlet("/auth/register", injector.getInstance(UserRegistrationServlet.class));
-
     server.addServlet("/fetch/*", injector.getInstance(FetchServlet.class));
     server.addServlet("/search/*", injector.getInstance(SearchServlet.class));
+    server.addServlet("/notification/*", injector.getInstance(NotificationServlet.class));
 
     server.addServlet("/robot/dataapi", injector.getInstance(DataApiServlet.class));
     server.addServlet(DataApiOAuthServlet.DATA_API_OAUTH_PATH + "/*", injector.getInstance(DataApiOAuthServlet.class));
@@ -276,4 +288,16 @@
     FederationTransport federationManager = injector.getInstance(FederationTransport.class);
     federationManager.startFederation();
   }
+
+  private static void initializeSearch(Injector injector, WaveBus waveBus)
+      throws WaveletStateException, WaveServerException {
+    PerUserWaveViewDistpatcher waveViewDistpatcher =
+        injector.getInstance(PerUserWaveViewDistpatcher.class);
+    PerUserWaveViewBus.Listener listener = injector.getInstance(PerUserWaveViewBus.Listener.class);
+    waveViewDistpatcher.addListener(listener);
+    waveBus.subscribe(waveViewDistpatcher);
+
+    WaveIndexer waveIndexer = injector.getInstance(WaveIndexer.class);
+    waveIndexer.remakeIndex();
+  }
 }

Modified: trunk/src/main/resources/wave-server-production.properties
===================================================================
--- trunk/src/main/resources/wave-server-production.properties	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/resources/wave-server-production.properties	2012-05-20 21:01:15 UTC (rev 1869)
@@ -76,14 +76,22 @@
 # Default value: "" (empty)
 welcome_wave_id =
 
-# Thread counts
-#The number of threads to listen on wavelet updates. Default value: 1
+# The number of threads to listen on wavelet updates. Default value: 1
 listener_executor_thread_count = 1
-#The number of threads for loading wavelets. Default value: 2
-wavelet_load_executor_thread_count = 2
-#The number of threads to persist deltas. Default value: 2
-delta_persist_executor_thread_count = 2
 
+# The number of threads for loading wavelets. Default value: 1
+wavelet_load_executor_thread_count = 1
+
+# The number of threads to persist deltas. Default value: 1
+delta_persist_executor_thread_count = 1
+
+# The number of threads to perform post wavelet loading logic. Default value: 1
+storage_continuation_executor_thread_count = 1
+
+# The number of threads for looking up the wavelet ids
+# while creating a list of all wavelets in the persistent storage. Default value: 1
+lookup_executor_thread_count = 1
+
 # To enable federation, edit the server.federation.config file and include it here.
 # Or run ant -f server-config.xml server-federation-config
 # If not using the server-config.xml ant script - it is possible just to comment the line.
@@ -101,17 +109,33 @@
 
 # Set true to prevent anyone registering on your server.
 # When true, only the admin user can use the RegistrationRobot to add new accounts
+# Default value: false (in kune true)
+disable_registration = true
+
+# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional).
 # Default value: false
-disable_registration = false
-
-# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional)
 enable_ssl = false
 
 # Path to keystore containg the ssl certificates to server
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_path = /etc/kune/kune.ks
 
-#Password to the keystore
+#Password to the keystore.
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_password = change_me
 
-# Enable import of waves via /import URL. Default value: false
+# Enable import of waves via /import URL. 
+# Default value: false
 enable_import = false
+
+# Currently supported search types: memory, lucene.
+# Default value: lucene.
+search_type = lucene
+
+# The location where search indexes are stored on disk.
+# Note: This is only used when using the lucene search type. It is ignored
+# for other search types.
+# Default value: _indexes
+index_directory = /var/lib/kune/_wave_indexes
+
+analytics_account =

Modified: trunk/src/main/resources/wave-server-testing.properties
===================================================================
--- trunk/src/main/resources/wave-server-testing.properties	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/resources/wave-server-testing.properties	2012-05-20 21:01:15 UTC (rev 1869)
@@ -76,14 +76,22 @@
 # Default value: "" (empty)
 welcome_wave_id =
 
-# Thread counts
-#The number of threads to listen on wavelet updates. Default value: 1
+# The number of threads to listen on wavelet updates. Default value: 1
 listener_executor_thread_count = 1
-#The number of threads for loading wavelets. Default value: 2
-wavelet_load_executor_thread_count = 2
-#The number of threads to persist deltas. Default value: 2
-delta_persist_executor_thread_count = 2
 
+# The number of threads for loading wavelets. Default value: 1
+wavelet_load_executor_thread_count = 1
+
+# The number of threads to persist deltas. Default value: 1
+delta_persist_executor_thread_count = 1
+
+# The number of threads to perform post wavelet loading logic. Default value: 1
+storage_continuation_executor_thread_count = 1
+
+# The number of threads for looking up the wavelet ids
+# while creating a list of all wavelets in the persistent storage. Default value: 1
+lookup_executor_thread_count = 1
+
 # To enable federation, edit the server.federation.config file and include it here.
 # Or run ant -f server-config.xml server-federation-config
 # If not using the server-config.xml ant script - it is possible just to comment the line.
@@ -101,17 +109,33 @@
 
 # Set true to prevent anyone registering on your server.
 # When true, only the admin user can use the RegistrationRobot to add new accounts
+# Default value: false (in kune true)
+disable_registration = true
+
+# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional).
 # Default value: false
-disable_registration = false
-
-# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional)
 enable_ssl = false
 
 # Path to keystore containg the ssl certificates to server
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_path = src/main/resources/wiab.ks
 
-#Password to the keystore
+#Password to the keystore.
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_password = fafafa
 
-# Enable import of waves via /import URL. Default value: false
+# Enable import of waves via /import URL. 
+# Default value: false
 enable_import = false
+
+# Currently supported search types: memory, lucene.
+# Default value: lucene.
+search_type = lucene
+
+# The location where search indexes are stored on disk.
+# Note: This is only used when using the lucene search type. It is ignored
+# for other search types.
+# Default value: _indexes
+index_directory = _indexes
+
+analytics_account =

Modified: trunk/src/main/resources/wave-server.properties
===================================================================
--- trunk/src/main/resources/wave-server.properties	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/main/resources/wave-server.properties	2012-05-20 21:01:15 UTC (rev 1869)
@@ -76,14 +76,22 @@
 # Default value: "" (empty)
 welcome_wave_id =
 
-# Thread counts
-#The number of threads to listen on wavelet updates. Default value: 1
+# The number of threads to listen on wavelet updates. Default value: 1
 listener_executor_thread_count = 1
-#The number of threads for loading wavelets. Default value: 2
-wavelet_load_executor_thread_count = 2
-#The number of threads to persist deltas. Default value: 2
-delta_persist_executor_thread_count = 2
 
+# The number of threads for loading wavelets. Default value: 1
+wavelet_load_executor_thread_count = 1
+
+# The number of threads to persist deltas. Default value: 1
+delta_persist_executor_thread_count = 1
+
+# The number of threads to perform post wavelet loading logic. Default value: 1
+storage_continuation_executor_thread_count = 1
+
+# The number of threads for looking up the wavelet ids
+# while creating a list of all wavelets in the persistent storage. Default value: 1
+lookup_executor_thread_count = 1
+
 # To enable federation, edit the server.federation.config file and include it here.
 # Or run ant -f server-config.xml server-federation-config
 # If not using the server-config.xml ant script - it is possible just to comment the line.
@@ -101,17 +109,33 @@
 
 # Set true to prevent anyone registering on your server.
 # When true, only the admin user can use the RegistrationRobot to add new accounts
+# Default value: false (in kune true)
+disable_registration = true
+
+# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional).
 # Default value: false
-disable_registration = false
-
-# Enable SSL for all address/port combinations listed (makes the next 2 settings non-optional)
 enable_ssl = false
 
 # Path to keystore containg the ssl certificates to server
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_path = src/main/resources/wiab.ks
 
-#Password to the keystore
+#Password to the keystore.
+# Note: this is only used when enable_ssl set to true.
 ssl_keystore_password = fafafa
 
-# Enable import of waves via /import URL. Default value: false
+# Enable import of waves via /import URL. 
+# Default value: false
 enable_import = true
+
+# Currently supported search types: memory, lucene.
+# Default value: lucene.
+search_type = lucene
+
+# The location where search indexes are stored on disk.
+# Note: This is only used when using the lucene search type. It is ignored
+# for other search types.
+# Default value: _indexes
+index_directory = kune-data/_indexes
+
+analytics_account =

Modified: trunk/src/test/java/cc/kune/core/server/integration/IntegrationTestHelper.java
===================================================================
--- trunk/src/test/java/cc/kune/core/server/integration/IntegrationTestHelper.java	2012-05-06 23:38:27 UTC (rev 1868)
+++ trunk/src/test/java/cc/kune/core/server/integration/IntegrationTestHelper.java	2012-05-20 21:01:15 UTC (rev 1869)
@@ -93,7 +93,7 @@
               requestStaticInjection(GroupServerUtils.class);
             }
           }, new ListsServerModule(), new RobotApiModule(), new PlatformServerModule(),
-          new DocumentServerModule(), new ChatServerModule(), new ServerModule(false, 1, 2, 2),
+          new DocumentServerModule(), new ChatServerModule(), new ServerModule(false, 1, 1, 1, 1, 1),
           federationModule, new WikiServerModule(), new TaskServerModule(), new BarterServerModule(),
           new EventsServerModule(), new TrashServerModule());
       try {




More information about the kune-commits mailing list