http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/register/RobotRegistrar.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/register/RobotRegistrar.java 
b/src/org/waveprotocol/box/server/robots/register/RobotRegistrar.java
deleted file mode 100644
index fa7efbe..0000000
--- a/src/org/waveprotocol/box/server/robots/register/RobotRegistrar.java
+++ /dev/null
@@ -1,86 +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.register;
-
-import org.waveprotocol.box.server.account.RobotAccountData;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import 
org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-/**
- * Provides robot un/registration services.
- *
- * @author [email protected] (Yuri Zelikov)
- */
-public interface RobotRegistrar {
-
-  /** Receives robot un/registration events. */
-  public interface Listener {
-
-    /** Invoked after the robot account was created and added to the account 
store. */
-    public void onRegistrationSuccess(RobotAccountData account);
-
-    /** Invoked after the robot account was removed from the account store. */
-    public void onUnregistrationSuccess(RobotAccountData account);
-  }
-
-  /**
-   * Registers a new robot account.
-   *
-   * @param robotId the robotId to register.
-   * @param location the location of the robot (URI).
-   * @return the newly registered robot account.
-   * @throws RobotRegistrationException if account for this id already exist.
-   * @throws PersistenceException if the persistence layer reports an error.
-   */
-  public RobotAccountData registerNew(ParticipantId robotId, String location)
-      throws RobotRegistrationException, PersistenceException;
-
-  /**
-   * Unregisters a robot by removing it from the account store.
-   *
-   * @param robotId the id to remove.
-   * @return the account data of the removed robot or
-   *         <code>null</null> if no such robot account exist.
-   * @throws RobotRegistrationException if the id to remove exist but is not a
-   *         robot.
-   * @throws PersistenceException if the persistence layer reports an error.
-   */
-  public RobotAccountData unregister(ParticipantId robotId) throws 
RobotRegistrationException,
-      PersistenceException;
-
-  /**
-   * Registers a new robot or re-registers an existing robot in order to 
update the robot location.
-   *
-   * @param robotId the robot id.
-   * @param location the new location of the robot (URI).
-   * @return the updated robot account.
-   * @throws RobotRegistrationException if the id to re-register exist but is 
not a robot.
-   * @throws PersistenceException if the persistence layer reports an error.
-   */
-  public RobotAccountData registerOrUpdate(ParticipantId robotId, String 
location)
-      throws RobotRegistrationException, PersistenceException;
-
-  /** Adds listener. */
-  public void addRegistrationListener(Listener listener);
-
-  /** Removes listener. */
-  public void removeRegistrationListener(Listener listener);
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/register/RobotRegistrarImpl.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/register/RobotRegistrarImpl.java 
b/src/org/waveprotocol/box/server/robots/register/RobotRegistrarImpl.java
deleted file mode 100644
index 06b00eb..0000000
--- a/src/org/waveprotocol/box/server/robots/register/RobotRegistrarImpl.java
+++ /dev/null
@@ -1,218 +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.register;
-
-import com.google.common.base.Preconditions;
-import com.google.inject.Inject;
-
-import org.waveprotocol.box.server.account.AccountData;
-import org.waveprotocol.box.server.account.RobotAccountData;
-import org.waveprotocol.box.server.account.RobotAccountDataImpl;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import 
org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException;
-import org.waveprotocol.wave.model.id.TokenGenerator;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.net.URI;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.logging.Logger;
-
-/**
- * Implements {@link RobotRegistrar}.
- *
- * @author [email protected] (Yuri Zelikov)
- */
-public class RobotRegistrarImpl implements RobotRegistrar {
-
-  private static final Listener REGISTRATION_EVENTS_LOGGER = new Listener() {
-
-    final Logger log = Logger.getLogger(RobotRegistrarImpl.class.getName());
-
-    @Override
-    public void onRegistrationSuccess(RobotAccountData account) {
-      log.info("Registered robot: " + account.getId().getAddress() + " at " + 
account.getUrl());
-    }
-
-    @Override
-    public void onUnregistrationSuccess(RobotAccountData account) {
-      log.info("Unregistered robot: " + account.getId().getAddress() + " at " 
+ account.getUrl());
-    }
-  };
-
-  /** The length of the verification token (token secret). */
-  private static final int TOKEN_LENGTH = 48;
-
-  /** The account store. */
-  private final AccountStore accountStore;
-
-  /** The verification token generator. */
-  private final TokenGenerator tokenGenerator;
-
-  /** The list of listeners on robot un/registration events. */
-  private final CopyOnWriteArraySet<Listener> listeners = new 
CopyOnWriteArraySet<Listener>();
-
-  /**
-   * Computes and validates the robot URL.
-   *
-   * @param location the robot location.
-   * @return the validated robot URL in the form:
-   *         [http|https]://[domain]:[port]/[path], for example:
-   *         http://example.com:80/myrobot
-   * @throws RobotRegistrationException if the specified URI is invalid.
-   */
-  private static String computeValidateRobotUrl(String location)
-      throws RobotRegistrationException {
-    URI uri;
-    try {
-      uri = URI.create(location);
-    } catch (IllegalArgumentException e) {
-      String errorMessage = "Invalid Location specified, please specify a 
location in URI format.";
-      throw new RobotRegistrationException(errorMessage + " " + 
e.getLocalizedMessage(), e);
-    }
-    String scheme = uri.getScheme();
-    if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) 
{
-      scheme = "http";
-    }
-    String robotLocation;
-    if (uri.getPort() != -1) {
-      robotLocation = scheme + "://" + uri.getHost() + ":" + uri.getPort() + 
uri.getPath();
-    } else {
-      robotLocation = scheme + "://" + uri.getHost() + uri.getPath();
-    }
-
-    if (robotLocation.endsWith("/")) {
-      robotLocation = robotLocation.substring(0, robotLocation.length() - 1);
-    }
-    return robotLocation;
-  }
-
-  @Inject
-  public RobotRegistrarImpl(AccountStore accountStore, TokenGenerator 
tokenGenerator) {
-    this.accountStore = accountStore;
-    this.tokenGenerator = tokenGenerator;
-    addRegistrationListener(REGISTRATION_EVENTS_LOGGER);
-  }
-
-  @Override
-  public RobotAccountData registerNew(ParticipantId robotId, String location)
-      throws RobotRegistrationException, PersistenceException {
-    Preconditions.checkNotNull(robotId);
-    Preconditions.checkNotNull(location);
-    Preconditions.checkArgument(!location.isEmpty());
-
-    if (accountStore.getAccount(robotId) != null) {
-      throw new RobotRegistrationException(robotId.getAddress()
-          + " is already in use, please choose another one.");
-    }
-    return registerRobot(robotId, location);
-  }
-
-  @Override
-  public RobotAccountData unregister(ParticipantId robotId) throws 
RobotRegistrationException,
-      PersistenceException {
-    Preconditions.checkNotNull(robotId);
-    AccountData accountData = accountStore.getAccount(robotId);
-    if (accountData == null) {
-      return null;
-    }
-    throwExceptionIfNotRobot(accountData);
-    RobotAccountData robotAccount = accountData.asRobot();
-    removeRobotAccount(robotAccount);
-    return robotAccount;
-  }
-
-  @Override
-  public RobotAccountData registerOrUpdate(ParticipantId robotId, String 
location)
-      throws RobotRegistrationException, PersistenceException {
-    Preconditions.checkNotNull(robotId);
-    Preconditions.checkNotNull(location);
-    Preconditions.checkArgument(!location.isEmpty());
-
-    AccountData account = accountStore.getAccount(robotId);
-    if (account != null) {
-      throwExceptionIfNotRobot(account);
-      RobotAccountData robotAccount = account.asRobot();
-      if (robotAccount.getUrl().equals(location)) {
-        return robotAccount;
-      } else {
-        removeRobotAccount(robotAccount);
-      }
-    }
-    return registerRobot(robotId, location);
-  }
-
-  /**
-   *  Adds the robot to the account store and notifies the listeners.
-   */
-  private RobotAccountData registerRobot(ParticipantId robotId, String 
location)
-      throws RobotRegistrationException, PersistenceException {
-    String robotLocation = computeValidateRobotUrl(location);
-
-    RobotAccountData robotAccount =
-        new RobotAccountDataImpl(robotId, robotLocation,
-            tokenGenerator.generateToken(TOKEN_LENGTH), null, true);
-    accountStore.putAccount(robotAccount);
-    for (Listener listener : listeners) {
-      listener.onRegistrationSuccess(robotAccount);
-    }
-    return robotAccount;
-  }
-
-  /**
-   * Removes the robot account and notifies the listeners.
-   * @param existingAccount the account to remove
-   * @throws PersistenceException if the persistence layer reports an error.
-   */
-  private void removeRobotAccount(RobotAccountData existingAccount)
-      throws PersistenceException {
-    accountStore.removeAccount(existingAccount.getId());
-    for (Listener listener : listeners) {
-      listener.onUnregistrationSuccess(existingAccount);
-    }
-  }
-
-  /**
-   * Ensures that the account belongs to a robot.
-   *
-   * @param existingAccount the account to check.
-   * @throws RobotRegistrationException if the account is not robot.
-   */
-  private void throwExceptionIfNotRobot(AccountData existingAccount)
-      throws RobotRegistrationException {
-    if (!existingAccount.isRobot()) {
-      throw new RobotRegistrationException(existingAccount.getId().getAddress()
-          + " is not a robot account!");
-    }
-  }
-
-  // Handle listeners.
-  @Override
-  public void addRegistrationListener(Listener listener) {
-    Preconditions.checkNotNull(listener);
-    listeners.add(listener);
-  }
-
-  @Override
-  public void removeRegistrationListener(Listener listener) {
-    Preconditions.checkNotNull(listener);
-    listeners.remove(listener);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/testing/OperationServiceHelper.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/testing/OperationServiceHelper.java 
b/src/org/waveprotocol/box/server/robots/testing/OperationServiceHelper.java
deleted file mode 100644
index 814f972..0000000
--- a/src/org/waveprotocol/box/server/robots/testing/OperationServiceHelper.java
+++ /dev/null
@@ -1,120 +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.testing;
-
-import static org.mockito.Mockito.mock;
-
-import com.google.wave.api.data.converter.EventDataConverter;
-import com.google.wave.api.data.converter.v22.EventDataConverterV22;
-
-import org.waveprotocol.box.server.robots.OperationContextImpl;
-import org.waveprotocol.box.server.robots.RobotWaveletData;
-import org.waveprotocol.box.server.robots.operations.OperationService;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
-import org.waveprotocol.wave.model.id.IdURIEncoderDecoder;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.operation.SilentOperationSink;
-import 
org.waveprotocol.wave.model.operation.wave.BasicWaveletOperationContextFactory;
-import org.waveprotocol.wave.model.operation.wave.WaveletOperation;
-import org.waveprotocol.wave.model.testing.BasicFactories;
-import org.waveprotocol.wave.model.testing.FakeIdGenerator;
-import org.waveprotocol.wave.model.version.HashedVersionFactory;
-import org.waveprotocol.wave.model.version.HashedVersionFactoryImpl;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.ParticipationHelper;
-import org.waveprotocol.wave.model.wave.data.DocumentFactory;
-import org.waveprotocol.wave.model.wave.data.DocumentOperationSink;
-import org.waveprotocol.wave.model.wave.data.ObservableWaveletData;
-import org.waveprotocol.wave.model.wave.data.WaveletData;
-import org.waveprotocol.wave.model.wave.data.impl.EmptyWaveletSnapshot;
-import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-import org.waveprotocol.wave.util.escapers.jvm.JavaUrlCodec;
-
-/**
- * Helper for testing {@link OperationService}. Puts a single empty
- * conversational wavelet with one participant in the operation context.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public class OperationServiceHelper {
-
-  private static final IdURIEncoderDecoder URI_CODEC =
-      new IdURIEncoderDecoder(new JavaUrlCodec());
-  private static final HashedVersionFactory HASH_FACTORY = new 
HashedVersionFactoryImpl(URI_CODEC);
-  private static final DocumentFactory<? extends DocumentOperationSink> 
DOCUMENT_FACTORY =
-      BasicFactories.observablePluggableMutableDocumentFactory();
-
-  private final WaveletProvider waveletProvider;
-  private final OperationContextImpl context;
-
-  /**
-   * Constructs a new {@link OperationServiceHelper} with a wavelet with the
-   * name and participant that are passed in.
-   *
-   * @param waveletName the name of the empty wavelet to open in the context.
-   * @param participant the participant that should be on that empty wavelet.
-   */
-  public OperationServiceHelper(WaveletName waveletName, ParticipantId 
participant) {
-    waveletProvider = mock(WaveletProvider.class);
-    EventDataConverter converter = new EventDataConverterV22();
-
-    ObservableWaveletData waveletData = 
WaveletDataImpl.Factory.create(DOCUMENT_FACTORY).create(
-        new EmptyWaveletSnapshot(waveletName.waveId, waveletName.waveletId, 
participant,
-            HASH_FACTORY.createVersionZero(waveletName), 0L));
-    waveletData.addParticipant(participant);
-
-    BasicWaveletOperationContextFactory CONTEXT_FACTORY =
-        new BasicWaveletOperationContextFactory(participant);
-
-    SilentOperationSink<WaveletOperation> executor =
-        SilentOperationSink.Executor.<WaveletOperation, 
WaveletData>build(waveletData);
-    OpBasedWavelet wavelet =
-        new OpBasedWavelet(waveletData.getWaveId(), waveletData, 
CONTEXT_FACTORY,
-            ParticipationHelper.DEFAULT, executor, SilentOperationSink.VOID);
-
-    // Make a conversation with an empty root blip
-    WaveletBasedConversation.makeWaveletConversational(wavelet);
-    ConversationUtil conversationUtil = new 
ConversationUtil(FakeIdGenerator.create());
-    ObservableConversation conversation = 
conversationUtil.buildConversation(wavelet).getRoot();
-    conversation.getRootThread().appendBlip();
-
-    context = new OperationContextImpl(waveletProvider, converter, 
conversationUtil);
-    context.putWavelet(waveletName.waveId, waveletName.waveletId,
-        new RobotWaveletData(waveletData, 
HASH_FACTORY.createVersionZero(waveletName)));
-  }
-
-  /**
-   * @return the {@link WaveletProvider} mock
-   */
-  public WaveletProvider getWaveletProvider() {
-    return waveletProvider;
-  }
-
-  /**
-   * @return the {@link OperationContextImpl} with the empty wavelet opened.
-   */
-  public OperationContextImpl getContext() {
-    return context;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/util/ConversationUtil.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/util/ConversationUtil.java 
b/src/org/waveprotocol/box/server/robots/util/ConversationUtil.java
deleted file mode 100644
index a3b5ff7..0000000
--- a/src/org/waveprotocol/box/server/robots/util/ConversationUtil.java
+++ /dev/null
@@ -1,89 +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.util;
-
-import com.google.common.base.Preconditions;
-import com.google.inject.Inject;
-
-import org.waveprotocol.wave.model.conversation.Conversation;
-import org.waveprotocol.wave.model.conversation.ConversationBlip;
-import org.waveprotocol.wave.model.conversation.ObservableConversationView;
-import org.waveprotocol.wave.model.conversation.WaveBasedConversationView;
-import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
-import org.waveprotocol.wave.model.id.IdGenerator;
-import org.waveprotocol.wave.model.id.IdUtil;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.wave.ObservableWavelet;
-import org.waveprotocol.wave.model.wave.ReadOnlyWaveView;
-
-/**
- * Utility class for {@link Conversation}s used by the Robot API.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public class ConversationUtil {
-
-  private final IdGenerator idGenerator;
-
-  @Inject
-  public ConversationUtil(IdGenerator idGenerator) {
-    this.idGenerator = idGenerator;
-  }
-
-  /**
-   * Builds an {@link ObservableConversationView} for the given wavelet. Note
-   * that this can be expensive since the conversation is not garbage collected
-   * until the wavelet is.
-   *
-   * @param wavelet The wavelet to return the conversation for, must be a valid
-   *        conversation wavelet.
-   * @throws IllegalArgumentException if the wavelet is not a valid 
conversation
-   *         wavelet.
-   */
-  public ObservableConversationView buildConversation(ObservableWavelet 
wavelet) {
-    Preconditions.checkArgument(IdUtil.isConversationalId(wavelet.getId()),
-        "Expected conversational wavelet, got " + wavelet.getId());
-    
Preconditions.checkArgument(WaveletBasedConversation.waveletHasConversation(wavelet),
-        "Conversation can't be build on a wavelet " + wavelet.getId()
-            + " without conversation structure");
-
-    ReadOnlyWaveView wv = new ReadOnlyWaveView(wavelet.getWaveId());
-    wv.addWavelet(wavelet);
-
-    return WaveBasedConversationView.create(wv, idGenerator);
-  }
-
-  /**
-   * Generates a {@link WaveletName} for a conversational wavelet.
-   */
-  public WaveletName generateWaveletName() {
-    return WaveletName.of(idGenerator.newWaveId(), 
idGenerator.newConversationRootWaveletId());
-  }
-
-  /**
-   * Returns the blip id of the first blip in the root thread.
-   *
-   * @param conversation the conversation to get the blip id from.
-   */
-  public static String getRootBlipId(Conversation conversation) {
-    ConversationBlip rootBlip = conversation.getRootThread().getFirstBlip();
-    return (rootBlip != null) ? rootBlip.getId() : "";
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/util/LoggingRequestListener.java
----------------------------------------------------------------------
diff --git 
a/src/org/waveprotocol/box/server/robots/util/LoggingRequestListener.java 
b/src/org/waveprotocol/box/server/robots/util/LoggingRequestListener.java
deleted file mode 100644
index e7586e4..0000000
--- a/src/org/waveprotocol/box/server/robots/util/LoggingRequestListener.java
+++ /dev/null
@@ -1,56 +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.util;
-
-import 
org.waveprotocol.box.server.waveserver.WaveletProvider.SubmitRequestListener;
-import org.waveprotocol.wave.model.version.HashedVersion;
-import org.waveprotocol.wave.util.logging.Log;
-
-/**
- * {@link SubmitRequestListener} that simply logs its calls.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public final class LoggingRequestListener implements SubmitRequestListener {
-
-  private final Log log;
-
-  /**
-   * Constructs a new {@link SubmitRequestListener} that logs its calls to the
-   * given log.
-   *
-   * @param log the log to use.
-   */
-  public LoggingRequestListener(Log log) {
-    this.log = log;
-  }
-
-  @Override
-  public void onFailure(String errorMessage) {
-    log.warning("Robot operations failed to be submitted: " + errorMessage);
-  }
-
-  @Override
-  public void onSuccess(int operationsApplied, HashedVersion 
hashedVersionAfterApplication,
-      long applicationTimestamp) {
-    log.fine(operationsApplied + " Robot operations have been succesfully 
applied "
-        + "changing the version to " + hashedVersionAfterApplication);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/util/OperationUtil.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/util/OperationUtil.java 
b/src/org/waveprotocol/box/server/robots/util/OperationUtil.java
deleted file mode 100644
index a0c12df..0000000
--- a/src/org/waveprotocol/box/server/robots/util/OperationUtil.java
+++ /dev/null
@@ -1,301 +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.util;
-
-import com.google.common.base.Strings;
-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.OperationType;
-import com.google.wave.api.ProtocolVersion;
-import com.google.wave.api.robot.RobotName;
-
-import org.waveprotocol.box.server.common.CoreWaveletOperationSerializer;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.OperationResults;
-import org.waveprotocol.box.server.robots.OperationServiceRegistry;
-import org.waveprotocol.box.server.robots.RobotWaveletData;
-import org.waveprotocol.box.server.robots.operations.OperationService;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import 
org.waveprotocol.box.server.waveserver.WaveletProvider.SubmitRequestListener;
-import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta;
-import org.waveprotocol.wave.model.conversation.ConversationView;
-import org.waveprotocol.wave.model.id.IdUtil;
-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.operation.wave.WaveletDelta;
-import org.waveprotocol.wave.model.supplement.PrimitiveSupplement;
-import org.waveprotocol.wave.model.supplement.SupplementedWave;
-import org.waveprotocol.wave.model.supplement.SupplementedWaveImpl;
-import 
org.waveprotocol.wave.model.supplement.SupplementedWaveImpl.DefaultFollow;
-import org.waveprotocol.wave.model.supplement.WaveletBasedSupplement;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.util.List;
-import java.util.Map.Entry;
-
-/**
- * {@link OperationRequest} utility methods.
- *
- * @author [email protected] (Lennard de Rijk)
- */
-public class OperationUtil {
-
-  private static final Log LOG = Log.get(OperationUtil.class);
-
-  private OperationUtil() {
-  }
-
-  /**
-   * Attempts to get a parameter, throws an exception if not found.
-   *
-   * @param <T> type of class to cast to.
-   * @param operation operation to extract property from.
-   * @param property the key of the parameter.
-   * @return specialized object after being serialized.
-   *
-   * @throws InvalidRequestException if the property is not found.
-   */
-  @SuppressWarnings("unchecked")
-  public static <T> T getRequiredParameter(OperationRequest operation, 
ParamsProperty property)
-      throws InvalidRequestException {
-    Object parameter = operation.getParameter(property);
-    Class<T> clazz = (Class<T>) property.clazz();
-    if (parameter == null || !clazz.isInstance(parameter)) {
-      throw new InvalidRequestException("property " + property + " not found", 
operation);
-    }
-    return clazz.cast(parameter);
-  }
-
-  /**
-   * Attempts to get a parameter, returns the {@code null} if not found.
-   *
-   * @param <T> type of class to cast to.
-   * @param operation operation to extract property from.
-   * @param key the key of the parameter.
-   * @return specialized object after being serialized, or {@code null} if the
-   *         parameter could not be found.
-   */
-  public static <T> T getOptionalParameter(OperationRequest operation, 
ParamsProperty key) {
-    return OperationUtil.<T> getOptionalParameter(operation, key, null);
-  }
-
-  /**
-   * Attempts to get a parameter, returns the default if not found.
-   *
-   * @param <T> type of class to cast to.
-   * @param operation operation to extract property from.
-   * @param property the key of the parameter.
-   * @param defaultValue default value to return if parameter could not be
-   *        found.
-   * @return specialized object after being serialized, or the default value if
-   *         the parameter could not be found.
-   */
-  @SuppressWarnings("unchecked")
-  public static <T> T getOptionalParameter(
-      OperationRequest operation, ParamsProperty property, T defaultValue) {
-    Object parameter = operation.getParameter(property);
-    Class<T> clazz = (Class<T>) property.clazz();
-    if (parameter != null && clazz.isInstance(parameter)) {
-      return clazz.cast(parameter);
-    }
-    return defaultValue;
-  }
-
-  /**
-   * Determines the protocol version of a given operation bundle by inspecting
-   * the first operation in the bundle. If it is a {@code robot.notify}
-   * operation, and contains {@code protocolVersion} parameter, then this 
method
-   * will return the value of that parameter. Otherwise, this method will 
return
-   * the default version.
-   *
-   * @param operations the {@link OperationRequest}s to inspect.
-   * @return the wire protocol version of the given operation bundle.
-   */
-  public static ProtocolVersion getProtocolVersion(List<OperationRequest> 
operations) {
-    if (operations.size() == 0) {
-      return ProtocolVersion.DEFAULT;
-    }
-
-    OperationRequest firstOperation = operations.get(0);
-    if 
(firstOperation.getMethod().equals(OperationType.ROBOT_NOTIFY.method())) {
-      String versionString = (String) 
firstOperation.getParameter(ParamsProperty.PROTOCOL_VERSION);
-      if (versionString != null) {
-        return ProtocolVersion.fromVersionString(versionString);
-      }
-    }
-    return ProtocolVersion.DEFAULT;
-  }
-
-  /**
-   * @return the type of operation present in the request
-   */
-  public static OperationType getOperationType(OperationRequest operation) {
-    String methodName = operation.getMethod();
-
-    // TODO(ljvderijk): This might be removed after the deserialization is 
fixed
-    if (methodName.startsWith("wave.")) {
-      methodName = methodName.replaceFirst("^wave[.]", "");
-    }
-    return OperationType.fromMethodName(methodName);
-  }
-
-  /**
-   * Executes an {@link OperationRequest}. If the operation throws an
-   * {@link InvalidRequestException} this exception will be used to construct 
an
-   * error response in the {@link OperationContext}.
-   *
-   * @param operation the operation to be executed. If the operation contains
-   *        {@link ParamsProperty.PROXYING_FOR} - then it will be taken in
-   *        account.
-   * @param operationRegistry the registry containing the operations that can 
be
-   *        performed.
-   * @param context the context in which the operation is to be executed.
-   * @param author the author of the operation.
-   */
-  public static void executeOperation(OperationRequest operation,
-      OperationServiceRegistry operationRegistry, OperationContext context, 
ParticipantId author) {
-    try {
-      OperationService service =
-          
operationRegistry.getServiceFor(OperationUtil.getOperationType(operation));
-      ParticipantId proxyParticipant = 
OperationUtil.computeParticipant(operation, author);
-      service.execute(operation, context, proxyParticipant);
-    } catch (InvalidRequestException e) {
-      LOG.warning("Operation " + operation + " failed to execute", e);
-      context.constructErrorResponse(operation, e.getMessage());
-    }
-  }
-
-  /**
-   * Submits all deltas to the wavelet provider that are generated by the open
-   * wavelets in the {@link OperationResults}.
-   *
-   * @param results the results of performing robot operations.
-   * @param waveletProvider wavelet provider used to send the deltas to.
-   * @param requestListener callback for deltas that are submitted to the
-   *        wavelet provider.
-   */
-  public static void submitDeltas(OperationResults results, WaveletProvider 
waveletProvider,
-      SubmitRequestListener requestListener) {
-    for (Entry<WaveletName, RobotWaveletData> entry : 
results.getOpenWavelets().entrySet()) {
-      WaveletName waveletName = entry.getKey();
-      RobotWaveletData w = entry.getValue();
-      for (WaveletDelta delta : w.getDeltas()) {
-        ProtocolWaveletDelta protocolDelta = 
CoreWaveletOperationSerializer.serialize(delta);
-        waveletProvider.submitRequest(waveletName, protocolDelta, 
requestListener);
-      }
-    }
-  }
-
-
-  /**
-   * Appends proxyFor to the participant address.
-   *
-   * @param proxyFor the proxyFor.
-   * @param participant the participant to apply the proxyFor.
-   * @return new participant instance in the format
-   *         [email protected]. If proxyFor is null then just
-   *         returns unmodified participant.
-   * @throws InvalidParticipantAddress if participant address and/or proxy are
-   *         invalid.
-   */
-  public static ParticipantId toProxyParticipant(ParticipantId participant, 
String proxyFor)
-      throws InvalidParticipantAddress {
-    if (!Strings.isNullOrEmpty(proxyFor)) {
-      RobotName robotName = RobotName.fromAddress(participant.getAddress());
-      robotName.setProxyFor(proxyFor);
-      String robotAddress = robotName.toParticipantAddress();
-      if (!RobotName.isWellFormedAddress(robotAddress)) {
-        throw new InvalidParticipantAddress(robotAddress,
-            "is not a valid robot name, the proxy is likely to be wrong");
-      }
-      return ParticipantId.of(robotName.toParticipantAddress());
-    } else {
-      return participant;
-    }
-  }
-
-  /**
-   * Computes participant ID using optional {@link ParamsProperty.PROXYING_FOR}
-   * parameter.
-   *
-   * @param operation the operation to be executed.
-   * @param participant the base participant id.
-   * @return new participant instance in the format
-   *         [email protected]. If proxyFor is null then just
-   *         returns unmodified participant.
-   * @throws InvalidRequestException if participant address and/or proxyFor are
-   *         invalid.
-   */
-  public static ParticipantId computeParticipant(OperationRequest operation,
-      ParticipantId participant) throws InvalidRequestException {
-    String proxyAddress =
-        OperationUtil.getOptionalParameter(operation, 
ParamsProperty.PROXYING_FOR);
-    try {
-      return toProxyParticipant(participant, proxyAddress);
-    } catch (InvalidParticipantAddress e) {
-      throw new InvalidRequestException(
-          participant.getAddress()
-          + (proxyAddress != null ? "+" + proxyAddress : ""
-              + " is not a valid participant address"), operation);
-    }
-  }
-
-  /**
-   * Builds the supplement model for a wave.
-   *
-   * @param operation the operation.
-   * @param context the operation context.
-   * @param participant the viewer.
-   * @return the wave supplement.
-   * @throws InvalidRequestException if the wave id provided in the operation 
is
-   *         invalid.
-   */
-  public static SupplementedWave buildSupplement(OperationRequest operation,
-      OperationContext context, ParticipantId participant) throws 
InvalidRequestException {
-    OpBasedWavelet wavelet = context.openWavelet(operation, participant);
-    ConversationView conversationView = 
context.getConversationUtil().buildConversation(wavelet);
-
-    // TODO (Yuri Z.) Find a way to obtain an instance of IdGenerator and use 
it
-    // to create udwId.
-    WaveletId udwId = IdUtil.buildUserDataWaveletId(participant);
-    String waveIdStr = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.WAVE_ID);
-    WaveId waveId = null;
-    try {
-      waveId = ApiIdSerializer.instance().deserialiseWaveId(waveIdStr);
-    } catch (InvalidIdException e) {
-      throw new InvalidRequestException("Invalid WAVE_ID parameter: " + 
waveIdStr, operation, e);
-    }
-    OpBasedWavelet udw = context.openWavelet(waveId, udwId, participant);
-
-    PrimitiveSupplement udwState = WaveletBasedSupplement.create(udw);
-
-    SupplementedWave supplement =
-        SupplementedWaveImpl.create(udwState, conversationView, participant, 
DefaultFollow.ALWAYS);
-    return supplement;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/util/RobotsUtil.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/util/RobotsUtil.java 
b/src/org/waveprotocol/box/server/robots/util/RobotsUtil.java
deleted file mode 100644
index aa61ca9..0000000
--- a/src/org/waveprotocol/box/server/robots/util/RobotsUtil.java
+++ /dev/null
@@ -1,97 +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.util;
-
-import com.google.wave.api.Annotation;
-import com.google.wave.api.Blip;
-import com.google.wave.api.BlipContent;
-import com.google.wave.api.Range;
-
-import org.waveprotocol.box.server.robots.RobotWaveletData;
-import org.waveprotocol.box.server.util.WaveletDataUtil;
-import org.waveprotocol.wave.model.id.IdURIEncoderDecoder;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.version.HashedVersion;
-import org.waveprotocol.wave.model.version.HashedVersionFactory;
-import org.waveprotocol.wave.model.version.HashedVersionZeroFactoryImpl;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.data.ObservableWaveletData;
-import org.waveprotocol.wave.util.escapers.jvm.JavaUrlCodec;
-
-/**
- * Provides helper methods for the operation services.
- *
- * @author [email protected] (Yuri Zelikov)
- */
-public class RobotsUtil {
-
-  @SuppressWarnings("serial")
-  public static class RobotRegistrationException extends Exception {
-
-    public RobotRegistrationException (String message) {
-      super(message);
-    }
-
-    public RobotRegistrationException(String message, Throwable t) {
-      super(message, t);
-    }
-  }
-
-  private static final IdURIEncoderDecoder URI_CODEC = new 
IdURIEncoderDecoder(new JavaUrlCodec());
-  private static final HashedVersionFactory HASH_FACTORY = new 
HashedVersionZeroFactoryImpl(
-      URI_CODEC);
-
-  /**
-   * Creates a new empty robot wavelet data.
-   *
-   * @param participant the wavelet creator.
-   * @param waveletName the wavelet name.
-   */
-  public static RobotWaveletData createEmptyRobotWavelet(ParticipantId 
participant,
-      WaveletName waveletName) {
-    HashedVersion hashedVersionZero = 
HASH_FACTORY.createVersionZero(waveletName);
-    ObservableWaveletData emptyWavelet =
-        WaveletDataUtil.createEmptyWavelet(waveletName, participant, 
hashedVersionZero,
-            System.currentTimeMillis());
-    RobotWaveletData newWavelet = new RobotWaveletData(emptyWavelet, 
hashedVersionZero);
-    return newWavelet;
-  }
-
-  /**
-   * Copies the content of the source blip into the target blip.
-   *
-   * @param fromBlip the source blip.
-   * @param toBlip the target blip.
-   */
-  public static void copyBlipContents(Blip fromBlip, Blip toBlip) {
-    for (BlipContent blipContent: fromBlip.all().values()) {
-      toBlip.append(blipContent);
-    }
-    for (Annotation annotation : fromBlip.getAnnotations()) {
-      Range range = annotation.getRange();
-      toBlip.range(range.getStart() + 1, range.getEnd() + 
1).annotate(annotation.getName(),
-          annotation.getValue());
-    }
-  }
-
-  private RobotsUtil() {
-
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java 
b/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
deleted file mode 100644
index 7fa14af..0000000
--- a/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
+++ /dev/null
@@ -1,123 +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.rpc;
-
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.JsonRpcResponse;
-import com.google.wave.api.OperationQueue;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.ProtocolVersion;
-import com.google.wave.api.SearchResult;
-import com.google.wave.api.data.converter.EventDataConverterManager;
-
-import org.waveprotocol.box.search.SearchProto.SearchRequest;
-import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.robots.OperationContextImpl;
-import org.waveprotocol.box.server.robots.OperationServiceRegistry;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-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 javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * A base for servlets that provide search functionality.
- *
- * @author [email protected] (Yuri Z.)
- */
-@SuppressWarnings("serial")
-public abstract class AbstractSearchServlet extends HttpServlet {
-
-  private static final Log LOG = Log.get(AbstractSearchServlet.class);
-
-  private static String DEFAULT_QUERY = "";
-  private static String DEFAULT_NUMRESULTS = "100";
-
-  protected final ConversationUtil conversationUtil;
-  protected final EventDataConverterManager converterManager;
-  protected final WaveletProvider waveletProvider;
-  protected final SessionManager sessionManager;
-  protected final OperationServiceRegistry operationRegistry;
-
-
-  private static String getParameter(HttpServletRequest req, String paramName, 
String defaultValue) {
-    String param = req.getParameter(paramName);
-    param = param == null ? defaultValue : param;
-    return param;
-  }
-
-  /**
-   * Constructor.
-   */
-  public AbstractSearchServlet(ConversationUtil conversationUtil,
-      EventDataConverterManager converterManager, WaveletProvider 
waveletProvider,
-      SessionManager sessionManager, OperationServiceRegistry 
operationRegistry) {
-    this.conversationUtil = conversationUtil;
-    this.converterManager = converterManager;
-    this.waveletProvider = waveletProvider;
-    this.sessionManager = sessionManager;
-    this.operationRegistry = operationRegistry;
-  }
-
-  /**
-   * Extracts search query params from request.
-   *
-   * @param req the request.
-   * @param response the response.
-   * @return the SearchRequest with query data.
-   */
-  public static SearchRequest parseSearchRequest(HttpServletRequest req,
-      HttpServletResponse response) {
-
-    String query = getParameter(req, "query", DEFAULT_QUERY);
-    String index = getParameter(req, "index", "0");
-    String numResults = getParameter(req, "numResults", DEFAULT_NUMRESULTS);
-    SearchRequest searchRequest =
-        
SearchRequest.newBuilder().setQuery(query).setIndex(Integer.parseInt(index))
-            .setNumResults(Integer.parseInt(numResults)).build();
-    return searchRequest;
-  }
-
-  /**
-   * Performs search using Data API.
-   */
-  protected SearchResult performSearch(SearchRequest searchRequest, 
ParticipantId user) {
-    OperationQueue opQueue = new OperationQueue();
-    opQueue.search(searchRequest.getQuery(), searchRequest.getIndex(),
-        searchRequest.getNumResults());
-    OperationContextImpl context =
-        new OperationContextImpl(waveletProvider,
-            converterManager.getEventDataConverter(ProtocolVersion.DEFAULT), 
conversationUtil);
-    LOG.fine(
-        "Performing query: " + searchRequest.getQuery() + " [" + 
searchRequest.getIndex() + ", "
-            + (searchRequest.getIndex() + searchRequest.getNumResults()) + 
"]");
-    OperationRequest operationRequest = opQueue.getPendingOperations().get(0);
-    String opId = operationRequest.getId();
-    OperationUtil.executeOperation(operationRequest, operationRegistry, 
context, user);
-    JsonRpcResponse jsonRpcResponse = context.getResponses().get(opId);
-    SearchResult searchResult =
-        (SearchResult) 
jsonRpcResponse.getData().get(ParamsProperty.SEARCH_RESULTS);
-    return searchResult;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/rpc/AttachmentInfoServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/rpc/AttachmentInfoServlet.java 
b/src/org/waveprotocol/box/server/rpc/AttachmentInfoServlet.java
deleted file mode 100644
index b4dd4a0..0000000
--- a/src/org/waveprotocol/box/server/rpc/AttachmentInfoServlet.java
+++ /dev/null
@@ -1,143 +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.rpc;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-import java.util.logging.Level;
-import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.rpc.ProtoSerializer.SerializationException;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.waveprotocol.box.attachment.AttachmentMetadata;
-import org.waveprotocol.box.attachment.AttachmentProto.AttachmentsResponse;
-import org.waveprotocol.box.attachment.proto.AttachmentMetadataProtoImpl;
-import org.waveprotocol.box.server.attachment.AttachmentService;
-import org.waveprotocol.box.server.persistence.AttachmentUtil;
-import org.waveprotocol.box.server.waveserver.WaveServerException;
-import org.waveprotocol.wave.media.model.AttachmentId;
-
-/*
- * Serves attachments info from a provided store.
- *
- * @author [email protected] (A. Kaplanov)
- */
-
-@SuppressWarnings("serial")
-@Singleton
-public class AttachmentInfoServlet extends HttpServlet {
-  public static final String ATTACHMENTS_INFO_URL = "/attachmentsInfo";
-
-  private static final Log LOG = Log.get(AttachmentInfoServlet.class);
-
-  private final AttachmentService service;
-  private final WaveletProvider waveletProvider;
-  private final SessionManager sessionManager;
-  private final ProtoSerializer serializer;
-
-  @Inject
-  private AttachmentInfoServlet(AttachmentService service, WaveletProvider 
waveletProvider,
-      SessionManager sessionManager, ProtoSerializer serializer) {
-    this.service = service;
-    this.waveletProvider = waveletProvider;
-    this.sessionManager = sessionManager;
-    this.serializer = serializer;
-  }
-
-  @Override
-  protected void doGet(HttpServletRequest request, HttpServletResponse 
response) throws IOException {
-    List<AttachmentId> attachmentIds = getIdsFromRequest(request);
-
-    if (attachmentIds == null) {
-      response.sendError(HttpServletResponse.SC_NOT_FOUND);
-      return;
-    }
-
-    ParticipantId user = 
sessionManager.getLoggedInUser(request.getSession(false));
-
-    AttachmentsResponse.Builder attachmentsResponse = 
AttachmentsResponse.newBuilder();
-    for (AttachmentId id : attachmentIds) {
-      AttachmentMetadata metadata = service.getMetadata(id);
-      if (metadata != null) {
-        boolean isAuthorized = false;
-        WaveletName waveletName = 
AttachmentUtil.waveRef2WaveletName(metadata.getWaveRef());
-        try {
-          isAuthorized = waveletProvider.checkAccessPermission(waveletName, 
user);
-        } catch (WaveServerException e) {
-          LOG.warning("Problem while authorizing user: " + user + " for 
wavelet: " + waveletName, e);
-        }
-        if (isAuthorized) {
-          attachmentsResponse.addAttachment(new 
AttachmentMetadataProtoImpl(metadata).getPB());
-        }
-      }
-    }
-
-    String info;
-    try {
-      info = serializer.toJson(attachmentsResponse.build()).toString();
-    } catch (SerializationException ex) {
-      LOG.log(Level.SEVERE, "Attachments info serialize", ex);
-      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-      return;
-    }
-
-    response.setStatus(HttpServletResponse.SC_OK);
-    response.setContentType("application/json; charset=utf8");
-    response.setHeader("Cache-Control", "no-store");
-    response.getWriter().append(info);
-
-    LOG.info("Fetched info for " + attachmentIds.size() + " attachments");
-  }
-
-  /**
-   * Get the attachment Ids from the URL in the request.
-   *
-   * @param request
-   * @return the list of Ids.
-   */
-  private static List<AttachmentId> getIdsFromRequest(HttpServletRequest 
request) {
-    String par = request.getParameter("attachmentIds");
-    if (par != null) {
-      List<AttachmentId> ids = new ArrayList<AttachmentId>();
-      for (String id : par.split(",", -1)) {
-        try {
-          ids.add(AttachmentId.deserialise(id));
-        } catch (InvalidIdException ex) {
-          LOG.log(Level.SEVERE, "Deserialize attachment Id " + id, ex);
-        }
-      }
-      return ids;
-    }
-    return null;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/rpc/AttachmentServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/rpc/AttachmentServlet.java 
b/src/org/waveprotocol/box/server/rpc/AttachmentServlet.java
deleted file mode 100644
index e0d99bf..0000000
--- a/src/org/waveprotocol/box/server/rpc/AttachmentServlet.java
+++ /dev/null
@@ -1,296 +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.rpc;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.typesafe.config.Config;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileItemFactory;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.io.FilenameUtils;
-import org.waveprotocol.box.attachment.AttachmentMetadata;
-import org.waveprotocol.box.server.attachment.AttachmentService;
-import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.persistence.AttachmentStore.AttachmentData;
-import org.waveprotocol.box.server.persistence.AttachmentUtil;
-import org.waveprotocol.box.server.waveserver.WaveServerException;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.wave.media.model.AttachmentId;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.net.URLDecoder;
-import java.util.Calendar;
-import java.util.List;
-import java.util.logging.Level;
-
-/**
- * Serves attachments from a provided store.
- *
- * @author [email protected] (A. Kaplanov)
- *
- */
-
-@SuppressWarnings("serial")
-@Singleton
-public class AttachmentServlet extends HttpServlet {
-  public static String ATTACHMENT_URL = "/attachment";
-  public static String THUMBNAIL_URL = "/thumbnail";
-
-  public static String THUMBNAIL_PATTERN_FORMAT_NAME = "png";
-  public static String THUMBNAIL_PATTERN_DEFAULT = "default";
-
-  private static final Log LOG = Log.get(AttachmentServlet.class);
-
-  private final AttachmentService service;
-  private final WaveletProvider waveletProvider;
-  private final SessionManager sessionManager;
-  private final String thumbnailPattternsDirectory;
-
-  @Inject
-  private AttachmentServlet(AttachmentService service, WaveletProvider 
waveletProvider,
-      SessionManager sessionManager, Config config) {
-    this.service = service;
-    this.waveletProvider = waveletProvider;
-    this.sessionManager = sessionManager;
-    this.thumbnailPattternsDirectory = 
config.getString("core.thumbnail_patterns_directory");
-  }
-
-  @Override
-  protected void doGet(HttpServletRequest request, HttpServletResponse 
response) throws IOException {
-    AttachmentId attachmentId = getAttachmentIdFromRequest(request);
-
-    if (attachmentId == null) {
-      response.sendError(HttpServletResponse.SC_NOT_FOUND);
-      return;
-    }
-
-    String fileName = getFileNameFromRequest(request);
-    String waveRefStr = getWaveRefFromRequest(request);
-
-    AttachmentMetadata metadata = service.getMetadata(attachmentId);
-    WaveletName waveletName;
-
-    if (metadata == null) {
-      // Old attachments does not have metainfo.
-      if (waveRefStr != null) {
-        waveletName = AttachmentUtil.waveRef2WaveletName(waveRefStr);
-      } else {
-        response.sendError(HttpServletResponse.SC_NOT_FOUND);
-        return;
-      }
-    } else {
-      waveletName = AttachmentUtil.waveRef2WaveletName(metadata.getWaveRef());
-    }
-
-    ParticipantId user = 
sessionManager.getLoggedInUser(request.getSession(false));
-    boolean isAuthorized = false;
-    try {
-      isAuthorized = waveletProvider.checkAccessPermission(waveletName, user);
-    } catch (WaveServerException e) {
-      LOG.warning("Problem while authorizing user: " + user + " for wavelet: " 
+ waveletName, e);
-    }
-    if (!isAuthorized) {
-      response.sendError(HttpServletResponse.SC_FORBIDDEN);
-      return;
-    }
-
-    if (metadata == null) {
-      metadata = service.buildAndStoreMetadataWithThumbnail(attachmentId, 
waveletName, fileName, null);
-    }
-
-    String contentType;
-    AttachmentData data;
-    if (request.getRequestURI().startsWith(ATTACHMENT_URL)) {
-      contentType = metadata.getMimeType();
-      data = service.getAttachment(attachmentId);
-      if (data == null) {
-        response.sendError(HttpServletResponse.SC_NOT_FOUND);
-        return;
-      }
-    } else if (request.getRequestURI().startsWith(THUMBNAIL_URL)) {
-      if (metadata.hasImageMetadata()) {
-        contentType = AttachmentService.THUMBNAIL_MIME_TYPE;
-        data = service.getThumbnail(attachmentId);
-        if (data == null) {
-          response.sendError(HttpServletResponse.SC_NOT_FOUND);
-          return;
-        }
-      } else {
-        contentType = THUMBNAIL_PATTERN_FORMAT_NAME;
-        data = getThumbnailByContentType(metadata.getMimeType());
-      }
-    } else {
-      response.sendError(HttpServletResponse.SC_NOT_FOUND);
-      return;
-    }
-    if (data == null) {
-      response.sendError(HttpServletResponse.SC_NOT_FOUND);
-      return;
-    }
-
-    response.setContentType(contentType);
-    response.setContentLength((int)data.getSize());
-    response.setHeader("Content-Disposition", "attachment; filename=\"" + 
metadata.getFileName() + "\"");
-    response.setStatus(HttpServletResponse.SC_OK);
-    response.setDateHeader("Last-Modified", 
Calendar.getInstance().getTimeInMillis());
-    AttachmentUtil.writeTo(data.getInputStream(), response.getOutputStream());
-
-    LOG.info("Fetched attachment with id '" + attachmentId + "'");
-  }
-
-  @Override
-  protected void doPost(HttpServletRequest request, HttpServletResponse 
response) throws ServletException,
-      IOException {
-    // Process only multipart requests.
-    if (ServletFileUpload.isMultipartContent(request)) {
-      // Create a factory for disk-based file items.
-      FileItemFactory factory = new DiskFileItemFactory();
-
-      // Create a new file upload handler.
-      ServletFileUpload upload = new ServletFileUpload(factory);
-
-      // Parse the request.
-      try {
-        @SuppressWarnings("unchecked")
-        List<FileItem> items = upload.parseRequest(request);
-        AttachmentId id = null;
-        String waveRefStr = null;
-        FileItem fileItem = null;
-        for (FileItem item : items) {
-          // Process only file upload - discard other form item types.
-          if (item.isFormField()) {
-            if (item.getFieldName().equals("attachmentId")) {
-              id = AttachmentId.deserialise(item.getString());
-            }
-            if (item.getFieldName().equals("waveRef")) {
-              waveRefStr = item.getString();
-            }
-          } else {
-            fileItem = item;
-          }
-        }
-
-        if (id == null) {
-          response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No 
attachment Id in the request.");
-          return;
-        }
-        if (waveRefStr == null) {
-          response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No wave 
reference in request.");
-          return;
-        }
-
-        WaveletName waveletName = 
AttachmentUtil.waveRef2WaveletName(waveRefStr);
-        ParticipantId user = 
sessionManager.getLoggedInUser(request.getSession(false));
-        boolean isAuthorized = 
waveletProvider.checkAccessPermission(waveletName, user);
-        if (!isAuthorized) {
-          response.sendError(HttpServletResponse.SC_FORBIDDEN);
-          return;
-        }
-
-        // Get only the file name not whole path.
-        if (fileItem != null && fileItem.getName()  != null) {
-          String fileName = FilenameUtils.getName(fileItem.getName());
-          service.storeAttachment(id, fileItem.getInputStream(), waveletName, 
fileName, user);
-          response.setStatus(HttpServletResponse.SC_CREATED);
-          String msg =
-              String.format("The file with name: %s and id: %s was created 
successfully.",
-                  fileName, id);
-          LOG.fine(msg);
-          response.getWriter().print("OK");
-          response.flushBuffer();
-        }
-      } catch (Exception e) {
-        LOG.severe("Upload error", e);
-        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
-            "An error occurred while upload the file : " + e.getMessage());
-      }
-    } else {
-      LOG.severe("Request contents type is not supported by the servlet.");
-      response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
-          "Request contents type is not supported by the servlet.");
-    }
-  }
-
-  private static AttachmentId getAttachmentIdFromRequest(HttpServletRequest 
request) {
-    if (request.getPathInfo().length() == 0) {
-      return null;
-    }
-    String id = getAttachmentIdStringFromRequest(request);
-    try {
-      return AttachmentId.deserialise(id);
-    } catch (InvalidIdException ex) {
-      LOG.log(Level.SEVERE, "Deserialize attachment Id " + id, ex);
-      return null;
-    }
-  }
-
-  private static String getAttachmentIdStringFromRequest(HttpServletRequest 
request) {
-    // Discard the leading '/' in the pathinfo.
-    return request.getPathInfo().substring(1);
-  }
-
-  private AttachmentData getThumbnailByContentType(String contentType) throws 
IOException {
-    File file = new File(thumbnailPattternsDirectory, 
contentType.replaceAll("/", "_"));
-    if (!file.exists()) {
-      file = new File(thumbnailPattternsDirectory, THUMBNAIL_PATTERN_DEFAULT);
-    }
-    final File thumbFile = file;
-    return new AttachmentData() {
-
-      @Override
-      public InputStream getInputStream() throws IOException {
-        return new FileInputStream(thumbFile);
-      }
-
-      @Override
-      public long getSize() {
-        return thumbFile.length();
-      }
-    };
-  }
-
-  private static String getFileNameFromRequest(HttpServletRequest request) {
-    String fileName = request.getParameter("fileName");
-    return fileName != null ? fileName : "";
-  }
-
-  private static String getWaveRefFromRequest(HttpServletRequest request) {
-    String waveRefStrEncoded = request.getParameter("waveRef");
-    String waveRefStr = null;
-    if (waveRefStrEncoded != null) {
-      try {
-        waveRefStr = URLDecoder.decode(waveRefStrEncoded, "UTF-8");
-      } catch (UnsupportedEncodingException e) {
-        LOG.warning("Problem decoding: " + waveRefStrEncoded, e);
-      }
-    }
-    return waveRefStr;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/rpc/AuthenticationServlet.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/rpc/AuthenticationServlet.java 
b/src/org/waveprotocol/box/server/rpc/AuthenticationServlet.java
deleted file mode 100644
index b282576..0000000
--- a/src/org/waveprotocol/box/server/rpc/AuthenticationServlet.java
+++ /dev/null
@@ -1,412 +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.rpc;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.gxp.base.GxpContext;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import com.typesafe.config.Config;
-import org.eclipse.jetty.util.MultiMap;
-import org.eclipse.jetty.util.UrlEncoded;
-import org.waveprotocol.box.server.CoreSettingsNames;
-import 
org.waveprotocol.box.server.authentication.HttpRequestBasedCallbackHandler;
-import org.waveprotocol.box.server.authentication.ParticipantPrincipal;
-import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.gxp.AuthenticationPage;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.robots.agent.welcome.WelcomeRobot;
-import org.waveprotocol.box.server.util.RegistrationUtil;
-import org.waveprotocol.wave.model.id.WaveIdentifiers;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import javax.inject.Singleton;
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-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;
-import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLDecoder;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CodingErrorAction;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-
-/**
- * A servlet for authenticating a user's password and giving them a token via a
- * cookie.
- *
- * @author [email protected] (Joseph Gentle)
- */
-@SuppressWarnings("serial")
-@Singleton
-public class AuthenticationServlet extends HttpServlet {
-  private static final String DEFAULT_REDIRECT_URL = "/";
-  public static final String RESPONSE_STATUS_NONE = "NONE";
-  public static final String RESPONSE_STATUS_FAILED = "FAILED";
-  public static final String RESPONSE_STATUS_SUCCESS = "SUCCESS";
-  // The Object ID of the PKCS #9 email address stored in the client 
certificate.
-  // Source: 
http://www.rsa.com/products/bsafe/documentation/sslc251html/group__AD__COMMON__OIDS.html
-  private static final String OID_EMAIL = "1.2.840.113549.1.9.1";
-
-  private static final Log LOG = Log.get(AuthenticationServlet.class);
-
-  private final AccountStore accountStore;
-  private final Configuration configuration;
-  private final SessionManager sessionManager;
-  private final String domain;
-  private final boolean isClientAuthEnabled;
-  private final String clientAuthCertDomain;
-  private final boolean isRegistrationDisabled;
-  private final boolean isLoginPageDisabled;
-  private boolean failedClientAuth = false;
-private final WelcomeRobot welcomeBot;
-  private final String analyticsAccount;
-
-  @Inject
-  public AuthenticationServlet(AccountStore accountStore,
-                               Configuration configuration,
-                               SessionManager sessionManager,
-                               @Named(CoreSettingsNames.WAVE_SERVER_DOMAIN) 
String domain,
-                               Config config,
-                               WelcomeRobot welcomeBot) {
-    Preconditions.checkNotNull(accountStore, "AccountStore is null");
-    Preconditions.checkNotNull(configuration, "Configuration is null");
-    Preconditions.checkNotNull(sessionManager, "Session manager is null");
-
-    this.accountStore = accountStore;
-    this.configuration = configuration;
-    this.sessionManager = sessionManager;
-    this.domain = domain.toLowerCase();
-    this.isClientAuthEnabled = config.getBoolean("security.enable_clientauth");
-    this.clientAuthCertDomain = 
config.getString("security.clientauth_cert_domain").toLowerCase();
-    this.isRegistrationDisabled = 
config.getBoolean("administration.disable_registration");
-    this.isLoginPageDisabled = 
config.getBoolean("administration.disable_loginpage");
-    this.welcomeBot = welcomeBot;
-    this.analyticsAccount = 
config.getString("administration.analytics_account");
-  }
-
-  @SuppressWarnings("unchecked")
-  private LoginContext login(BufferedReader body) throws IOException, 
LoginException {
-    try {
-      Subject subject = new Subject();
-
-      String parametersLine = body.readLine();
-      // Throws UnsupportedEncodingException.
-      byte[] utf8Bytes = parametersLine.getBytes("UTF-8");
-
-      CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
-      utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
-      utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
-
-      // Throws CharacterCodingException.
-      CharBuffer parsed = utf8Decoder.decode(ByteBuffer.wrap(utf8Bytes));
-      parametersLine = parsed.toString();
-
-      MultiMap<String> parameters = new UrlEncoded(parametersLine);
-      CallbackHandler callbackHandler = new 
HttpRequestBasedCallbackHandler(parameters);
-
-      LoginContext context = new LoginContext("Wave", subject, 
callbackHandler, configuration);
-
-      // If authentication fails, login() will throw a LoginException.
-      context.login();
-      return context;
-    } catch (CharacterCodingException cce) {
-      throw new LoginException("Character coding exception (not utf-8): "
-          + cce.getLocalizedMessage());
-    } catch (UnsupportedEncodingException uee) {
-      throw new LoginException("ad character encoding specification: " + 
uee.getLocalizedMessage());
-    }
-  }
-
-  /**
-   * The POST request should have all the fields required for authentication.
-   */
-  @Override
-  protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    req.setCharacterEncoding("UTF-8");
-    LoginContext context;
-    Subject subject;
-    ParticipantId loggedInAddress = null;
-
-    if (isClientAuthEnabled) {
-      boolean skipClientAuth = false;
-      try {
-        X509Certificate[] certs = (X509Certificate[]) 
req.getAttribute("javax.servlet.request.X509Certificate");
-
-        if (certs == null) {
-          if (isLoginPageDisabled) {
-            throw new IllegalStateException(
-                "No client X.509 certificate provided (you need to get a 
certificate"
-                    + "from your systems manager and import it into your 
browser).");
-          }
-          else {
-            failedClientAuth = true;
-            skipClientAuth = true;
-            doGet(req, resp);
-          }
-        }
-
-        if (!skipClientAuth) {
-          failedClientAuth = false;
-          subject = new Subject();
-          for (X509Certificate cert : certs) {
-            X500Principal principal = cert.getSubjectX500Principal();
-            subject.getPrincipals().add(principal);
-          }
-          loggedInAddress = getLoggedInUser(subject);
-        }
-      } catch (InvalidParticipantAddress e1) {
-        throw new IllegalStateException(
-            "The user provided valid authentication information, but the 
username"
-                + " isn't a valid user address.");
-      }
-    }
-
-    if (!isLoginPageDisabled && loggedInAddress == null) {
-      try {
-        context = login(req.getReader());
-      } catch (LoginException e) {
-        String message = "The username or password you entered is incorrect.";
-        String responseType = RESPONSE_STATUS_FAILED;
-        LOG.info("User authentication failed: " + e.getLocalizedMessage());
-        resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
-        resp.setContentType("text/html;charset=utf-8");
-        AuthenticationPage.write(resp.getWriter(), new 
GxpContext(req.getLocale()), domain, message,
-            responseType, isLoginPageDisabled, analyticsAccount);
-        return;
-      }
-
-      subject = context.getSubject();
-
-      try {
-        loggedInAddress = getLoggedInUser(subject);
-      } catch (InvalidParticipantAddress e1) {
-        throw new IllegalStateException(
-            "The user provided valid authentication information, but the 
username"
-                + " isn't a valid user address.");
-      }
-
-      if (loggedInAddress == null) {
-        try {
-          context.logout();
-        } catch (LoginException e) {
-          // Logout failed. Absorb the error, since we're about to throw an
-          // illegal state exception anyway.
-        }
-
-        throw new IllegalStateException(
-            "The user provided valid authentication information, but we don't "
-                + "know how to map their identity to a wave user address.");
-      }
-    }
-
-    HttpSession session = req.getSession(true);
-    sessionManager.setLoggedInUser(session, loggedInAddress);
-    LOG.info("Authenticated user " + loggedInAddress);
-
-    redirectLoggedInUser(req, resp);
-  }
-
-  /**
-   * Get the participant id of the given subject.
-   *
-   * The subject is searched for compatible principals. When other
-   * authentication types are added, this method will need to be updated to
-   * support their principal types.
-   *
-   * @throws InvalidParticipantAddress The subject's address is invalid
-   */
-  private ParticipantId getLoggedInUser(Subject subject) throws 
InvalidParticipantAddress {
-    String address = null;
-
-    for (Principal p : subject.getPrincipals()) {
-      // TODO(josephg): When we support other authentication types (LDAP, etc),
-      // this method will need to read the address portion out of the other 
principal types.
-      if (p instanceof ParticipantPrincipal) {
-        address = ((ParticipantPrincipal) p).getName();
-        break;
-      } else if (p instanceof X500Principal) {
-        return attemptClientCertificateLogin((X500Principal)p);
-      }
-    }
-
-    return address == null ? null : ParticipantId.of(address);
-  }
-
-  /**
-   * Attempts to authenticate the user using their client certificate.
-   *
-   * Retrieves the email from their certificate, using it as the wave username.
-   * If the user doesn't exist and registration is enabled, it will 
automatically create an account
-   * before continuing. Otherwise it will simply check if the account exists 
and authenticate based
-   * on that.
-   *
-   * @throws RuntimeException The encoding of the email is unsupported on this 
system
-   * @throws InvalidParticipantAddress The email address doesn't correspond to 
an account
-   */
-  private ParticipantId attemptClientCertificateLogin(X500Principal p)
-      throws RuntimeException, InvalidParticipantAddress {
-    String distinguishedName = p.getName();
-    try {
-      LdapName ldapName = new LdapName(distinguishedName);
-      for (Rdn rdn: ldapName.getRdns()) {
-        if (rdn.getType().equals(OID_EMAIL)) {
-          String email = decodeEmailFromCertificate((byte[])rdn.getValue());
-          if (email.endsWith("@" + clientAuthCertDomain)) {
-            // Check we decoded the string correctly.
-            Preconditions.checkState(WaveIdentifiers.isValidIdentifier(email),
-                "The decoded email is not a valid wave identifier");
-            ParticipantId id = ParticipantId.of(email);
-            if (!RegistrationUtil.doesAccountExist(accountStore, id)) {
-              if (!isRegistrationDisabled) {
-                if (!RegistrationUtil.createAccountIfMissing(accountStore, id, 
null, welcomeBot)) {
-                  return null;
-                }
-              } else {
-                throw new InvalidNameException(
-                    "User doesn't already exist, and registration disabled by 
administrator");
-              }
-            }
-            return id;
-          }
-        }
-      }
-    } catch (UnsupportedEncodingException ex) {
-      throw new RuntimeException(ex);
-    } catch (InvalidNameException ex) {
-      throw new InvalidParticipantAddress(distinguishedName,
-          "Certificate does not contain a valid distinguished name");
-    }
-    return null;
-  }
-
-  /**
-   * Decodes the user email from the X.509 certificate.
-   *
-   * Email address is assumed to be valid in ASCII, and less than 128 
characters long
-   *
-   * @param encoded Output from rdn.getValue(). 1st byte is the tag, second is 
the length.
-   * @return The decoded email in ASCII
-   * @throws UnsupportedEncodingException The email address wasn't in ASCII
-   */
-  private String decodeEmailFromCertificate(byte[] encoded) throws 
UnsupportedEncodingException {
-    // Check for < 130, since first 2 bytes are taken up as stated above.
-    Preconditions.checkState(encoded.length < 130,"The email address is longer 
than expected");
-    return new String(encoded, 2, encoded.length - 2, "ascii");
-  }
-
-  /**
-   * On GET, present a login form if the user isn't authenticated.
-   */
-  @Override
-  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws IOException {
-    // If the user is already logged in, we'll try to redirect them 
immediately.
-    resp.setCharacterEncoding("UTF-8");
-    req.setCharacterEncoding("UTF-8");
-    HttpSession session = req.getSession(false);
-    ParticipantId user = sessionManager.getLoggedInUser(session);
-
-    if (user != null) {
-      redirectLoggedInUser(req, resp);
-    } else {
-      if (isClientAuthEnabled && !failedClientAuth) {
-          X509Certificate[] certs = (X509Certificate[]) 
req.getAttribute("javax.servlet.request.X509Certificate");
-          if (certs != null) {
-            doPost(req, resp);
-          }
-      }
-
-      if (!isLoginPageDisabled) {
-        resp.setStatus(HttpServletResponse.SC_OK);
-      }
-      else {
-        resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
-      }
-      resp.setContentType("text/html;charset=utf-8");
-      AuthenticationPage.write(resp.getWriter(), new 
GxpContext(req.getLocale()), domain, "",
-          RESPONSE_STATUS_NONE, isLoginPageDisabled, analyticsAccount);
-    }
-  }
-
-  /**
-   * Redirect the user back to DEFAULT_REDIRECT_URL, unless a custom redirect
-   * URL has been specified in the query string; in which case redirect there.
-   *
-   * Only redirects to local URLs are allowed.
-   *
-   * @throws IOException
-   */
-  private void redirectLoggedInUser(HttpServletRequest req, 
HttpServletResponse resp)
-      throws IOException {
-     
Preconditions.checkState(sessionManager.getLoggedInUser(req.getSession(false)) 
!= null,
-         "The user is not logged in");
-    String query = req.getQueryString();
-
-    // Not using req.getParameter() for this because calling that method might 
parse the password
-    // sitting in POST data into a String, where it could be read by another 
process after the
-    // string is garbage collected.
-    if (query == null || !query.startsWith("r=")) {
-      resp.sendRedirect(DEFAULT_REDIRECT_URL);
-      return;
-    }
-
-    String encoded_url = query.substring("r=".length());
-    String path = URLDecoder.decode(encoded_url, "UTF-8");
-
-    // The URL must not be an absolute URL to prevent people using this as a
-    // generic redirection service.
-    URI uri;
-    try {
-      uri = new URI(path);
-    } catch (URISyntaxException e) {
-      // The redirect URL is invalid.
-      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-      return;
-    }
-
-    if (Strings.isNullOrEmpty(uri.getHost()) == false) {
-      // The URL includes a host component. Disallow it.
-      resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-    } else {
-      resp.sendRedirect(path);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/rpc/ClientRpcChannel.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/rpc/ClientRpcChannel.java 
b/src/org/waveprotocol/box/server/rpc/ClientRpcChannel.java
deleted file mode 100644
index 148c58a..0000000
--- a/src/org/waveprotocol/box/server/rpc/ClientRpcChannel.java
+++ /dev/null
@@ -1,36 +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.rpc;
-
-import com.google.protobuf.RpcChannel;
-import com.google.protobuf.RpcController;
-
-/**
- * Provides the client end-point of a wave server connection. Used to generate
- * usable Stub implementations of any service type.
- */
-public interface ClientRpcChannel extends RpcChannel {
-  /**
-   * Return a new RpcController for users of this RpcChannel.
-   * 
-   * @return the new RpcController implementation
-   */
-  public RpcController newRpcController();
-}

Reply via email to