Author: yurize
Date: Mon Feb  6 18:45:52 2012
New Revision: 1241106

URL: http://svn.apache.org/viewvc?rev=1241106&view=rev
Log:
Adds SSL serving capabilites. By [email protected] 
https://reviews.apache.org/r/3584/

Modified:
    incubator/wave/trunk/server-config.xml
    incubator/wave/trunk/server.config.example
    incubator/wave/trunk/src/org/waveprotocol/box/server/CoreSettings.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/ServerRpcProvider.java
    
incubator/wave/trunk/src/org/waveprotocol/box/webclient/client/WebClient.java
    
incubator/wave/trunk/test/org/waveprotocol/box/server/robots/agent/AbstractRobotAgentTest.java
    incubator/wave/trunk/test/org/waveprotocol/box/server/rpc/RpcTest.java

Modified: incubator/wave/trunk/server-config.xml
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/server-config.xml?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- incubator/wave/trunk/server-config.xml (original)
+++ incubator/wave/trunk/server-config.xml Mon Feb  6 18:45:52 2012
@@ -23,6 +23,9 @@
   <property name="wavelet_load_executor_thread_count" value="2" />
   <property name="delta_persist_executor_thread_count" value="2" />
   <property name="disable_registration" value="false" />
+  <property name="enable_ssl" value="false" />
+  <property name="ssl_keystore_path" value="./wiab.ks" />
+  <property name="ssl_keystore_password" value="" />
 
 
   <!-- Properties for server.federation.config -->
@@ -85,6 +88,9 @@
           <token key="WAVELET_LOAD_EXECUTOR_THREAD_COUNT" 
value="${wavelet_load_executor_thread_count}" />
           <token key="DELTA_PERSIST_EXECUTOR_THREAD_COUNT" 
value="${delta_persist_executor_thread_count}" />
           <token key="DISABLE_REGISTRATION" value="${disable_registration}" />
+          <token key="ENABLE_SSL" value="${enable_ssl}" />
+          <token key="SSL_KEYSTORE_PATH" value="${ssl_keystore_path}" />
+          <token key="SSL_KEYSTORE_PASSWORD" value="${ssl_keystore_password}" 
/>"
         </replacetokens>
       </filterchain>
     </copy>

Modified: incubator/wave/trunk/server.config.example
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/server.config.example?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- incubator/wave/trunk/server.config.example (original)
+++ incubator/wave/trunk/server.config.example Mon Feb  6 18:45:52 2012
@@ -114,3 +114,12 @@ waveserver_disable_signer_verification =
 # When true, only the admin user can use the RegistrationRobot to add new 
accounts
 # Default value: false
 disable_registration = @DISABLE_REGISTRATION@
+
+# Enable SSL for all address/port combinations listed (makes the next 2 
settings non-optional)
+enable_ssl = @ENABLE_SSL@
+
+# Path to keystore containg the ssl certificates to server
+ssl_keystore_path = @SSL_KEYSTORE_PATH@
+
+#Password to the keystore
+ssl_keystore_password = @SSL_KEYSTORE_PASSWORD@

