http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java 
b/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java
deleted file mode 100644
index a2a0daf..0000000
--- a/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.agent.passwd;
-
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.CANNOT_CHANGE_PASSWORD_FOR_USER;
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.changeUserPassword;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Singleton;
-
-import org.apache.commons.cli.CommandLine;
-import org.eclipse.jetty.util.MultiMap;
-import 
org.waveprotocol.box.server.authentication.HttpRequestBasedCallbackHandler;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import org.waveprotocol.box.server.robots.agent.AbstractCliRobotAgent;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-/**
- * Robot agent that allows a user to change her own password. The userId should
- * be from this wave domain.
- * 
- * When the robot is added to a wave, it prints basic description and then
- * inspects text entered by the user. When a new line char is entered it scans
- * the last line of the text in the blip and parses it using Apache CLI command
- * line interpreter. If the command found to be valid, the robot validates user
- * credentials and then changes the password of the user to a new one.
- * 
- * @author [email protected] (Yuri Zelikov)
- */
-@SuppressWarnings("serial")
-@Singleton
-public final class PasswordRobot extends AbstractCliRobotAgent {
-
-  private static final Logger LOG = 
Logger.getLogger(PasswordRobot.class.getName());
-  public static final String ROBOT_URI = AGENT_PREFIX_URI + "/passwd/user";
-
-  /** Configuration for the LoginContext. */
-  private final Configuration configuration;
-  
-  @Inject
-  public PasswordRobot(Injector injector) {
-    super(injector);
-    configuration = injector.getInstance(Configuration.class);
-  }
-
-  @Override
-  protected String maybeExecuteCommand(CommandLine commandLine, String 
modifiedBy) {
-    String robotMessage = null;
-    // Get the user that wants to change her own password.
-    if (!modifiedBy.endsWith("@" + getWaveDomain())) {
-      // Can change passwords only for users on this wave domain.
-      robotMessage =
-          String.format("User %s does not belong to the @%s domain\n", 
modifiedBy,
-              getWaveDomain());
-    } else {
-      String[] args = commandLine.getArgs();
-      try {
-        ParticipantId participantId = ParticipantId.of(modifiedBy);
-        if (args.length == 2) {
-          // If current password is empty, i.e. "", then user should pass
-          // only the new password.
-          args = Arrays.copyOf(args, 3);
-          args[2] = args[1];
-          args[1] = "";
-        }
-        String oldPassword = args[1];
-        String newPassword = args[2];
-        verifyCredentials(oldPassword, participantId);
-        changeUserPassword(newPassword, participantId, getAccountStore());
-        robotMessage =
-            String.format("Changed password for user %s, the new password is: 
%s", modifiedBy,
-                newPassword);
-        LOG.info(modifiedBy + " changed  password for user: " + modifiedBy);
-      } catch (IllegalArgumentException e) {
-        robotMessage = e.getMessage();
-        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
-      } catch (PersistenceException e) {
-        robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy;
-        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
-      } catch (InvalidParticipantAddress e) {
-        robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy;
-        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
-      } catch (LoginException e) {
-        robotMessage =
-            CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy
-                + ". Please verify your old password";
-        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
-      }
-    }
-    return robotMessage;
-  }
-
-  /**
-   * Verifies user credentials.
-   * 
-   * @param oldPassword the password to verify.
-   * @param participantId the participantId of the user.
-   * @throws LoginException if the user provided incorrect password.
-   */
-  private void verifyCredentials(String password, ParticipantId participantId)
-      throws LoginException {
-    MultiMap<String> parameters = new MultiMap<String>();
-    parameters.putAllValues(ImmutableMap.of("password", password, "address", 
participantId.getAddress()));
-    CallbackHandler callbackHandler = new 
HttpRequestBasedCallbackHandler(parameters);
-    LoginContext context = new LoginContext("Wave", new Subject(), 
callbackHandler, configuration);
-    // If authentication fails, login() will throw a LoginException.
-    context.login();
-  }
-
-  @Override
-  public String getFullDescription() {
-    return getShortDescription() + " If your password is empty - enter only 
the new password.\n"
-        + getUsage() + "\nExample: " + getCommandName() + " " + getExample();
-  }
-
-  @Override
-  public String getCmdLineSyntax() {
-    return "[OPTIONS] [OLD_PASSWORD] [NEW_PASSWORD]";
-  }
-
-  @Override
-  public String getExample() {
-    return "old_password new_password";
-  }
-
-  @Override
-  public String getShortDescription() {
-    return "The command allows users to change their own password. "
-    + "Please make sure to use it in a wave without other participants. "
-    + "It is also advised to remove yourself from the wave "
-    + "when you finished changing the password.";
-  }
-
-  @Override
-  public String getCommandName() {
-    return "passwd";
-  }
-
-  @Override
-  public String getRobotName() {
-    return "Passwd-Bot";
-  }
-
-  @Override
-  public int getMinNumOfArguments() {
-    return 1;
-  }
-  
-  @Override
-  public int getMaxNumOfArguments() {
-    return 2;
-  }
-  
-  @Override
-  public String getRobotUri() {
-    return ROBOT_URI;
-  }
-  
-  @Override
-  public String getRobotId() {
-    return "passwd-bot";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java
 
b/src/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java
deleted file mode 100644
index cbf3332..0000000
--- 
a/src/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.agent.registration;
-
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Singleton;
-import com.typesafe.config.Config;
-import org.apache.commons.cli.CommandLine;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import org.waveprotocol.box.server.robots.agent.AbstractCliRobotAgent;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.CANNOT_CREATE_USER;
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.createUser;
-
-/**
- * Robot agent that handles the user registration by an admin
- *
- * @author [email protected] (Ali Lown)
- */
-@SuppressWarnings("serial")
-@Singleton
-public final class RegistrationRobot extends AbstractCliRobotAgent {
-
-  private static final Logger LOG = 
Logger.getLogger(RegistrationRobot.class.getName());
-  public static final String ROBOT_URI = AGENT_PREFIX_URI + 
"/registration/admin";
-
-  /** The address of the admin user as defined in the server configuration. */
-  private final String serverAdminId;
-
-  /** Account store with user and robot accounts. */
-  private final AccountStore accountStore;
-
-  @Inject
-  public RegistrationRobot(Injector injector) {
-    super(injector);
-    serverAdminId =
-        
injector.getInstance(Config.class).getString("administration.admin_user");
-    accountStore = injector.getInstance(AccountStore.class);
-  }
-
-  @Override
-  protected String maybeExecuteCommand(CommandLine commandLine, String 
modifiedBy) {
-    String robotMessage;
-    // Verify that the user that attempts to create a user has admin 
privileges.
-    if (!modifiedBy.equals(serverAdminId)) {
-      robotMessage =
-          "User " + modifiedBy + " is not authorized to use " + 
getCommandName() + " command.";
-    } else {
-      String userId = null;
-      try {
-        String[] args = commandLine.getArgs();
-        userId = args[1];
-        String password = args[2];
-        // Add domain to the user id if needed.
-        userId = userId + (userId.contains("@") ? "" : "@" + getWaveDomain());
-        ParticipantId participantId = ParticipantId.of(userId);
-        createUser(accountStore, participantId, password);
-        robotMessage = String.format("Created user %s, the password is: %s\n", 
userId, password);
-        LOG.log(Level.INFO, "Created user " + userId + " by " + modifiedBy);
-      } catch (IllegalArgumentException e) {
-        LOG.log(Level.SEVERE, userId, e);
-        robotMessage = e.getMessage();
-      } catch (PersistenceException | InvalidParticipantAddress e) {
-        robotMessage = CANNOT_CREATE_USER + userId;
-        LOG.log(Level.SEVERE, "userId: " + userId, e);
-      }
-    }
-
-    return robotMessage;
-  }
-
-  @Override
-  public int getMinNumOfArguments() {
-    return 2;
-  }
-
-  @Override
-  public int getMaxNumOfArguments() {
-    return 2;
-  }
-
-  @Override
-  public String getCommandName() {
-    return "register";
-  }
-
-  @Override
-  public String getFullDescription() {
-    return getShortDescription() + "\n" + getUsage() + "\nExample: " + 
getCommandName() + " "
-        + getExample();
-  }
-
-  @Override
-  public String getCmdLineSyntax() {
-    return "[OPTIONS] [USERNAME] [PASSWORD]";
-  }
-
-  @Override
-  public String getExample() {
-    return "user_id password";
-  }
-
-  @Override
-  public String getShortDescription() {
-    return "The command allows the admin to register other users. "
-    + "Please make sure to use it in a wave without other participants. "
-    + "It is also advised to remove yourself from the wave "
-    + "when you finished creating users.";
-  }
-
-  @Override
-  public String getRobotName() {
-    return "Registration-Bot";
-  }
-
-  @Override
-  public String getRobotUri() {
-    return ROBOT_URI;
-  }
-
-  @Override
-  public String getRobotId() {
-    return "registration-bot";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java 
b/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
deleted file mode 100755
index fddab5a..0000000
--- a/src/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.agent.welcome;
-
-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.Singleton;
-import com.google.wave.api.Wavelet;
-import com.typesafe.config.Config;
-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.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;
-
-import static 
org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine;
-
-
-/**
- * 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(WelcomeRobot.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(Config.class).getString("administration.welcome_wave_id");
-    if (!"".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";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/dataapi/BaseApiServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/dataapi/BaseApiServlet.java 
b/src/org/waveprotocol/box/server/robots/dataapi/BaseApiServlet.java
deleted file mode 100644
index 6ddf7b4..0000000
--- a/src/org/waveprotocol/box/server/robots/dataapi/BaseApiServlet.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.dataapi;
-
-import com.google.common.collect.Lists;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcResponse;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.ProtocolVersion;
-import com.google.wave.api.RobotSerializer;
-import com.google.wave.api.data.converter.EventDataConverterManager;
-import com.google.wave.api.impl.GsonFactory;
-
-import net.oauth.OAuthAccessor;
-import net.oauth.OAuthException;
-import net.oauth.OAuthMessage;
-import net.oauth.OAuthValidator;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.OperationContextImpl;
-import org.waveprotocol.box.server.robots.OperationResults;
-import org.waveprotocol.box.server.robots.OperationServiceRegistry;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.robots.util.LoggingRequestListener;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URISyntaxException;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * The base {@link HttpServlet} for {@link DataApiServlet} and
- * {@link ActiveApiServlet}.
- * 
- * @author [email protected] (Lennard de Rijk)
- * @author [email protected] (Yuri Z.)
- */
-@SuppressWarnings("serial")
-public abstract class BaseApiServlet extends HttpServlet {
-
-  private static final Log LOG = Log.get(BaseApiServlet.class);
-  private static final WaveletProvider.SubmitRequestListener 
LOGGING_REQUEST_LISTENER =
-      new LoggingRequestListener(LOG);
-  private static final String JSON_CONTENT_TYPE = "application/json";
-
-  private final RobotSerializer robotSerializer;
-  private final EventDataConverterManager converterManager;
-  private final WaveletProvider waveletProvider;
-  private final OperationServiceRegistry operationRegistry;
-  private final ConversationUtil conversationUtil;
-  private final OAuthValidator validator;
-  
-  /** Holds incoming operation requests. */
-  private List<OperationRequest> operations;
-
-  public BaseApiServlet(RobotSerializer robotSerializer,
-      EventDataConverterManager converterManager, WaveletProvider 
waveletProvider,
-      OperationServiceRegistry operationRegistry, ConversationUtil 
conversationUtil,
-      OAuthValidator validator) {
-    this.robotSerializer = robotSerializer;
-    this.converterManager = converterManager;
-    this.waveletProvider = waveletProvider;
-    this.conversationUtil = conversationUtil;
-    this.operationRegistry = operationRegistry;
-    this.validator = validator;
-  }
-
-  /**
-   *  Validates OAUTH and executes operations.
-   * 
-   * @param req the request.
-   * @param resp the response.
-   * @param message the OAUTH message.
-   * @param accessor the OAUTH accessor.
-   * @param participant the author for which to perform the robot operations.
-   * @throws IOException if encountered errors during writing of a response.
-   */
-  protected final void processOpsRequest(HttpServletRequest req, 
HttpServletResponse resp, OAuthMessage message,
-      OAuthAccessor accessor, ParticipantId participant) throws IOException {
-    try {
-      validator.validateMessage(message, accessor);
-    } catch (OAuthException e) {
-      LOG.info("The message does not conform to OAuth", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    } catch (URISyntaxException e) {
-      LOG.info("The message URL is invalid", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    }
-
-    String apiRequest;
-    try {
-      // message.readBodyAsString() doesn't work due to a NPE in the OAuth
-      // libraries.
-      BufferedReader reader = req.getReader();
-      apiRequest = reader.readLine();
-    } catch (IOException e) {
-      LOG.warning("Unable to read the incoming request", e);
-      throw e;
-    }
-
-    LOG.info("Received the following Json: " + apiRequest);
-    try {
-      operations = robotSerializer.deserializeOperations(apiRequest);
-    } catch (InvalidRequestException e) {
-      LOG.info("Unable to parse Json to list of OperationRequests: " + 
apiRequest);
-      resp.sendError(HttpServletResponse.SC_BAD_REQUEST,
-          "Unable to parse Json to list of OperationRequests: " + apiRequest);
-      return;
-    }
-
-    // Create an unbound context.
-    ProtocolVersion version = OperationUtil.getProtocolVersion(operations);
-    OperationContextImpl context = new OperationContextImpl(
-        waveletProvider, converterManager.getEventDataConverter(version), 
conversationUtil);
-
-    executeOperations(context, operations, participant);
-    handleResults(context, resp, version);
-  }
-
-  /**
-   * Executes operations in the given context.
-   *
-   * @param context the context to perform the operations in.
-   * @param operations the operations to perform.
-   * @param author the author for which to perform the robot operations.
-   */
-  private void executeOperations(
-      OperationContext context, List<OperationRequest> operations, 
ParticipantId author) {
-    for (OperationRequest operation : operations) {
-      OperationUtil.executeOperation(operation, operationRegistry, context, 
author);
-    }
-  }
-
-  /**
-   * Handles an {@link OperationResults} by submitting the deltas that are
-   * generated and writing a response to the robot.
-   *
-   * @param results the results of the operations performed.
-   * @param resp the servlet to write the response in.
-   * @param version the version of the protocol to use for writing a response.
-   * @throws IOException if the response can not be written.
-   */
-  private void handleResults(
-      OperationResults results, HttpServletResponse resp, ProtocolVersion 
version)
-      throws IOException {
-    OperationUtil.submitDeltas(results, waveletProvider, 
LOGGING_REQUEST_LISTENER);
-    
-    // Ensure that responses are returned in the same order as corresponding
-    // requests.
-    LinkedList<JsonRpcResponse> responses = Lists.newLinkedList();
-    for (OperationRequest operation : operations) {
-      String opId = operation.getId();
-      JsonRpcResponse response = results.getResponses().get(opId);
-      responses.addLast(response);
-    }
-
-    String jsonResponse =
-        robotSerializer.serialize(responses, 
GsonFactory.JSON_RPC_RESPONSE_LIST_TYPE, version);
-    LOG.info("Returning the following Json: " + jsonResponse);
-
-    // Write the response back through the HttpServlet
-    try {
-      resp.setContentType(JSON_CONTENT_TYPE);
-      PrintWriter writer = resp.getWriter();
-      writer.append(jsonResponse);
-      writer.flush();
-      resp.setStatus(HttpServletResponse.SC_OK);
-    } catch (IOException e) {
-      LOG.severe("IOException during writing of a response", e);
-      throw e;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/dataapi/DataApiOAuthServlet.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/dataapi/DataApiOAuthServlet.java 
b/src/org/waveprotocol/box/server/robots/dataapi/DataApiOAuthServlet.java
deleted file mode 100644
index 6c31853..0000000
--- a/src/org/waveprotocol/box/server/robots/dataapi/DataApiOAuthServlet.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.dataapi;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.cache.CacheBuilder;
-import com.google.gxp.base.GxpContext;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-
-import net.oauth.OAuth;
-import net.oauth.OAuthAccessor;
-import net.oauth.OAuthConsumer;
-import net.oauth.OAuthException;
-import net.oauth.OAuthMessage;
-import net.oauth.OAuthProblemException;
-import net.oauth.OAuthServiceProvider;
-import net.oauth.OAuthValidator;
-import net.oauth.server.HttpRequestMessage;
-
-import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.gxp.OAuthAuthorizeTokenPage;
-import org.waveprotocol.wave.model.id.TokenGenerator;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.box.server.gxp.OAuthAuthorizationCodePage;
-import org.waveprotocol.wave.model.util.CharBase64;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Singleton;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Servlet responsible for the 3-legged OAuth dance required for the Data api.
- *
- * @author [email protected] (Lennard de Rijk)
- * @author [email protected] (A. Kaplanov)
- */
-@SuppressWarnings("serial")
-@Singleton
-public class DataApiOAuthServlet extends HttpServlet {
-
-  public static final String DATA_API_OAUTH_PATH = "/robot/dataapi/oauth";
-  private static final Log LOG = Log.get(DataApiOAuthServlet.class);
-  private static final String ANONYMOUS_TOKEN = "anonymous";
-  private static final String ANONYMOUS_TOKEN_SECRET = "anonymous";
-  private static final String HTML_CONTENT_TYPE = "text/html";
-  private static final String PLAIN_CONTENT_TYPE = "text/plain";
-  private static final int TOKEN_LENGTH = 8;
-  private static final int XSRF_TOKEN_TIMEOUT_HOURS = 12;
-
-  private final String requestTokenPath;
-  private final String authorizeTokenPath;
-  private final String accessTokenPath;
-  private final String allTokensPath;
-  private final OAuthServiceProvider serviceProvider;
-  private final OAuthValidator validator;
-  private final DataApiTokenContainer tokenContainer;
-  private final SessionManager sessionManager;
-  private final TokenGenerator tokenGenerator;
-  // TODO(ljvderijk): We should refactor this and use it for our other pages.
-  private final ConcurrentMap<ParticipantId, String> xsrfTokens;
-
-  @Inject
-  public DataApiOAuthServlet(@Named("request_token_path") String 
requestTokenPath,
-      @Named("authorize_token_path") String authorizeTokenPath,
-      @Named("access_token_path") String accessTokenPath,
-      @Named("all_tokens_path") String allTokensPath,
-      OAuthServiceProvider serviceProvider,
-      OAuthValidator validator, DataApiTokenContainer tokenContainer,
-      SessionManager sessionManager, TokenGenerator tokenGenerator) {
-    this.requestTokenPath = requestTokenPath;
-    this.authorizeTokenPath = authorizeTokenPath;
-    this.accessTokenPath = accessTokenPath;
-    this.allTokensPath = allTokensPath;
-    this.serviceProvider = serviceProvider;
-    this.validator = validator;
-    this.tokenContainer = tokenContainer;
-    this.sessionManager = sessionManager;
-    this.tokenGenerator = tokenGenerator;
-    this.xsrfTokens =
-        CacheBuilder.newBuilder()
-          .expireAfterWrite(XSRF_TOKEN_TIMEOUT_HOURS, TimeUnit.HOURS)
-          .<ParticipantId, String>build().asMap();
-  }
-
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    routeRequest(req, resp);
-  }
-
-
-  @Override
-  protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    routeRequest(req, resp);
-  }
-
-  /** Routes all requests to the appropriate handler */
-  private void routeRequest(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    String pathInfo = req.getPathInfo();
-    if (pathInfo.equals(requestTokenPath)) {
-      doRequestToken(req, resp);
-    } else if (pathInfo.equals(authorizeTokenPath)) {
-      doAuthorizeToken(req, resp);
-    } else if (pathInfo.equals(accessTokenPath)) {
-      doExchangeToken(req, resp);
-    } else if (pathInfo.equals(allTokensPath)) {
-      doAllTokens(req, resp);
-    } else {
-      resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
-    }
-  }
-
-  /**
-   * Handles the request to get a new unauthorized request token.
-   */
-  private void doRequestToken(HttpServletRequest req, HttpServletResponse 
resp) throws IOException {
-    OAuthMessage message = new HttpRequestMessage(req, 
req.getRequestURL().toString());
-
-    // Anyone can generate a request token.
-    OAuthConsumer consumer =
-        new OAuthConsumer("", ANONYMOUS_TOKEN, ANONYMOUS_TOKEN_SECRET, 
serviceProvider);
-    OAuthAccessor accessor = new OAuthAccessor(consumer);
-    try {
-      validator.validateMessage(message, accessor);
-    } catch (OAuthException e) {
-      LOG.info("The message does not conform to OAuth", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    } catch (URISyntaxException e) {
-      LOG.info("The message URL is invalid", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    }
-
-    accessor = tokenContainer.generateRequestToken(consumer);
-
-    resp.setContentType(OAuth.FORM_ENCODED);
-    ServletOutputStream out = resp.getOutputStream();
-    OAuth.formEncode(OAuth.newList(
-        OAuth.OAUTH_TOKEN, accessor.requestToken,
-        OAuth.OAUTH_TOKEN_SECRET, accessor.tokenSecret,
-        OAuth.OAUTH_CALLBACK_CONFIRMED, "true"),
-        out);
-    out.close();
-    resp.setStatus(HttpServletResponse.SC_OK);
-  }
-
-  /**
-   * Handles the request to authorize a token. Checks if the user is logged in,
-   * if not the user is redirected to the login page.
-   *
-   * <p>
-   * If it is a GET request the user will be asked whether permission should be
-   * given. For a POST request we will handle the user's decision.
-   */
-  private void doAuthorizeToken(HttpServletRequest req, HttpServletResponse 
resp)
-      throws IOException {
-    // Check if the OAuth parameters are present, even if we don't use them
-    // during a GET request.
-    OAuthMessage message = new HttpRequestMessage(req, 
req.getRequestURL().toString());
-    try {
-      message.requireParameters(OAuth.OAUTH_CALLBACK, OAuth.OAUTH_TOKEN);
-    } catch (OAuthProblemException e) {
-      LOG.info("Parameter absent", e);
-      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
-      return;
-    }
-
-    // Check if the user is logged in, else redirect to login.
-    ParticipantId user = sessionManager.getLoggedInUser(req.getSession(false));
-    if (user == null) {
-      resp.sendRedirect(sessionManager.getLoginUrl(
-          DATA_API_OAUTH_PATH + authorizeTokenPath + "?" + 
req.getQueryString()));
-      return;
-    }
-
-    // Check if the request token is valid, note that this doesn't hold after
-    // the call to the container since the token might time out.
-    try {
-      tokenContainer.getRequestTokenAccessor(message.getToken());
-    } catch (OAuthProblemException e) {
-      LOG.info("Trying to load a non existing token for authorization", e);
-      resp.sendError(e.getHttpStatusCode(), e.getMessage());
-      return;
-    }
-
-    if (req.getMethod().equals("GET")) {
-      doAuthorizeTokenGet(req, resp, user);
-    } else if (req.getMethod().equals("POST")) {
-      doAuthorizeTokenPost(req, resp, user, message);
-    } else {
-      throw new IllegalStateException(
-          "This method shouldn't be called outside GET or POST requests");
-    }
-  }
-
-  /**
-   * Handles the GET request to authorize a token by displaying the page asking
-   * for user's permission.
-   *
-   * @param req {@link HttpServletRequest} received.
-   * @param resp {@link HttpServletResponse} to write the response in.
-   * @param user User who wants to authorize the token.
-   */
-  private void doAuthorizeTokenGet(
-      HttpServletRequest req, HttpServletResponse resp, ParticipantId user) 
throws IOException {
-    Preconditions.checkNotNull(user, "User must be supplied");
-    // Ask the user for permission.
-    OAuthAuthorizeTokenPage.write(resp.getWriter(), new 
GxpContext(req.getLocale()),
-        user.getAddress(), getOrGenerateXsrfToken(user));
-    resp.setContentType(HTML_CONTENT_TYPE);
-    resp.setStatus(HttpServletResponse.SC_OK);
-    return;
-  }
-
-  /**
-   * Method that handles the POST request for the authorize token page. The
-   * token will be rejected if the user pressed the cancel button. Otherwise 
the
-   * token will be authorized.
-   *
-   * @param req {@link HttpServletRequest} received.
-   * @param resp {@link HttpServletResponse} to write the response in.
-   * @param user user who is authorizing the token.
-   * @param message the {@link OAuthMessage} present in the request.
-   */
-  private void doAuthorizeTokenPost(
-      HttpServletRequest req, HttpServletResponse resp, ParticipantId user, 
OAuthMessage message)
-      throws IOException {
-    Preconditions.checkNotNull(user, "User must be supplied");
-
-    // Check the XSRF token.
-    if (Strings.isNullOrEmpty(req.getParameter("token"))
-        || !req.getParameter("token").equals(xsrfTokens.get(user))) {
-      LOG.warning(
-          "Request without a valid  xsrf token received from " + 
req.getRemoteAddr() + " for user "
-              + user);
-      resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid XSRF 
token");
-      return;
-    }
-    // Check whether the user agreed to give access.
-    if (req.getParameter("cancel") != null) {
-      try {
-        tokenContainer.rejectRequestToken(message.getToken());
-      } catch (OAuthProblemException e) {
-        LOG.info("Rejecting a request token failed", e);
-        resp.sendError(e.getHttpStatusCode(), e.getMessage());
-        return;
-      }
-      resp.setContentType(PLAIN_CONTENT_TYPE);
-      resp.getWriter().append("No access granted, you can now close this 
page.");
-      resp.setStatus(HttpServletResponse.SC_OK);
-      return;
-    } else if (req.getParameter("agree") == null) {
-      // User did not agree nor disagree, bad request.
-      LOG.warning(
-          "Bad request when authorzing a token from " + req.getRemoteAddr() + 
" for user " + user);
-      resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-      return;
-    }
-
-    // Authorize the token.
-    OAuthAccessor accessor;
-    try {
-      accessor = tokenContainer.authorizeRequestToken(message.getToken(), 
user);
-    } catch (OAuthProblemException e) {
-      LOG.info("Authorizing a request token failed", e);
-      resp.sendError(e.getHttpStatusCode(), e.getMessage());
-      return;
-    }
-
-    // Create the callback url and send the user to it
-    String callback = message.getParameter(OAuth.OAUTH_CALLBACK);
-    callback = OAuth.addParameters(callback, OAuth.OAUTH_TOKEN, 
accessor.requestToken);
-    resp.sendRedirect(callback);
-  }
-
-  /**
-   * Exchanges an authorized request token with an access token.
-   */
-  private void doExchangeToken(HttpServletRequest req, HttpServletResponse 
resp)
-      throws IOException {
-    OAuthMessage message = new HttpRequestMessage(req, 
req.getRequestURL().toString());
-
-    String requestToken = message.getToken();
-    OAuthAccessor accessor;
-    try {
-      accessor = tokenContainer.getRequestTokenAccessor(requestToken);
-    } catch (OAuthProblemException e) {
-      LOG.info("Request token unknown", e);
-      resp.sendError(e.getHttpStatusCode(), e.getMessage());
-      return;
-    }
-
-    try {
-      validator.validateMessage(message, accessor);
-    } catch (OAuthException e) {
-      LOG.info("The message does not conform to OAuth", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    } catch (URISyntaxException e) {
-      LOG.info("The message URL is invalid", e);
-      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-      return;
-    }
-
-    OAuthAccessor authorizedAccessor;
-    try {
-      authorizedAccessor = 
tokenContainer.generateAccessToken(accessor.requestToken);
-    } catch (OAuthProblemException e) {
-      LOG.info("Request token unknown", e);
-      resp.sendError(e.getHttpStatusCode(), e.getMessage());
-      return;
-    }
-
-    resp.setContentType(OAuth.FORM_ENCODED);
-    ServletOutputStream out = resp.getOutputStream();
-    OAuth.formEncode(OAuth.newList(
-        OAuth.OAUTH_TOKEN, authorizedAccessor.accessToken,
-        OAuth.OAUTH_TOKEN_SECRET, authorizedAccessor.tokenSecret,
-        OAuth.OAUTH_CALLBACK_CONFIRMED, "true"),
-        out);
-    out.close();
-    resp.setStatus(HttpServletResponse.SC_OK);
-  }
-
-  /**
-   * Perform full Auth dance and print tokens.
-   */
-  private void doAllTokens(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    OAuthMessage message = new HttpRequestMessage(req, 
req.getRequestURL().toString());
-    String requestToken = message.getToken();
-    if (requestToken == null) {
-      OAuthConsumer consumer =
-          new OAuthConsumer("", ANONYMOUS_TOKEN, ANONYMOUS_TOKEN_SECRET, 
serviceProvider);
-      OAuthAccessor accessor = tokenContainer.generateRequestToken(consumer);
-      String url = accessor.consumer.serviceProvider.userAuthorizationURL
-          + "?oauth_token=" + accessor.requestToken + "&oauth_callback="
-          + req.getRequestURL().toString() + "&hd=default";
-      resp.sendRedirect(url);
-    } else {
-      OAuthAccessor accessor;
-      try {
-        accessor = tokenContainer.getRequestTokenAccessor(requestToken);
-      } catch (OAuthProblemException e) {
-        LOG.info("Request token unknown", e);
-        resp.sendError(e.getHttpStatusCode(), e.getMessage());
-        return;
-      }
-      OAuthAccessor authorizedAccessor;
-      try {
-        authorizedAccessor = 
tokenContainer.generateAccessToken(accessor.requestToken);
-      } catch (OAuthProblemException e) {
-        LOG.info("Request token unknown", e);
-        resp.sendError(e.getHttpStatusCode(), e.getMessage());
-        return;
-      }
-      String authorizationCode = authorizedAccessor.requestToken + " "
-          + authorizedAccessor.accessToken + " " + 
authorizedAccessor.tokenSecret;
-      String base64AuthCode = CharBase64.encode(authorizationCode.getBytes());
-      OAuthAuthorizationCodePage.write(resp.getWriter(), new 
GxpContext(req.getLocale()),
-          base64AuthCode);
-      resp.setContentType(HTML_CONTENT_TYPE);
-      resp.setStatus(HttpServletResponse.SC_OK);
-    }
-  }
-
-  /**
-   * Gets or generates an XSRF token for the given user.
-   *
-   * <p>
-   * XSRF is an attack where, for instance, another web site makes the user's
-   * browser do a POST request to authorize a request token. Because the user's
-   * browser might contain an valid login cookie for "Wave in a Box" this would
-   * succeed. By adding a hidden field on each form with a random token and
-   * checking the presence of this token the attack can be countered because 
the
-   * attacker does not know the token.
-   *
-   * @param user the user to generate a token for.
-   */
-  @VisibleForTesting
-  String getOrGenerateXsrfToken(ParticipantId user) {
-    String token = tokenGenerator.generateToken(TOKEN_LENGTH);
-    String previousToken = xsrfTokens.putIfAbsent(user, token);
-    if (previousToken != null) {
-      token = previousToken;
-    }
-    return token;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/dataapi/DataApiOperationServiceRegistry.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/dataapi/DataApiOperationServiceRegistry.java
 
b/src/org/waveprotocol/box/server/robots/dataapi/DataApiOperationServiceRegistry.java
deleted file mode 100644
index cfaf64a..0000000
--- 
a/src/org/waveprotocol/box/server/robots/dataapi/DataApiOperationServiceRegistry.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.dataapi;
-
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.wave.api.OperationType;
-
-import org.waveprotocol.box.server.robots.AbstractOperationServiceRegistry;
-import org.waveprotocol.box.server.robots.operations.*;
-
-/**
- * A registry of {@link OperationService}s for the data API.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public final class DataApiOperationServiceRegistry extends 
AbstractOperationServiceRegistry {
-  // Suppressing warnings about operations that are deprecated but still used 
by
-  // the default client libraries
-  @SuppressWarnings("deprecation")
-  @Inject
-  public DataApiOperationServiceRegistry(Injector injector) {
-    super();
-
-    // Register all the OperationProviders
-    register(OperationType.ROBOT_NOTIFY, DoNothingService.create());
-    register(OperationType.ROBOT_NOTIFY_CAPABILITIES_HASH, 
DoNothingService.create());
-    register(OperationType.WAVELET_ADD_PARTICIPANT_NEWSYNTAX, 
ParticipantServices.create());
-    register(OperationType.WAVELET_APPEND_BLIP, 
BlipOperationServices.create());
-    register(OperationType.WAVELET_REMOVE_PARTICIPANT_NEWSYNTAX, 
ParticipantServices.create());
-    register(OperationType.BLIP_CONTINUE_THREAD, 
BlipOperationServices.create());
-    register(OperationType.BLIP_CREATE_CHILD, BlipOperationServices.create());
-    register(OperationType.BLIP_DELETE, BlipOperationServices.create());
-    register(OperationType.DOCUMENT_APPEND_INLINE_BLIP, 
BlipOperationServices.create());
-    register(OperationType.DOCUMENT_APPEND_MARKUP, 
BlipOperationServices.create());
-    register(OperationType.DOCUMENT_INSERT_INLINE_BLIP, 
BlipOperationServices.create());
-    register(
-        OperationType.DOCUMENT_INSERT_INLINE_BLIP_AFTER_ELEMENT, 
BlipOperationServices.create());
-    register(OperationType.ROBOT_CREATE_WAVELET, 
CreateWaveletService.create());
-    register(OperationType.ROBOT_FETCH_WAVE, FetchWaveService.create());
-    register(OperationType.DOCUMENT_MODIFY, DocumentModifyService.create());
-    register(OperationType.ROBOT_SEARCH, 
injector.getInstance(SearchService.class));
-    register(OperationType.WAVELET_SET_TITLE, WaveletSetTitleService.create());
-    register(OperationType.ROBOT_FOLDER_ACTION, FolderActionService.create());
-    register(OperationType.ROBOT_FETCH_PROFILES, 
injector.getInstance(FetchProfilesService.class));
-    register(OperationType.ROBOT_EXPORT_SNAPSHOT, 
ExportSnapshotService.create());
-    register(OperationType.ROBOT_EXPORT_DELTAS, ExportDeltasService.create());
-    register(OperationType.ROBOT_EXPORT_ATTACHMENT, 
injector.getInstance(ExportAttachmentService.class));
-    register(OperationType.ROBOT_IMPORT_DELTAS, 
injector.getInstance(ImportDeltasService.class));
-    register(OperationType.ROBOT_IMPORT_ATTACHMENT, 
injector.getInstance(ImportAttachmentService.class));
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/dataapi/DataApiServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/dataapi/DataApiServlet.java 
b/src/org/waveprotocol/box/server/robots/dataapi/DataApiServlet.java
deleted file mode 100644
index 18743b5..0000000
--- a/src/org/waveprotocol/box/server/robots/dataapi/DataApiServlet.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.dataapi;
-
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import com.google.wave.api.RobotSerializer;
-import com.google.wave.api.data.converter.EventDataConverterManager;
-
-import net.oauth.OAuth;
-import net.oauth.OAuthAccessor;
-import net.oauth.OAuthMessage;
-import net.oauth.OAuthProblemException;
-import net.oauth.OAuthValidator;
-import net.oauth.server.HttpRequestMessage;
-
-import org.waveprotocol.box.server.robots.OperationServiceRegistry;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.io.IOException;
-
-import javax.inject.Singleton;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * {@link HttpServlet} that serves as the endpoint for the Data Api.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-@SuppressWarnings("serial")
-@Singleton
-public class DataApiServlet extends BaseApiServlet {
-
-  private static final Log LOG = Log.get(DataApiServlet.class);
-  private final DataApiTokenContainer tokenContainer;
-  
-  @Inject
-  public DataApiServlet(RobotSerializer robotSerializer,
-      EventDataConverterManager converterManager, WaveletProvider 
waveletProvider,
-      @Named("DataApiRegistry") OperationServiceRegistry operationRegistry,
-      ConversationUtil conversationUtil, OAuthValidator validator,
-      DataApiTokenContainer tokenContainer) {
-    super(robotSerializer, converterManager, waveletProvider, 
operationRegistry, conversationUtil,
-        validator);
-    this.tokenContainer = tokenContainer;
-  }
-  
-  /**
-   * Entry point for the Data API Calls.
-   */
-  @Override
-  protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    OAuthMessage message = new HttpRequestMessage(req, 
req.getRequestURL().toString());
-
-    OAuthAccessor accessor;
-    try {
-      message.requireParameters(OAuth.OAUTH_TOKEN);
-      accessor = 
tokenContainer.getAccessTokenAccessor(message.getParameter(OAuth.OAUTH_TOKEN));
-    } catch (OAuthProblemException e) {
-      LOG.info("No valid OAuth token present", e);
-      // Have to set status here manually, cannot use e.getHttpStatusCode
-      // because message.requireParameters doesn't set it in the exception.
-      resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
-      return;
-    }
-    ParticipantId participant =
-        (ParticipantId) 
accessor.getProperty(DataApiTokenContainer.USER_PROPERTY_NAME);
-    
-    processOpsRequest(req, resp, message, accessor, participant);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/dataapi/DataApiTokenContainer.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/dataapi/DataApiTokenContainer.java 
b/src/org/waveprotocol/box/server/robots/dataapi/DataApiTokenContainer.java
deleted file mode 100644
index 6032088..0000000
--- a/src/org/waveprotocol/box/server/robots/dataapi/DataApiTokenContainer.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.dataapi;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.MapMaker;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-import net.oauth.OAuth;
-import net.oauth.OAuthAccessor;
-import net.oauth.OAuthConsumer;
-import net.oauth.OAuthProblemException;
-
-import org.waveprotocol.box.server.util.OAuthUtil;
-import org.waveprotocol.wave.model.id.TokenGenerator;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Container to handle request and access tokens for the Data Api.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-@Singleton
-public final class DataApiTokenContainer {
-
-  private static final Log LOG = Log.get(DataApiTokenContainer.class);
-
-  /** Length of a token in number of characters */
-  private static final int TOKEN_LENGTH = 48;
-
-  /** Number of minutes a request token is valid */
-  private static final int REQUEST_TOKEN_EXPIRATION = 10;
-
-  /**
-   * Number of minutes an access token is valid, public so this can be shown to
-   * the user
-   */
-  public static final int ACCESS_TOKEN_EXPIRATION = 60;
-  public static final String USER_PROPERTY_NAME = "user";
-
-  /** Map containing unauthorized accessors indexed on their request token */
-  private ConcurrentMap<String, OAuthAccessor> requestTokenAccessors;
-
-  /** Map containing the authorized accessors indexed on the access token */
-  private ConcurrentMap<String, OAuthAccessor> accessTokenAccessors;
-
-  /** Used to generate OAuth tokens */
-  private final TokenGenerator tokenGenerator;
-
-  @Inject
-  @VisibleForTesting
-  DataApiTokenContainer(TokenGenerator tokenGenerator) {
-    this.tokenGenerator = tokenGenerator;
-
-    requestTokenAccessors =
-        CacheBuilder.newBuilder().expireAfterWrite(REQUEST_TOKEN_EXPIRATION, 
TimeUnit.MINUTES)
-        .<String, OAuthAccessor>build().asMap();
-    accessTokenAccessors =
-        CacheBuilder.newBuilder().expireAfterWrite(ACCESS_TOKEN_EXPIRATION, 
TimeUnit.MINUTES)
-        .<String, OAuthAccessor>build().asMap();
-  }
-
-  /**
-   * Gets the {@link OAuthAccessor} that is identified by the given request
-   * token. Any changes made to the accessor's fields, except the consumer, 
will
-   * not be reflected in this container.
-   *
-   * @param requestToken the request token used for identification.
-   * @throws OAuthProblemException if the token does not map to an accessor.
-   */
-  public OAuthAccessor getRequestTokenAccessor(String requestToken) throws 
OAuthProblemException {
-    OAuthAccessor accessor = requestTokenAccessors.get(requestToken);
-    if (accessor == null) {
-      OAuthProblemException exception =
-          OAuthUtil.newOAuthProblemException(OAuth.Problems.TOKEN_REJECTED);
-      exception.setParameter(OAuth.OAUTH_TOKEN, requestToken);
-      throw exception;
-    }
-    return accessor.clone();
-  }
-
-  /**
-   * Gets the authorized {@link OAuthAccessor} that is identified by the given
-   * access token. Any changes made to the accessor's fields, except the
-   * consumer, will not be reflected in this container.
-   *
-   * @param accessToken the access token used for identification.
-   * @throws OAuthProblemException if the token does not map to an accessor.
-   */
-  public OAuthAccessor getAccessTokenAccessor(String accessToken) throws 
OAuthProblemException {
-    OAuthAccessor accessor = accessTokenAccessors.get(accessToken);
-    if (accessor == null) {
-      OAuthProblemException exception =
-          OAuthUtil.newOAuthProblemException(OAuth.Problems.TOKEN_REJECTED);
-      exception.setParameter(OAuth.OAUTH_TOKEN, accessToken);
-      throw exception;
-    }
-    return accessor.clone();
-  }
-
-  /**
-   * Generates a new request token for the given {@link OAuthConsumer}.
-   *
-   * @param consumer the consumer to generate the token for.
-   */
-  public OAuthAccessor generateRequestToken(OAuthConsumer consumer) {
-    Preconditions.checkNotNull(consumer, "Consumer must not be null");
-
-    // Accessor can be generated up front with a token secret that does not 
need
-    // to be unique.
-    OAuthAccessor accessor = new OAuthAccessor(consumer);
-    accessor.tokenSecret = generateToken();
-
-    do {
-      accessor.requestToken = generateToken();
-    } while (requestTokenAccessors.putIfAbsent(accessor.requestToken, 
accessor) != null);
-
-    return accessor.clone();
-  }
-
-  /**
-   * Authorizes a request token to be exchanged for an access token.
-   *
-   * @param requestToken the request token used for identification.
-   * @param user the user that has authorized the token.
-   * @throws OAuthProblemException if the request token does not map to an
-   *         accessor or if the token was already used.
-   */
-  public OAuthAccessor authorizeRequestToken(String requestToken, 
ParticipantId user)
-      throws OAuthProblemException {
-    Preconditions.checkNotNull(user, "User must not be null");
-
-    OAuthAccessor accessor = getRequestTokenAccessor(requestToken);
-
-    if (accessor.getProperty(USER_PROPERTY_NAME) != null) {
-      throw OAuthUtil.newOAuthProblemException(OAuth.Problems.TOKEN_USED);
-    }
-
-    accessor.setProperty(USER_PROPERTY_NAME, user);
-    requestTokenAccessors.put(requestToken, accessor);
-
-    LOG.info("Authorized request token for " + user);
-    return accessor.clone();
-  }
-
-  /**
-   * Rejects authorization of a request token.
-   *
-   * @param requestToken the request token used for identification.
-   * @throws OAuthProblemException if the request token does not map to an
-   *         accessor or if the token was already used.
-   */
-  public void rejectRequestToken(String requestToken) throws 
OAuthProblemException {
-    OAuthAccessor accessor = getRequestTokenAccessor(requestToken);
-
-    if (accessor.getProperty(USER_PROPERTY_NAME) != null) {
-      throw OAuthUtil.newOAuthProblemException(OAuth.Problems.TOKEN_USED);
-    }
-
-    // Can't use remove(String, OAuthAccessor) since equals is not defined.
-    requestTokenAccessors.remove(requestToken);
-    LOG.info("Rejected request token " + requestToken);
-  }
-
-  /**
-   * Authorize the {@link OAuthAccessor} by generating a new access token and
-   * token secret.
-   *
-   * @param requestToken the requestToken used for identifying the accessor 
that
-   *        needs to be authorized.
-   * @return a new {@link OAuthAccessor} with the access token and token secret
-   *         set.
-   * @throws OAuthProblemException if the request token in the accessor is not
-   *         known.
-   */
-  public OAuthAccessor generateAccessToken(String requestToken) throws 
OAuthProblemException {
-    OAuthAccessor accessor = getRequestTokenAccessor(requestToken);
-
-    if (accessor.getProperty(USER_PROPERTY_NAME) == null) {
-      // User has not given the consumer permission yet.
-      throw 
OAuthUtil.newOAuthProblemException(OAuth.Problems.PERMISSION_UNKNOWN);
-    }
-
-    // Token secret does not need to unique so can be generated now.
-    accessor.tokenSecret = generateToken();
-
-    do {
-      accessor.accessToken = generateToken();
-    } while (accessTokenAccessors.putIfAbsent(accessor.accessToken, accessor) 
!= null);
-    requestTokenAccessors.remove(accessor.requestToken);
-
-    LOG.info("Generated access token for " + 
accessor.getProperty(USER_PROPERTY_NAME));
-    return accessor.clone();
-  }
-
-  /**
-   * Generates an OAuth token.
-   */
-  private String generateToken() {
-    return tokenGenerator.generateToken(TOKEN_LENGTH);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/operations/BlipOperationServices.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/operations/BlipOperationServices.java 
b/src/org/waveprotocol/box/server/robots/operations/BlipOperationServices.java
deleted file mode 100644
index 767d7f9..0000000
--- 
a/src/org/waveprotocol/box/server/robots/operations/BlipOperationServices.java
+++ /dev/null
@@ -1,425 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.BlipData;
-import com.google.wave.api.Element;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.OperationType;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.data.ApiView;
-import com.google.wave.api.event.WaveletBlipCreatedEvent;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.conversation.ConversationBlip;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.conversation.ObservableConversationBlip;
-import org.waveprotocol.wave.model.conversation.ObservableConversationView;
-import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
-import org.waveprotocol.wave.model.document.Doc;
-import org.waveprotocol.wave.model.document.Document;
-import org.waveprotocol.wave.model.document.util.LineContainers;
-import org.waveprotocol.wave.model.document.util.Point;
-import org.waveprotocol.wave.model.document.util.XmlStringBuilder;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.wave.ObservableWavelet;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-
-/**
- * {@link OperationService} for methods that create or deletes a blip.
- *
- * <p>
- * These methods are:
- * <li>{@link OperationType#BLIP_CONTINUE_THREAD}</li>
- * <li>{@link OperationType#BLIP_CREATE_CHILD}</li>
- * <li>{@link OperationType#WAVELET_APPEND_BLIP}</li>
- * <li>{@link OperationType#DOCUMENT_APPEND_INLINE_BLIP}</li>
- * <li>{@link OperationType#DOCUMENT_APPEND_MARKUP}</li>
- * <li>{@link OperationType#DOCUMENT_INSERT_INLINE_BLIP}</li>
- * <li>{@link OperationType#DOCUMENT_INSERT_INLINE_BLIP_AFTER_ELEMENT}</li>
- * <li>{@link OperationType#BLIP_DELETE}</li>.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public class BlipOperationServices implements OperationService {
-
-  private BlipOperationServices() {
-  }
-
-  @Override
-  public void execute(
-      OperationRequest operation, OperationContext context, ParticipantId 
participant)
-      throws InvalidRequestException {
-    OpBasedWavelet wavelet = context.openWavelet(operation, participant);
-    ObservableConversationView conversationView = 
context.openConversation(operation, participant);
-
-    String waveletId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.WAVELET_ID);
-    String conversationId;
-
-    try {
-      // TODO(anorth): Remove this round-trip when the API instead talks about
-      // opaque conversation ids, and doesn't use legacy id serialization.
-      conversationId = WaveletBasedConversation.idFor(
-          ApiIdSerializer.instance().deserialiseWaveletId(waveletId));
-    } catch (InvalidIdException e) {
-      throw new InvalidRequestException("Invalid conversation id", operation, 
e);
-    }
-    ObservableConversation conversation = 
conversationView.getConversation(conversationId);
-
-    OperationType type = OperationUtil.getOperationType(operation);
-    switch (type) {
-      case BLIP_CONTINUE_THREAD:
-        continueThread(operation, context, participant, conversation);
-        break;
-      case BLIP_CREATE_CHILD:
-        createChild(operation, context, participant, conversation);
-        break;
-      case WAVELET_APPEND_BLIP:
-        appendBlip(operation, context, participant, conversation);
-        break;
-      case DOCUMENT_APPEND_INLINE_BLIP:
-        appendInlineBlip(operation, context, participant, wavelet, 
conversation);
-        break;
-      case DOCUMENT_APPEND_MARKUP:
-        appendMarkup(operation, context, participant, wavelet, conversation);
-        break;
-      case DOCUMENT_INSERT_INLINE_BLIP:
-        insertInlineBlip(operation, context, participant, wavelet, 
conversation);
-        break;
-      case DOCUMENT_INSERT_INLINE_BLIP_AFTER_ELEMENT:
-        insertInlineBlipAfterElement(operation, context, participant, wavelet, 
conversation);
-        break;
-      case BLIP_DELETE:
-        delete(operation, context, participant, conversation);
-        break;
-      default:
-        throw new UnsupportedOperationException(
-            "This OperationService does not implement operation of type " + 
type.method());
-    }
-  }
-
-  /**
-   * Implementation of the {@link OperationType#BLIP_CONTINUE_THREAD} method. 
It
-   * appends a new blip to the end of the thread of the blip specified in the
-   * operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void continueThread(OperationRequest operation, OperationContext 
context,
-      ParticipantId participant, ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.BLIP_CONTINUE_THREAD,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-    String parentBlipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip parentBlip = context.getBlip(conversation, parentBlipId);
-
-    ConversationBlip newBlip = parentBlip.getThread().appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation of the {@link OperationType#BLIP_CREATE_CHILD} method. It
-   * appends a new reply thread to the blip specified in the operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void createChild(OperationRequest operation, OperationContext 
context,
-      ParticipantId participant, ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.BLIP_CREATE_CHILD,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-    String parentBlipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip parentBlip = context.getBlip(conversation, parentBlipId);
-
-    ConversationBlip newBlip = parentBlip.addReplyThread().appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation for the {@link OperationType#WAVELET_APPEND_BLIP} method. 
It
-   * appends a blip at the end of the root thread.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void appendBlip(OperationRequest operation, OperationContext context,
-      ParticipantId participant, ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.WAVELET_APPEND_BLIP,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-
-    ObservableConversationBlip newBlip = 
conversation.getRootThread().appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation for the {@link OperationType#DOCUMENT_APPEND_INLINE_BLIP}
-   * method. It appends an inline blip on a new line in the blip specified in
-   * the operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param wavelet the wavelet to operate on.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void appendInlineBlip(OperationRequest operation, OperationContext 
context,
-      ParticipantId participant, ObservableWavelet wavelet, 
ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.DOCUMENT_APPEND_INLINE_BLIP,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-    String parentBlipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip parentBlip = context.getBlip(conversation, parentBlipId);
-
-    // Append a new, empty line to the doc for the inline anchor.
-    Document doc = parentBlip.getContent();
-    Doc.E line = LineContainers.appendLine(doc, 
XmlStringBuilder.createEmpty());
-
-    // Insert new inline thread with the blip at the empty sentence.
-    int location = doc.getLocation(Point.after(doc, line));
-    ConversationBlip newBlip = 
parentBlip.addReplyThread(location).appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation for the {@link OperationType#DOCUMENT_APPEND_MARKUP}
-   * method. It appends markup within the blip specified in
-   * the operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param wavelet the wavelet to operate on.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void appendMarkup(OperationRequest operation, OperationContext 
context,
-      ParticipantId participant, ObservableWavelet wavelet, 
ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.DOCUMENT_APPEND_MARKUP,
-        "Unsupported operation " + operation);
-
-    String content = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.CONTENT);
-    String blipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip convBlip = context.getBlip(conversation, blipId);
-
-    // Create builder from xml content.
-    XmlStringBuilder markupBuilder = 
XmlStringBuilder.createFromXmlString(content);
-
-    // Append the new markup to the blip doc.
-    Document doc = convBlip.getContent();
-    LineContainers.appendLine(doc, markupBuilder);
-
-    // Report success.
-    context.constructResponse(operation, Maps.<ParamsProperty, Object> 
newHashMap());
-  }
-
-  /**
-   * Implementation for the {@link OperationType#DOCUMENT_INSERT_INLINE_BLIP}
-   * method. It inserts an inline blip at the location specified in the
-   * operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param wavelet the wavelet to operate on.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void insertInlineBlip(OperationRequest operation, OperationContext 
context,
-      ParticipantId participant, ObservableWavelet wavelet, 
ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == 
OperationType.DOCUMENT_INSERT_INLINE_BLIP,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-    String parentBlipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip parentBlip = context.getBlip(conversation, parentBlipId);
-
-    Integer index = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.INDEX);
-    if (index <= 0) {
-      throw new InvalidRequestException(
-          "Can't inline a blip on position <= 0, got " + index, operation);
-    }
-
-    ApiView view = new ApiView(parentBlip.getContent(), wavelet);
-    int xmlLocation = view.transformToXmlOffset(index);
-
-    // Insert new inline thread with the blip at the location as specified.
-    ConversationBlip newBlip = 
parentBlip.addReplyThread(xmlLocation).appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation for the
-   * {@link OperationType#DOCUMENT_INSERT_INLINE_BLIP_AFTER_ELEMENT} method. It
-   * inserts an inline blip after the element specified in the operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param wavelet the wavelet to operate on.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void insertInlineBlipAfterElement(OperationRequest operation, 
OperationContext context,
-      ParticipantId participant, OpBasedWavelet wavelet, 
ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(OperationUtil.getOperationType(operation)
-        == OperationType.DOCUMENT_INSERT_INLINE_BLIP_AFTER_ELEMENT,
-        "Unsupported operation " + operation);
-
-    BlipData blipData = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_DATA);
-    String parentBlipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    ConversationBlip parentBlip = context.getBlip(conversation, parentBlipId);
-
-    Element element = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.ELEMENT);
-
-    // view.locateElement will tell where the element actually is.
-    ApiView view = new ApiView(parentBlip.getContent(), wavelet);
-    int elementApiLocation = view.locateElement(element);
-
-    if (elementApiLocation == -1) {
-      throw new InvalidRequestException("Requested element not found", 
operation);
-    }
-
-    // Insert just after the requested element
-    int xmlLocation = view.transformToXmlOffset(elementApiLocation + 1);
-
-    // Insert new inline thread with the blip at the location of the element.
-    ConversationBlip newBlip = 
parentBlip.addReplyThread(xmlLocation).appendBlip();
-    context.putBlip(blipData.getBlipId(), newBlip);
-
-    putContentForNewBlip(newBlip, blipData.getContent());
-    processBlipCreatedEvent(operation, context, participant, conversation, 
newBlip);
-  }
-
-  /**
-   * Implementation for the {@link OperationType#BLIP_DELETE} method. It 
deletes
-   * the blip specified in the operation.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @param conversation the conversation to operate on.
-   * @throws InvalidRequestException if the operation fails to perform
-   */
-  private void delete(OperationRequest operation, OperationContext context,
-      ParticipantId participant, ObservableConversation conversation)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        OperationUtil.getOperationType(operation) == OperationType.BLIP_DELETE,
-        "Unsupported operation " + operation);
-
-    String blipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-    context.getBlip(conversation, blipId).delete();
-    // report success.
-    context.constructResponse(operation, Maps.<ParamsProperty, Object> 
newHashMap());
-  }
-
-  /**
-   * Inserts content into the new blip.
-   *
-   * @param newBlip the newly created blip.
-   * @param content the content to add.
-   */
-  private void putContentForNewBlip(ConversationBlip newBlip, String content) {
-    if (content.length() > 0 && content.charAt(0) == '\n') {
-      // While the client libraries force a newline to be sent as the first
-      // character we'll remove it here since the new blip we created already
-      // contains a newline.
-      content = content.substring(1);
-    }
-    XmlStringBuilder builder = XmlStringBuilder.createText(content);
-    LineContainers.appendToLastLine(newBlip.getContent(), builder);
-  }
-
-  /**
-   * Processes a {@link WaveletBlipCreatedEvent} and puts it into the context.
-   *
-   * @param operation the operation that has been performed
-   * @param context the context of the operation.
-   * @param participant the participant performing the operation.
-   * @param conversation the conversation to which the new blip was added
-   * @param newBlip the newly created blip.
-   * @throws InvalidRequestException if the event could not be processed.
-   */
-  private void processBlipCreatedEvent(OperationRequest operation, 
OperationContext context,
-      ParticipantId participant, ObservableConversation conversation, 
ConversationBlip newBlip)
-      throws InvalidRequestException {
-    WaveletBlipCreatedEvent event =
-        new WaveletBlipCreatedEvent(null, null, participant.getAddress(),
-            System.currentTimeMillis(), 
ConversationUtil.getRootBlipId(conversation),
-            newBlip.getId());
-    context.processEvent(operation, event);
-  }
-
-  public static BlipOperationServices create() {
-    return new BlipOperationServices();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/operations/CreateWaveletService.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/operations/CreateWaveletService.java 
b/src/org/waveprotocol/box/server/robots/operations/CreateWaveletService.java
deleted file mode 100644
index 963d52b..0000000
--- 
a/src/org/waveprotocol/box/server/robots/operations/CreateWaveletService.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import static 
org.waveprotocol.box.server.robots.util.RobotsUtil.createEmptyRobotWavelet;
-
-import com.google.common.collect.Lists;
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.event.WaveletCreatedEvent;
-import com.google.wave.api.impl.WaveletData;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.RobotWaveletData;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.conversation.ObservableConversationBlip;
-import org.waveprotocol.wave.model.conversation.ObservableConversationView;
-import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
-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.id.WaveletName;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-
-import java.util.List;
-
-/**
- * Implementation of the "wavelet.create" and "robot.createwavelet" operations.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public class CreateWaveletService implements OperationService {
-
-  private CreateWaveletService() {
-  }
-
-  /**
-   * Creates a new wavelet that is conversational based on the given
-   * {@link WaveletData}. Note that this is the robot api version of wavelet
-   * data not to be confused with
-   * {@link org.waveprotocol.wave.model.wave.data.WaveletData}.
-   *
-   * <p>
-   * The wavelet data must define the wave id in the temporary format otherwise
-   * it can not be opened by subsequent operations when calling
-   * {@link OperationContext#openWavelet(String, String, ParticipantId)} with
-   * the temporary wave id and wavelet id.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @throws InvalidRequestException if the operation fails to perform.
-   */
-  @Override
-  public void execute(
-      OperationRequest operation, OperationContext context, ParticipantId 
participant)
-      throws InvalidRequestException {
-    WaveletData waveletData =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.WAVELET_DATA);
-
-    // The loop validates the addresses present in the wavelet data before
-    // creating a new wavelet.
-    List<ParticipantId> participants = Lists.newArrayList(participant);
-    for (String address : waveletData.getParticipants()) {
-      try {
-        participants.add(ParticipantId.of(address));
-      } catch (InvalidParticipantAddress e) {
-        throw new InvalidRequestException(
-            address + " is not a valid participant address", operation);
-      }
-    }
-
-    WaveletName waveletName = 
context.getConversationUtil().generateWaveletName();
-    RobotWaveletData newWavelet = createEmptyRobotWavelet(participant, 
waveletName);
-    OpBasedWavelet opBasedWavelet = newWavelet.getOpBasedWavelet(participant);
-
-    WaveletBasedConversation.makeWaveletConversational(opBasedWavelet);
-
-    ObservableConversationView conversation =
-        context.getConversationUtil().buildConversation(opBasedWavelet);
-    ObservableConversationBlip rootBlip = 
conversation.getRoot().getRootThread().appendBlip();
-
-    for (ParticipantId newParticipant : participants) {
-      opBasedWavelet.addParticipant(newParticipant);
-    }
-
-    // Store the temporary id of the wavelet and rootblip so that future
-    // operations can reference it.
-    try {
-      WaveId waveId = 
ApiIdSerializer.instance().deserialiseWaveId(waveletData.getWaveId());
-      WaveletId waveletId =
-          
ApiIdSerializer.instance().deserialiseWaveletId(waveletData.getWaveletId());
-      context.putWavelet(waveId, waveletId, newWavelet);
-    } catch (InvalidIdException e) {
-      throw new InvalidRequestException("Invalid id", operation, e);
-    }
-    context.putBlip(waveletData.getRootBlipId(), rootBlip);
-
-    String message = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.MESSAGE);
-    WaveletCreatedEvent event =
-        new WaveletCreatedEvent(null, null, participant.getAddress(), 
System.currentTimeMillis(),
-            rootBlip.getId(), message,
-            ApiIdSerializer.instance().serialiseWaveId(waveletName.waveId),
-            
ApiIdSerializer.instance().serialiseWaveletId(waveletName.waveletId));
-    context.processEvent(operation, event);
-  }
-
-  public static CreateWaveletService create() {
-    return new CreateWaveletService();
-  }
-}

Reply via email to