Modified: incubator/wave/trunk/src/org/waveprotocol/box/server/CoreSettings.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/CoreSettings.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- incubator/wave/trunk/src/org/waveprotocol/box/server/CoreSettings.java 
(original)
+++ incubator/wave/trunk/src/org/waveprotocol/box/server/CoreSettings.java Mon 
Feb  6 18:45:52 2012
@@ -54,6 +54,9 @@ public class CoreSettings {
   public static final String WAVELET_LOAD_EXECUTOR_THREAD_COUNT = 
"wavelet_load_executor_thread_count";
   public static final String DELTA_PERSIST_EXECUTOR_THREAD_COUNT = 
"delta_persist_executor_thread_count";
   public static final String DISABLE_REGISTRATION = "disable_registration";
+  public static final String ENABLE_SSL = "enable_ssl";
+  public static final String SSL_KEYSTORE_PATH = "ssl_keystore_path";
+  public static final String SSL_KEYSTORE_PASSWORD = "ssl_keystore_password";
 
   @Setting(name = WAVE_SERVER_DOMAIN)
   private static String waveServerDomain;
@@ -171,8 +174,19 @@ public class CoreSettings {
       defaultValue = "2")
   private static int deltaPersistExecutorThreadCount;
 
-
   @Setting(name = DISABLE_REGISTRATION,
       description = "Prevents the register page from being available to 
anyone", defaultValue = "false")
   private static boolean disableRegistration;
+
+  @Setting(name = ENABLE_SSL,
+      description = "Enables SSL protocol on all address/port combinations", 
defaultValue = "false")
+  private static boolean enableSsl;
+
+  @Setting(name = SSL_KEYSTORE_PATH,
+      description = "Path to the keystore containing SSL certificase to 
server", defaultValue = "./wiab.ks")
+  private static String sslKeystorePath;
+
+  @Setting(name = SSL_KEYSTORE_PASSWORD,
+      description = "Password to the SSL keystore", defaultValue = "")
+  private static String sslKeystorePassword;
 }

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java
 (original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java
 Mon Feb  6 18:45:52 2012
@@ -1,164 +1,170 @@
-/**
- * Copyright 2011 Google Inc.
- *
- * 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
- *
- *      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.
- *
- */
-
-package org.waveprotocol.box.server.robots.agent;
-
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.name.Named;
-import com.google.inject.name.Names;
-import com.google.wave.api.AbstractRobot;
-
-import org.waveprotocol.box.server.CoreSettings;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import org.waveprotocol.box.server.robots.register.RobotRegistrar;
-import 
org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException;
-import org.waveprotocol.wave.model.id.TokenGenerator;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * The base for robot agents that run on the WIAB server.
- *
- * @author [email protected] (Yuri Zelikov)
- */
-@SuppressWarnings("serial")
-public abstract class AbstractBaseRobotAgent extends AbstractRobot {
-
-  public static class ServerFrontendAddressHolder {
-
-    private final List<String> addresses;
-
-    @Inject
-    ServerFrontendAddressHolder(
-        @Named(CoreSettings.HTTP_FRONTEND_ADDRESSES) List<String> addresses) {
-      this.addresses = addresses;
-    }
-
-    public List<String> getAddresses() {
-      return addresses;
-    }
-  }
-
-  public static final String AGENT_PREFIX_URI = "/agent";
-  private static final Logger LOG = 
Logger.getLogger(AbstractBaseRobotAgent.class.getName());
-
-  /** The wave server domain. */
-  private final String waveDomain;
-
-  /** Account store with user and robot accounts. */
-  private final AccountStore accountStore;
-
-  /** The robot registrar. */
-  private final RobotRegistrar robotRegistrar;
-
-  private final ServerFrontendAddressHolder frontendAddressHolder;
-
-  /**
-   * Constructor. Initializes the agent to serve on the URI provided by
-   * {@link #getRobotUri()} and ensures that the agent is registered in the
-   * Account store.
-   *
-   * @param injector the injector instance.
-   */
-  public AbstractBaseRobotAgent(Injector injector) {
-    this(injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WAVE_SERVER_DOMAIN))),
-        injector.getInstance(TokenGenerator.class), injector
-            .getInstance(ServerFrontendAddressHolder.class), injector
-            .getInstance(AccountStore.class), 
injector.getInstance(RobotRegistrar.class));
-  }
-
-  /**
-   * Constructor. Initializes the agent to serve on the URI provided by
-   * {@link #getRobotUri()} and ensures that the agent is registered in the
-   * Account store.
-   */
-  AbstractBaseRobotAgent(String waveDomain, TokenGenerator tokenGenerator,
-      ServerFrontendAddressHolder frontendAddressHolder, AccountStore 
accountStore,
-      RobotRegistrar robotRegistator) {
-    this.waveDomain = waveDomain;
-    this.frontendAddressHolder = frontendAddressHolder;
-    this.robotRegistrar = robotRegistator;
-    this.accountStore = accountStore;
-    ensureRegistered(tokenGenerator, getFrontEndAddress());
-  }
-
-  /**
-   * Ensures that the robot agent is registered in the {@link AccountStore}.
-   */
-  private void ensureRegistered(TokenGenerator tokenGenerator, String 
serverFrontendAddress) {
-    ParticipantId robotId = null;
-    try {
-      robotId = ParticipantId.of(getRobotId() + "@" + waveDomain);
-    } catch (InvalidParticipantAddress e) {
-      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
-      return;
-    }
-    try {
-      String location = "http://"; + serverFrontendAddress + getRobotUri();
-      // In order to re-register the agents if the server frontend address has 
changed.
-      robotRegistrar.registerOrUpdate(robotId, location);
-
-    } catch (RobotRegistrationException e) {
-      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
-    } catch (PersistenceException e) {
-      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
-    }
-  }
-
-  @Override
-  protected String getRobotProfilePageUrl() {
-    return null;
-  }
-
-  /**
-   * Returns the wave domain.
-   */
-  public String getWaveDomain() {
-    return waveDomain;
-  }
-
-  /**
-   * Returns the front end address.
-   */
-  public String getFrontEndAddress() {
-    return frontendAddressHolder.getAddresses().get(0);
-  }
-
-  /**
-   * Returns the account store.
-   */
-  protected AccountStore getAccountStore() {
-    return accountStore;
-  }
-
-  /**
-   * Returns the robot URI.
-   */
-  public abstract String getRobotUri();
-
-  /**
-   * Returns the robot participant id.
-   */
-  public abstract String getRobotId();
-}
+/**
+ * Copyright 2011 Google Inc.
+ *
+ * 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
+ *
+ *      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.
+ *
+ */
+
+package org.waveprotocol.box.server.robots.agent;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
+import com.google.wave.api.AbstractRobot;
+
+import org.waveprotocol.box.server.CoreSettings;
+import org.waveprotocol.box.server.persistence.AccountStore;
+import org.waveprotocol.box.server.persistence.PersistenceException;
+import org.waveprotocol.box.server.robots.register.RobotRegistrar;
+import 
org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException;
+import org.waveprotocol.wave.model.id.TokenGenerator;
+import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
+import org.waveprotocol.wave.model.wave.ParticipantId;
+
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * The base for robot agents that run on the WIAB server.
+ *
+ * @author [email protected] (Yuri Zelikov)
+ */
+@SuppressWarnings("serial")
+public abstract class AbstractBaseRobotAgent extends AbstractRobot {
+
+  public static class ServerFrontendAddressHolder {
+
+    private final List<String> addresses;
+
+    @Inject
+    ServerFrontendAddressHolder(
+        @Named(CoreSettings.HTTP_FRONTEND_ADDRESSES) List<String> addresses) {
+      this.addresses = addresses;
+    }
+
+    public List<String> getAddresses() {
+      return addresses;
+    }
+  }
+
+  public static final String AGENT_PREFIX_URI = "/agent";
+  private static final Logger LOG = 
Logger.getLogger(AbstractBaseRobotAgent.class.getName());
+
+  /** The wave server domain. */
+  private final String waveDomain;
+
+  /** Account store with user and robot accounts. */
+  private final AccountStore accountStore;
+
+  /** SSL enabled flag? */
+  private final Boolean isSSLEnabled;
+
+  /** The robot registrar. */
+  private final RobotRegistrar robotRegistrar;
+
+  private final ServerFrontendAddressHolder frontendAddressHolder;
+
+  /**
+   * Constructor. Initializes the agent to serve on the URI provided by
+   * {@link #getRobotUri()} and ensures that the agent is registered in the
+   * Account store.
+   *
+   * @param injector the injector instance.
+   */
+  public AbstractBaseRobotAgent(Injector injector) {
+    this(injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WAVE_SERVER_DOMAIN))),
+        injector.getInstance(TokenGenerator.class), injector
+            .getInstance(ServerFrontendAddressHolder.class), injector
+            .getInstance(AccountStore.class), 
injector.getInstance(RobotRegistrar.class),
+        injector.getInstance(Key.get(Boolean.class, 
Names.named(CoreSettings.ENABLE_SSL))));
+  }
+
+  /**
+   * Constructor. Initializes the agent to serve on the URI provided by
+   * {@link #getRobotUri()} and ensures that the agent is registered in the
+   * Account store.
+   */
+  AbstractBaseRobotAgent(String waveDomain, TokenGenerator tokenGenerator,
+      ServerFrontendAddressHolder frontendAddressHolder, AccountStore 
accountStore,
+      RobotRegistrar robotRegistator, Boolean sslEnabled) {
+    this.waveDomain = waveDomain;
+    this.frontendAddressHolder = frontendAddressHolder;
+    this.robotRegistrar = robotRegistator;
+    this.accountStore = accountStore;
+    this.isSSLEnabled = sslEnabled;
+    ensureRegistered(tokenGenerator, getFrontEndAddress());
+  }
+
+  /**
+   * Ensures that the robot agent is registered in the {@link AccountStore}.
+   */
+  private void ensureRegistered(TokenGenerator tokenGenerator, String 
serverFrontendAddress) {
+    ParticipantId robotId = null;
+    try {
+      robotId = ParticipantId.of(getRobotId() + "@" + waveDomain);
+    } catch (InvalidParticipantAddress e) {
+      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
+      return;
+    }
+    try {
+      String location = serverFrontendAddress + getRobotUri();
+      // In order to re-register the agents if the server frontend address has 
changed.
+      robotRegistrar.registerOrUpdate(robotId, location);
+
+    } catch (RobotRegistrationException e) {
+      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
+    } catch (PersistenceException e) {
+      LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e);
+    }
+  }
+
+  @Override
+  protected String getRobotProfilePageUrl() {
+    return null;
+  }
+
+  /**
+   * Returns the wave domain.
+   */
+  public String getWaveDomain() {
+    return waveDomain;
+  }
+
+  /**
+   * Returns the front end address with correct prefix.
+   */
+  public String getFrontEndAddress() {
+    //TODO(alown): should this really only get the first one?
+    return (this.isSSLEnabled ? "https://"; : "http://";) + 
frontendAddressHolder.getAddresses().get(0);
+  }
+
+  /**
+   * Returns the account store.
+   */
+  protected AccountStore getAccountStore() {
+    return accountStore;
+  }
+
+  /**
+   * Returns the robot URI.
+   */
+  public abstract String getRobotUri();
+
+  /**
+   * Returns the robot participant id.
+   */
+  public abstract String getRobotId();
+}

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java
 (original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java
 Mon Feb  6 18:45:52 2012
@@ -1,269 +1,270 @@
-/**
- * Copyright 2011 Google Inc.
- *
- * 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
- *
- *      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.
- *
- */
-
-package org.waveprotocol.box.server.robots.agent;
-
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine;
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.lastEnteredLineOf;
-
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.name.Names;
-import com.google.wave.api.Blip;
-import com.google.wave.api.event.DocumentChangedEvent;
-import com.google.wave.api.event.WaveletSelfAddedEvent;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.PosixParser;
-import org.waveprotocol.box.server.CoreSettings;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.robots.register.RobotRegistrar;
-import org.waveprotocol.box.server.robots.register.RobotRegistrarImpl;
-import org.waveprotocol.wave.model.id.TokenGenerator;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * The base for robot agents that run on the WIAB server and interact with 
users
- * by entering commands as text in the blips.
- *
- * @author [email protected] (Yuri Zelikov)
- */
-@SuppressWarnings("serial")
-public abstract class AbstractCliRobotAgent extends AbstractBaseRobotAgent {
-
-  /** The options for the command. */
-  private final Options options;
-  private final CommandLineParser parser;
-  private final HelpFormatter helpFormatter;
-
-  /**
-   * Constructor. Initializes the agent to serve on the URI provided by
-   * {@link #getRobotUri()} and ensures that the agent is registered in the
-   * Account store.
-   *
-   * @param injector the injector instance.
-   */
-  public AbstractCliRobotAgent(Injector injector) {
-    this(injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WAVE_SERVER_DOMAIN))),
-        injector.getInstance(TokenGenerator.class), injector
-            .getInstance(ServerFrontendAddressHolder.class), injector
-            .getInstance(AccountStore.class), 
injector.getInstance(RobotRegistrarImpl.class));
-  }
-
-  /**
-   * Constructor. Initializes the agent to serve on the URI provided by
-   * {@link #getRobotUri()} and ensures that the agent is registered in the
-   * Account store.
-   */
-  AbstractCliRobotAgent(String waveDomain, TokenGenerator tokenGenerator,
-      ServerFrontendAddressHolder frontendAddressHolder, AccountStore 
accountStore,
-      RobotRegistrar robotRegistrar) {
-    super(waveDomain, tokenGenerator, frontendAddressHolder, accountStore, 
robotRegistrar);
-    parser = new PosixParser();
-    helpFormatter = new HelpFormatter();
-    options = initOptions();
-  }
-
-  /**
-   * Displays a short description when the robot is added to a wave.
-   */
-  @Override
-  public void onWaveletSelfAdded(WaveletSelfAddedEvent event) {
-    String robotAddress = event.getWavelet().getRobotAddress();
-    // Display a short description.
-    appendLine(event.getBlip(), "\n" + robotAddress + ": I am listening.\n" + 
getShortDescription()
-        + "\nFor help type " + "\"" + getCommandName()
-        + " -help\" on a new line and hit \"Enter\".");
-  }
-
-  @Override
-  public void onDocumentChanged(DocumentChangedEvent event) {
-    Blip blip = event.getBlip();
-    String modifiedBy = event.getModifiedBy();
-    CommandLine commandLine = null;
-    try {
-      commandLine = preprocessCommand(blip.getContent());
-    } catch (IllegalArgumentException e) {
-      appendLine(blip, e.getMessage());
-    }
-    if (commandLine != null) {
-      if (commandLine.hasOption("help")
-          // Or if only options.
-          || (commandLine.getArgs().length - commandLine.getOptions().length 
<= 1)) {
-        appendLine(blip, getFullDescription());
-      } else {
-        String robotMessage = maybeExecuteCommand(commandLine, modifiedBy);
-        appendLine(blip, robotMessage);
-      }
-    }
-  }
-
-  /**
-   * Validates and parses the input for the command.
-   *
-   * @param blipContent the blip contents.
-   * @return the command line {@link CommandLine} object with parsed data from
-   *         the blip contents or null in case the content doesn't contain a
-   *         command.
-   * @throws IllegalArgumentException if illegal arguments passed to the
-   *         command.
-   */
-  protected CommandLine preprocessCommand(String blipContent) throws 
IllegalArgumentException {
-    CommandLine commandLine = null;
-    String lastLine = lastEnteredLineOf(blipContent);
-    if (lastLine != null) {
-      try {
-        commandLine = parse(lastLine.split(" "));
-      } catch (ParseException e) {
-        throw new IllegalArgumentException(e);
-      }
-      String[] args = commandLine.getArgs();
-      if (!args[0].equals(getCommandName())) {
-        return null;
-      }
-      int argsNum = args.length - commandLine.getOptions().length - 1;
-      // If there are only options in the command - then it is also invalid and
-      // have to display usage anyway.
-      if ((argsNum > 0)
-          && (argsNum < getMinNumOfArguments() || argsNum > 
getMaxNumOfArguments())) {
-        String message = null;
-        if (getMinNumOfArguments() == getMaxNumOfArguments()) {
-          message =
-            String.format("Invalid number of arguments. Expected: %d , actual: 
%d %s",
-                getMinNumOfArguments(), argsNum, getUsage());
-        } else {
-          message =
-            String.format(
-                "Invalid number of arguments. Expected between %d and %d, 
actual: %d. %s",
-                getMinNumOfArguments(), getMaxNumOfArguments(), argsNum, 
getUsage());
-        }
-        throw new IllegalArgumentException(message);
-      }
-    }
-    return commandLine;
-  }
-
-  @Override
-  protected String getRobotProfilePageUrl() {
-    return null;
-  }
-
-  /**
-   * Returns the command options usage.
-   */
-  public String getUsage() {
-    StringWriter stringWriter = new StringWriter();
-    PrintWriter pw = new PrintWriter(stringWriter);
-    // HelpFormatter doesn't provide other ways to access defaultWidth, so we
-    // forced to access it in a deprecated way.
-    // TODO (user) Update this code to remove access of deprecated fields when
-    // it will be possible.
-    helpFormatter.printHelp(pw, helpFormatter.defaultWidth, getCommandName() + 
" "
-        + getCmdLineSyntax() + " \n", null, options, 
helpFormatter.defaultLeftPad,
-        helpFormatter.defaultDescPad, "", false);
-    pw.flush();
-    String usageStr = stringWriter.toString();
-    return usageStr;
-  }
-
-  /**
-   * Initializes basic options. Override if more options needed.
-   *
-   * @return the command options.
-   */
-  protected Options initOptions() {
-    // Create Options.
-    Options options = new Options();
-    // The robot has only "help" option.
-    @SuppressWarnings("static-access")
-    Option help = OptionBuilder.withDescription("Displays help for the 
command.").create("help");
-    options.addOption(help);
-    return options;
-  }
-
-  protected CommandLine parse(String... args) throws ParseException {
-    return getParser().parse(getOptions(), args);
-  }
-
-  /**
-   * Returns the command line parser.
-   */
-  protected CommandLineParser getParser() {
-    return parser;
-  }
-
-  /**
-   * Returns the command options.
-   */
-  protected Options getOptions() {
-    return options;
-  }
-
-  /**
-   * Attempts to execute the command.
-   *
-   * @param commandLine the commandLine with arguments and/or options entered 
by
-   *        the user.
-   * @param modifiedBy the user that entered the content.
-   * @return the result message: success or failure.
-   */
-  protected abstract String maybeExecuteCommand(CommandLine commandLine, 
String modifiedBy);
-
-  /**
-   * Returns the short description of the robot.
-   */
-  public abstract String getShortDescription();
-
-  /**
-   * Returns the full robot description.
-   */
-  public abstract String getFullDescription();
-
-  /**
-   * Returns the command name for the robot.
-   */
-  public abstract String getCommandName();
-
-  /**
-   * Returns the command line syntax.
-   */
-  public abstract String getCmdLineSyntax();
-
-  /**
-   * Returns the command use example.
-   */
-  public abstract String getExample();
-
-  /**
-   * Returns the minimum number of arguments this command accepts. Should be
-   * greater than zero and less or equal to {@link #getMaxNumOfArguments()}.
-   */
-  public abstract int getMinNumOfArguments();
-
-  /**
-   * Returns the maximum number of arguments this command accepts.
-   */
-  public abstract int getMaxNumOfArguments();
-}
+/**
+ * Copyright 2011 Google Inc.
+ *
+ * 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
+ *
+ *      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.
+ *
+ */
+
+package org.waveprotocol.box.server.robots.agent;
+
+import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine;
+import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.lastEnteredLineOf;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.name.Names;
+import com.google.wave.api.Blip;
+import com.google.wave.api.event.DocumentChangedEvent;
+import com.google.wave.api.event.WaveletSelfAddedEvent;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.waveprotocol.box.server.CoreSettings;
+import org.waveprotocol.box.server.persistence.AccountStore;
+import org.waveprotocol.box.server.robots.register.RobotRegistrar;
+import org.waveprotocol.box.server.robots.register.RobotRegistrarImpl;
+import org.waveprotocol.wave.model.id.TokenGenerator;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * The base for robot agents that run on the WIAB server and interact with 
users
+ * by entering commands as text in the blips.
+ *
+ * @author [email protected] (Yuri Zelikov)
+ */
+@SuppressWarnings("serial")
+public abstract class AbstractCliRobotAgent extends AbstractBaseRobotAgent {
+
+  /** The options for the command. */
+  private final Options options;
+  private final CommandLineParser parser;
+  private final HelpFormatter helpFormatter;
+
+  /**
+   * Constructor. Initializes the agent to serve on the URI provided by
+   * {@link #getRobotUri()} and ensures that the agent is registered in the
+   * Account store.
+   *
+   * @param injector the injector instance.
+   */
+  public AbstractCliRobotAgent(Injector injector) {
+    this(injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WAVE_SERVER_DOMAIN))),
+        injector.getInstance(TokenGenerator.class), injector
+            .getInstance(ServerFrontendAddressHolder.class), injector
+            .getInstance(AccountStore.class), 
injector.getInstance(RobotRegistrarImpl.class),
+        injector.getInstance(Key.get(Boolean.class, 
Names.named(CoreSettings.ENABLE_SSL))));
+  }
+
+  /**
+   * Constructor. Initializes the agent to serve on the URI provided by
+   * {@link #getRobotUri()} and ensures that the agent is registered in the
+   * Account store.
+   */
+  AbstractCliRobotAgent(String waveDomain, TokenGenerator tokenGenerator,
+      ServerFrontendAddressHolder frontendAddressHolder, AccountStore 
accountStore,
+      RobotRegistrar robotRegistrar, Boolean sslEnabled) {
+    super(waveDomain, tokenGenerator, frontendAddressHolder, accountStore, 
robotRegistrar, sslEnabled);
+    parser = new PosixParser();
+    helpFormatter = new HelpFormatter();
+    options = initOptions();
+  }
+
+  /**
+   * Displays a short description when the robot is added to a wave.
+   */
+  @Override
+  public void onWaveletSelfAdded(WaveletSelfAddedEvent event) {
+    String robotAddress = event.getWavelet().getRobotAddress();
+    // Display a short description.
+    appendLine(event.getBlip(), "\n" + robotAddress + ": I am listening.\n" + 
getShortDescription()
+        + "\nFor help type " + "\"" + getCommandName()
+        + " -help\" on a new line and hit \"Enter\".");
+  }
+
+  @Override
+  public void onDocumentChanged(DocumentChangedEvent event) {
+    Blip blip = event.getBlip();
+    String modifiedBy = event.getModifiedBy();
+    CommandLine commandLine = null;
+    try {
+      commandLine = preprocessCommand(blip.getContent());
+    } catch (IllegalArgumentException e) {
+      appendLine(blip, e.getMessage());
+    }
+    if (commandLine != null) {
+      if (commandLine.hasOption("help")
+          // Or if only options.
+          || (commandLine.getArgs().length - commandLine.getOptions().length 
<= 1)) {
+        appendLine(blip, getFullDescription());
+      } else {
+        String robotMessage = maybeExecuteCommand(commandLine, modifiedBy);
+        appendLine(blip, robotMessage);
+      }
+    }
+  }
+
+  /**
+   * Validates and parses the input for the command.
+   *
+   * @param blipContent the blip contents.
+   * @return the command line {@link CommandLine} object with parsed data from
+   *         the blip contents or null in case the content doesn't contain a
+   *         command.
+   * @throws IllegalArgumentException if illegal arguments passed to the
+   *         command.
+   */
+  protected CommandLine preprocessCommand(String blipContent) throws 
IllegalArgumentException {
+    CommandLine commandLine = null;
+    String lastLine = lastEnteredLineOf(blipContent);
+    if (lastLine != null) {
+      try {
+        commandLine = parse(lastLine.split(" "));
+      } catch (ParseException e) {
+        throw new IllegalArgumentException(e);
+      }
+      String[] args = commandLine.getArgs();
+      if (!args[0].equals(getCommandName())) {
+        return null;
+      }
+      int argsNum = args.length - commandLine.getOptions().length - 1;
+      // If there are only options in the command - then it is also invalid and
+      // have to display usage anyway.
+      if ((argsNum > 0)
+          && (argsNum < getMinNumOfArguments() || argsNum > 
getMaxNumOfArguments())) {
+        String message = null;
+        if (getMinNumOfArguments() == getMaxNumOfArguments()) {
+          message =
+            String.format("Invalid number of arguments. Expected: %d , actual: 
%d %s",
+                getMinNumOfArguments(), argsNum, getUsage());
+        } else {
+          message =
+            String.format(
+                "Invalid number of arguments. Expected between %d and %d, 
actual: %d. %s",
+                getMinNumOfArguments(), getMaxNumOfArguments(), argsNum, 
getUsage());
+        }
+        throw new IllegalArgumentException(message);
+      }
+    }
+    return commandLine;
+  }
+
+  @Override
+  protected String getRobotProfilePageUrl() {
+    return null;
+  }
+
+  /**
+   * Returns the command options usage.
+   */
+  public String getUsage() {
+    StringWriter stringWriter = new StringWriter();
+    PrintWriter pw = new PrintWriter(stringWriter);
+    // HelpFormatter doesn't provide other ways to access defaultWidth, so we
+    // forced to access it in a deprecated way.
+    // TODO (user) Update this code to remove access of deprecated fields when
+    // it will be possible.
+    helpFormatter.printHelp(pw, helpFormatter.defaultWidth, getCommandName() + 
" "
+        + getCmdLineSyntax() + " \n", null, options, 
helpFormatter.defaultLeftPad,
+        helpFormatter.defaultDescPad, "", false);
+    pw.flush();
+    String usageStr = stringWriter.toString();
+    return usageStr;
+  }
+
+  /**
+   * Initializes basic options. Override if more options needed.
+   *
+   * @return the command options.
+   */
+  protected Options initOptions() {
+    // Create Options.
+    Options options = new Options();
+    // The robot has only "help" option.
+    @SuppressWarnings("static-access")
+    Option help = OptionBuilder.withDescription("Displays help for the 
command.").create("help");
+    options.addOption(help);
+    return options;
+  }
+
+  protected CommandLine parse(String... args) throws ParseException {
+    return getParser().parse(getOptions(), args);
+  }
+
+  /**
+   * Returns the command line parser.
+   */
+  protected CommandLineParser getParser() {
+    return parser;
+  }
+
+  /**
+   * Returns the command options.
+   */
+  protected Options getOptions() {
+    return options;
+  }
+
+  /**
+   * Attempts to execute the command.
+   *
+   * @param commandLine the commandLine with arguments and/or options entered 
by
+   *        the user.
+   * @param modifiedBy the user that entered the content.
+   * @return the result message: success or failure.
+   */
+  protected abstract String maybeExecuteCommand(CommandLine commandLine, 
String modifiedBy);
+
+  /**
+   * Returns the short description of the robot.
+   */
+  public abstract String getShortDescription();
+
+  /**
+   * Returns the full robot description.
+   */
+  public abstract String getFullDescription();
+
+  /**
+   * Returns the command name for the robot.
+   */
+  public abstract String getCommandName();
+
+  /**
+   * Returns the command line syntax.
+   */
+  public abstract String getCmdLineSyntax();
+
+  /**
+   * Returns the command use example.
+   */
+  public abstract String getExample();
+
+  /**
+   * Returns the minimum number of arguments this command accepts. Should be
+   * greater than zero and less or equal to {@link #getMaxNumOfArguments()}.
+   */
+  public abstract int getMinNumOfArguments();
+
+  /**
+   * Returns the maximum number of arguments this command accepts.
+   */
+  public abstract int getMaxNumOfArguments();
+}

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
 (original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
 Mon Feb  6 18:45:52 2012
@@ -1,124 +1,124 @@
-/**
- * Copyright 2011 Google Inc.
- *
- * 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
- *
- *      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.
- *
- */
-
-package org.waveprotocol.box.server.robots.agent.welcome;
-
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Singleton;
-import com.google.inject.name.Names;
-import com.google.wave.api.Wavelet;
-
-import org.waveprotocol.box.server.CoreSettings;
-import org.waveprotocol.box.server.account.RobotAccountData;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import org.waveprotocol.box.server.robots.agent.AbstractBaseRobotAgent;
-import org.waveprotocol.box.server.robots.agent.passwd.PasswordRobot;
-import org.waveprotocol.box.server.robots.util.RobotsUtil;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.id.WaveId;
-import org.waveprotocol.wave.model.id.WaveletId;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-
-/**
- * The robot that adds a "Welcome" wave to the inbox of new users.
- * 
- * @author [email protected] (Yuri Zelikov)
- */
-@SuppressWarnings("serial")
-@Singleton
-public class WelcomeRobot extends AbstractBaseRobotAgent {
-
-
-  private static final Logger LOG = 
Logger.getLogger(PasswordRobot.class.getName());
-  public static final String ROBOT_URI = AGENT_PREFIX_URI + "/welcome";
-
-  /** The id of the wave that serves as a template for the welcome wave. */
-  private WaveId welcomeWaveId = null;
-
-  @Inject
-  public WelcomeRobot(Injector injector) {
-    super(injector);
-    String welcomeWaveIdStr =
-      injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WELCOME_WAVE_ID)));
-    if (!"UNDEFINED".equals(welcomeWaveIdStr)) {
-      try {
-        welcomeWaveId = WaveId.ofChecked(getWaveDomain(), welcomeWaveIdStr);
-      } catch (InvalidIdException e) {
-        LOG.log(Level.WARNING, "Problem parsing welcome wave id: " + 
welcomeWaveIdStr);
-      }
-    }
-  }
-
-  /**
-   * Greets new users by creating a new wave with welcome message and
-   * adding it to the inbox of the new user.
-   * 
-   * @param id the participant id of the new user.
-   * @throws IOException if there is a problem submitting the new wave.
-   */
-  public void greet(ParticipantId id) throws IOException {
-    Preconditions.checkNotNull(id);
-    RobotAccountData account = null;
-    String rpcUrl = "http://"; + getFrontEndAddress() + "/robot/rpc";
-    try {
-      account =
-        getAccountStore()
-        .getAccount(ParticipantId.ofUnsafe(getRobotId() + "@" + 
getWaveDomain())).asRobot();
-    } catch (PersistenceException e) {
-      LOG.log(Level.WARNING, "Cannot fetch account data for robot id: " + 
getRobotId(), e);
-    }
-    if (account != null) {
-      setupOAuth(account.getId().getAddress(), account.getConsumerSecret(), 
rpcUrl);
-      Wavelet newWelcomeWavelet = newWave(getWaveDomain(), 
Sets.newHashSet(id.getAddress()));
-      if (welcomeWaveId != null) {
-        Wavelet templateWelcomeWavelet =
-          fetchWavelet(welcomeWaveId, WaveletId.of(getWaveDomain(), 
"conv+root"), rpcUrl);
-        RobotsUtil.copyBlipContents(templateWelcomeWavelet.getRootBlip(),
-            newWelcomeWavelet.getRootBlip());
-      } else {
-        appendLine(newWelcomeWavelet.getRootBlip(), "Welcome to " + 
getWaveDomain() + "!");
-      }
-      submit(newWelcomeWavelet, rpcUrl);
-    }
-  }
-
-  @Override
-  public String getRobotUri() {
-    return ROBOT_URI;
-  }
-
-  @Override
-  public String getRobotId() {
-    return "welcome-bot";
-  }
-
-  @Override
-  protected String getRobotName() {
-    return "Welcome-Bot";
-  }
-}
+/**
+ * Copyright 2011 Google Inc.
+ *
+ * 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
+ *
+ *      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.
+ *
+ */
+
+package org.waveprotocol.box.server.robots.agent.welcome;
+
+import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import com.google.wave.api.Wavelet;
+
+import org.waveprotocol.box.server.CoreSettings;
+import org.waveprotocol.box.server.account.RobotAccountData;
+import org.waveprotocol.box.server.persistence.PersistenceException;
+import org.waveprotocol.box.server.robots.agent.AbstractBaseRobotAgent;
+import org.waveprotocol.box.server.robots.agent.passwd.PasswordRobot;
+import org.waveprotocol.box.server.robots.util.RobotsUtil;
+import org.waveprotocol.wave.model.id.InvalidIdException;
+import org.waveprotocol.wave.model.id.WaveId;
+import org.waveprotocol.wave.model.id.WaveletId;
+import org.waveprotocol.wave.model.wave.ParticipantId;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * The robot that adds a "Welcome" wave to the inbox of new users.
+ *
+ * @author [email protected] (Yuri Zelikov)
+ */
+@SuppressWarnings("serial")
+@Singleton
+public class WelcomeRobot extends AbstractBaseRobotAgent {
+
+
+  private static final Logger LOG = 
Logger.getLogger(PasswordRobot.class.getName());
+  public static final String ROBOT_URI = AGENT_PREFIX_URI + "/welcome";
+
+  /** The id of the wave that serves as a template for the welcome wave. */
+  private WaveId welcomeWaveId = null;
+
+  @Inject
+  public WelcomeRobot(Injector injector) {
+    super(injector);
+    String welcomeWaveIdStr =
+      injector.getInstance(Key.get(String.class, 
Names.named(CoreSettings.WELCOME_WAVE_ID)));
+    if (!"UNDEFINED".equals(welcomeWaveIdStr)) {
+      try {
+        welcomeWaveId = WaveId.ofChecked(getWaveDomain(), welcomeWaveIdStr);
+      } catch (InvalidIdException e) {
+        LOG.log(Level.WARNING, "Problem parsing welcome wave id: " + 
welcomeWaveIdStr);
+      }
+    }
+  }
+
+  /**
+   * Greets new users by creating a new wave with welcome message and
+   * adding it to the inbox of the new user.
+   *
+   * @param id the participant id of the new user.
+   * @throws IOException if there is a problem submitting the new wave.
+   */
+  public void greet(ParticipantId id) throws IOException {
+    Preconditions.checkNotNull(id);
+    RobotAccountData account = null;
+    String rpcUrl = getFrontEndAddress() + "/robot/rpc";
+    try {
+      account =
+        getAccountStore()
+        .getAccount(ParticipantId.ofUnsafe(getRobotId() + "@" + 
getWaveDomain())).asRobot();
+    } catch (PersistenceException e) {
+      LOG.log(Level.WARNING, "Cannot fetch account data for robot id: " + 
getRobotId(), e);
+    }
+    if (account != null) {
+      setupOAuth(account.getId().getAddress(), account.getConsumerSecret(), 
rpcUrl);
+      Wavelet newWelcomeWavelet = newWave(getWaveDomain(), 
Sets.newHashSet(id.getAddress()));
+      if (welcomeWaveId != null) {
+        Wavelet templateWelcomeWavelet =
+          fetchWavelet(welcomeWaveId, WaveletId.of(getWaveDomain(), 
"conv+root"), rpcUrl);
+        RobotsUtil.copyBlipContents(templateWelcomeWavelet.getRootBlip(),
+            newWelcomeWavelet.getRootBlip());
+      } else {
+        appendLine(newWelcomeWavelet.getRootBlip(), "Welcome to " + 
getWaveDomain() + "!");
+      }
+      submit(newWelcomeWavelet, rpcUrl);
+    }
+  }
+
+  @Override
+  public String getRobotUri() {
+    return ROBOT_URI;
+  }
+
+  @Override
+  public String getRobotId() {
+    return "welcome-bot";
+  }
+
+  @Override
+  protected String getRobotName() {
+    return "Welcome-Bot";
+  }
+}

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
 (original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
 Mon Feb  6 18:45:52 2012
@@ -28,12 +28,12 @@ import org.waveprotocol.box.server.robot
  * gravatar.com and adding their wave address to the main profile. It is
  * impossible to create a main profile with wave address since gravatar 
requires
  * email address verification.
- * 
+*
  * @author [email protected] (Yuri Zelikov)
  */
 public class GravatarProfilesFetcher implements ProfilesFetcher {
 
-  private static final String GRAVATAR_URL = "http://www.gravatar.com/avatar/";;
+  private static final String GRAVATAR_URL = 
"https://secure.gravatar.com/avatar/";;
 
   public static GravatarProfilesFetcher create() {
     return new GravatarProfilesFetcher();

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/ServerRpcProvider.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/ServerRpcProvider.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/ServerRpcProvider.java 
(original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/ServerRpcProvider.java 
Mon Feb  6 18:45:52 2012
@@ -44,12 +44,15 @@ import com.glines.socketio.server.transp
 import com.glines.socketio.server.transport.XHRPollingTransport;
 import com.glines.socketio.server.transport.jetty.JettyWebSocketTransport;
 
+import org.eclipse.jetty.http.ssl.SslContextFactory;
+import org.eclipse.jetty.server.ssl.SslSocketConnector;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.bio.SocketConnector;
 import org.eclipse.jetty.server.session.HashSessionManager;
 import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlets.GzipFilter;
 import org.eclipse.jetty.util.resource.ResourceCollection;
 import org.eclipse.jetty.webapp.WebAppContext;
 import org.eclipse.jetty.websocket.WebSocket;
@@ -108,6 +111,9 @@ public class ServerRpcProvider {
   private final SessionManager sessionManager;
   private final org.eclipse.jetty.server.SessionManager jettySessionManager;
   private Server httpServer = null;
+  private final boolean sslEnabled;
+  private final String sslKeystorePath;
+  private final String sslKeystorePassword;
 
   // Mapping from incoming protocol buffer type -> specific handler.
   private final Map<Descriptors.Descriptor, RegisteredServiceMethod> 
registeredServices =
@@ -305,7 +311,8 @@ public class ServerRpcProvider {
    */
   public ServerRpcProvider(InetSocketAddress[] httpAddresses, Integer 
flashsocketPolicyPort,
       String[] resourceBases, ExecutorService threadPool, SessionManager 
sessionManager,
-      org.eclipse.jetty.server.SessionManager jettySessionManager, String 
sessionStoreDir) {
+      org.eclipse.jetty.server.SessionManager jettySessionManager, String 
sessionStoreDir,
+      boolean sslEnabled, String sslKeystorePath, String sslKeystorePassword) {
     this.httpAddresses = httpAddresses;
     this.flashsocketPolicyPort = flashsocketPolicyPort;
     this.resourceBases = resourceBases;
@@ -313,6 +320,9 @@ public class ServerRpcProvider {
     this.sessionManager = sessionManager;
     this.jettySessionManager = jettySessionManager;
     this.sessionStoreDir = sessionStoreDir;
+    this.sslEnabled = sslEnabled;
+    this.sslKeystorePath = sslKeystorePath;
+    this.sslKeystorePassword = sslKeystorePassword;
   }
 
   /**
@@ -320,28 +330,35 @@ public class ServerRpcProvider {
    */
   public ServerRpcProvider(InetSocketAddress[] httpAddresses, Integer 
flashsocketPolicyPort,
       String[] resourceBases, SessionManager sessionManager,
-      org.eclipse.jetty.server.SessionManager jettySessionManager, String 
sessionStoreDir) {
+      org.eclipse.jetty.server.SessionManager jettySessionManager, String 
sessionStoreDir,
+      boolean sslEnabled, String sslKeystorePath, String sslKeystorePassword) {
     this(httpAddresses, flashsocketPolicyPort, resourceBases, 
Executors.newCachedThreadPool(),
-        sessionManager, jettySessionManager, sessionStoreDir);
+        sessionManager, jettySessionManager, sessionStoreDir, sslEnabled, 
sslKeystorePath,
+        sslKeystorePassword);
   }
 
   @Inject
   public ServerRpcProvider(@Named(CoreSettings.HTTP_FRONTEND_ADDRESSES) 
List<String> httpAddresses,
       @Named(CoreSettings.FLASHSOCKET_POLICY_PORT) Integer 
flashsocketPolicyPort,
       @Named(CoreSettings.RESOURCE_BASES) List<String> resourceBases,
-      SessionManager sessionManager, org.eclipse.jetty.server.SessionManager 
jettySessionManager, @Named(CoreSettings.SESSIONS_STORE_DIRECTORY) String 
sessionStoreDir) {
+      SessionManager sessionManager, org.eclipse.jetty.server.SessionManager 
jettySessionManager,
+      @Named(CoreSettings.SESSIONS_STORE_DIRECTORY) String sessionStoreDir,
+      @Named(CoreSettings.ENABLE_SSL) boolean sslEnabled,
+      @Named(CoreSettings.SSL_KEYSTORE_PATH) String sslKeystorePath,
+      @Named(CoreSettings.SSL_KEYSTORE_PASSWORD) String sslKeystorePassword) {
     this(parseAddressList(httpAddresses), flashsocketPolicyPort, resourceBases
-        .toArray(new String[0]), sessionManager, jettySessionManager, 
sessionStoreDir);
+        .toArray(new String[0]), sessionManager, jettySessionManager, 
sessionStoreDir,
+        sslEnabled, sslKeystorePath, sslKeystorePassword);
   }
 
   public void startWebSocketServer(final Injector injector) {
     httpServer = new Server();
 
-    List<SelectChannelConnector> connectors = 
getSelectChannelConnectors(httpAddresses);
+    List<SocketConnector> connectors = getSocketConnectors(httpAddresses);
     if (connectors.isEmpty()) {
       LOG.severe("No valid http end point address provided!");
     }
-    for (SelectChannelConnector connector : connectors) {
+    for (SocketConnector connector : connectors) {
       httpServer.addConnector(connector);
     }
     final WebAppContext context = new WebAppContext();
@@ -378,6 +395,7 @@ public class ServerRpcProvider {
 
       context.addEventListener(contextListener);
       context.addFilter(GuiceFilter.class, "/*", 
EnumSet.allOf(DispatcherType.class));
+      context.addFilter(GzipFilter.class, "/webclient/*", 
EnumSet.allOf(DispatcherType.class));
       httpServer.setHandler(context);
 
       httpServer.start();
@@ -492,14 +510,37 @@ public class ServerRpcProvider {
   }
 
   /**
-   * @return a list of {@link SelectChannelConnector} each bound to a host:port
+   * @return a list of {@link SocketConnector} each bound to a host:port
    *         pair form the list addresses.
    */
-  private List<SelectChannelConnector> getSelectChannelConnectors(
+  private List<SocketConnector> getSocketConnectors(
       InetSocketAddress[] httpAddresses) {
-    List<SelectChannelConnector> list = Lists.newArrayList();
+    List<SocketConnector> list = Lists.newArrayList();
+    String[] excludeCiphers = {"SSL_RSA_EXPORT_WITH_RC4_40_MD5", 
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+                               "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 
"SSL_RSA_WITH_DES_CBC_SHA",
+                               "SSL_DHE_RSA_WITH_DES_CBC_SHA", 
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+                               "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA"};
+    SslContextFactory sslContextFactory = null;
+
+    if (sslEnabled) {
+      Preconditions.checkState(sslKeystorePath != null && 
!sslKeystorePath.isEmpty(),
+          "SSL Keystore path left blank");
+      Preconditions.checkState(sslKeystorePassword != null && 
!sslKeystorePassword.isEmpty(),
+          "SSL Keystore password left blank");
+
+      sslContextFactory = new SslContextFactory(sslKeystorePath);
+      sslContextFactory.setKeyStorePassword(sslKeystorePassword);
+      sslContextFactory.setAllowRenegotiate(false);
+      sslContextFactory.setExcludeCipherSuites(excludeCiphers);
+    }
+
     for (InetSocketAddress address : httpAddresses) {
-      SelectChannelConnector connector = new SelectChannelConnector();
+      SocketConnector connector;
+      if (sslEnabled) {
+        connector = new SslSocketConnector(sslContextFactory);
+      } else {
+        connector = new SocketConnector();
+      }
       connector.setHost(address.getAddress().getHostAddress());
       connector.setPort(address.getPort());
       connector.setMaxIdleTime(0);

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/webclient/client/WebClient.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/webclient/client/WebClient.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/webclient/client/WebClient.java 
(original)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/webclient/client/WebClient.java 
Mon Feb  6 18:45:52 2012
@@ -269,10 +269,10 @@ public class WebClient implements EntryP
   }
 
   /**
-   * Returns <code>ws://yourhost[:port]/</code>.
+   * Returns <code>ws(s)://yourhost[:port]/</code>.
    */
   // XXX check formatting wrt GPE
-  private native String getWebSocketBaseUrl(String moduleBase) /*-{return "ws" 
+ /:\/\/[^\/]+/.exec(moduleBase)[0] + "/";}-*/;
+  private native String getWebSocketBaseUrl(String moduleBase) /*-{return 
((window.location.protocol == "https:") ? "wss" : "ws") + 
/:\/\/[^\/]+/.exec(moduleBase)[0] + "/";}-*/;
 
   private native boolean useSocketIO() /*-{ return !window.WebSocket }-*/;
 

Modified: 
incubator/wave/trunk/test/org/waveprotocol/box/server/robots/agent/AbstractRobotAgentTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/test/org/waveprotocol/box/server/robots/agent/AbstractRobotAgentTest.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- 
incubator/wave/trunk/test/org/waveprotocol/box/server/robots/agent/AbstractRobotAgentTest.java
 (original)
+++ 
incubator/wave/trunk/test/org/waveprotocol/box/server/robots/agent/AbstractRobotAgentTest.java
 Mon Feb  6 18:45:52 2012
@@ -43,8 +43,8 @@ public class AbstractRobotAgentTest exte
 
     public FakeRobotAgent(String waveDomain, TokenGenerator tokenGenerator,
         ServerFrontendAddressHolder frontendAddressHolder, AccountStore 
accountStore,
-        RobotRegistrar registrar) {
-      super(waveDomain, tokenGenerator, frontendAddressHolder, accountStore, 
registrar);
+        RobotRegistrar registrar, Boolean sslEnabled) {
+      super(waveDomain, tokenGenerator, frontendAddressHolder, accountStore, 
registrar, sslEnabled);
     }
 
     @Override
@@ -122,7 +122,7 @@ public class AbstractRobotAgentTest exte
     RobotRegistrar registar = mock(RobotRegistrar.class);
     agent =
         new FakeRobotAgent("example.com", tokenGenerator, 
frontendAddressHolder, accountStore,
-            registar);
+            registar, false);
   }
 
   public void testPreprocessCommandValidInput() throws Exception {

Modified: incubator/wave/trunk/test/org/waveprotocol/box/server/rpc/RpcTest.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/test/org/waveprotocol/box/server/rpc/RpcTest.java?rev=1241106&r1=1241105&r2=1241106&view=diff
==============================================================================
--- incubator/wave/trunk/test/org/waveprotocol/box/server/rpc/RpcTest.java 
(original)
+++ incubator/wave/trunk/test/org/waveprotocol/box/server/rpc/RpcTest.java Mon 
Feb  6 18:45:52 2012
@@ -68,7 +68,7 @@ public class RpcTest extends TestCase {
      */
     server =
         new ServerRpcProvider(new InetSocketAddress[] {new 
InetSocketAddress("localhost", 0)}, 0,
-            new String[] {"./war"}, sessionManager, null, null);
+            new String[] {"./war"}, sessionManager, null, null, false, null, 
null);
     Injector injector = Guice.createInjector(new AbstractModule() {
       @Override
       protected void configure() {


Reply via email to