http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/OperationContextImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/OperationContextImpl.java b/src/org/waveprotocol/box/server/robots/OperationContextImpl.java deleted file mode 100644 index 03874ea..0000000 --- a/src/org/waveprotocol/box/server/robots/OperationContextImpl.java +++ /dev/null @@ -1,406 +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; - -import static org.waveprotocol.box.server.robots.util.RobotsUtil.createEmptyRobotWavelet; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.wave.api.ApiIdSerializer; -import com.google.wave.api.InvalidRequestException; -import com.google.wave.api.JsonRpcConstant.ParamsProperty; -import com.google.wave.api.JsonRpcResponse; -import com.google.wave.api.OperationRequest; -import com.google.wave.api.data.converter.EventDataConverter; -import com.google.wave.api.event.Event; -import com.google.wave.api.event.EventSerializationException; -import com.google.wave.api.event.EventSerializer; -import com.google.wave.api.event.EventType; -import com.google.wave.api.event.OperationErrorEvent; - -import org.waveprotocol.box.common.Receiver; -import org.waveprotocol.box.server.frontend.CommittedWaveletSnapshot; -import org.waveprotocol.box.server.robots.util.ConversationUtil; -import org.waveprotocol.box.server.robots.util.OperationUtil; -import org.waveprotocol.box.server.waveserver.WaveServerException; -import org.waveprotocol.box.server.waveserver.WaveletProvider; -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.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.TransformedWaveletDelta; -import org.waveprotocol.wave.model.schema.SchemaCollection; -import org.waveprotocol.wave.model.version.HashedVersion; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.wave.data.ObservableWaveletData; -import org.waveprotocol.wave.model.wave.data.impl.ObservablePluggableMutableDocument; -import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl; -import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet; -import org.waveprotocol.wave.util.logging.Log; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Class which provides context for robot operations and gives access to the - * results. - * - * @author [email protected] (Lennard de Rijk) - */ -public class OperationContextImpl implements OperationContext, OperationResults { - - private static final Log LOG = Log.get(OperationContextImpl.class); - - private static final ObservableWaveletData.Factory<? extends ObservableWaveletData> FACTORY = - WaveletDataImpl.Factory.create( - ObservablePluggableMutableDocument.createFactory(SchemaCollection.empty())); - - /** - * Maps operation ID's to responses. - */ - private final Map<String, JsonRpcResponse> responses = Maps.newHashMap(); - - /** - * {@link WaveletProvider} that gives us access to wavelets. - */ - private final WaveletProvider waveletProvider; - - /** - * {@link EventDataConverter} that can convert to - * {@link com.google.wave.api.impl.WaveletData} and such. - */ - private final EventDataConverter converter; - - /** - * The wavelet to which this context is bound, null if unbound. - */ - private final RobotWaveletData boundWavelet; - - /** - * The wavelets that have been opened in the lifespan of this context. - */ - private final Map<WaveletName, RobotWaveletData> openedWavelets = Maps.newHashMap(); - - /** Stores temporary blip ids -> real blip ids */ - private final Map<String, String> tempBlipIdMap = Maps.newHashMap(); - /** Stores temporary wavelet names -> real wavelet names */ - private final Map<WaveletName, WaveletName> tempWaveletNameMap = Maps.newHashMap(); - /** Caches {@link ObservableConversationView}s */ - private final Map<WaveletName, Map<ParticipantId, ObservableConversationView>> - openedConversations; - - /** Used to create conversations. */ - private final ConversationUtil conversationUtil; - - /** - * Constructs an operation context not bound to any wavelet. - * - * @param waveletProvider the waveletprovider to use for querying wavelet. - * @param converter {@link EventDataConverter} for converting from server side - * objects. - * @param conversationUtil used to create conversations. - */ - public OperationContextImpl(WaveletProvider waveletProvider, EventDataConverter converter, - ConversationUtil conversationUtil) { - this(waveletProvider, converter, conversationUtil, null); - } - - /** - * Constructs a bound operation context. The bound wavelet is added to the - * list of open wavelets. - * - * @param waveletProvider the waveletprovider to use for querying wavelet. - * @param converter {@link EventDataConverter} for converting from server side - * objects. - * @param boundWavelet the wavelet to bind this context to, null for an - * unbound context. - * @param conversationUtil used to create conversations. - */ - public OperationContextImpl(WaveletProvider waveletProvider, EventDataConverter converter, - ConversationUtil conversationUtil, RobotWaveletData boundWavelet) { - this.waveletProvider = waveletProvider; - this.converter = converter; - this.conversationUtil = conversationUtil; - this.boundWavelet = boundWavelet; - this.openedConversations = Maps.newHashMap(); - - if (boundWavelet != null) { - openedWavelets.put(boundWavelet.getWaveletName(), boundWavelet); - } - } - - // OperationContext implementation begins here - - @Override - public EventDataConverter getConverter() { - return converter; - } - - @Override - public boolean isBound() { - return boundWavelet != null; - } - - @Override - public Map<WaveletName, RobotWaveletData> getOpenWavelets() { - return Collections.unmodifiableMap(openedWavelets); - } - - @Override - public void constructResponse(OperationRequest operation, Map<ParamsProperty, Object> data) { - setResponse(operation.getId(), JsonRpcResponse.result(operation.getId(), data)); - } - - @Override - public void constructErrorResponse(OperationRequest operation, String errorMessage) { - setResponse(operation.getId(), JsonRpcResponse.error(operation.getId(), errorMessage)); - } - - @Override - public void processEvent(OperationRequest operation, Event event) throws InvalidRequestException { - // Create JSON-RPC error response. - if (event.getType() == EventType.OPERATION_ERROR) { - constructErrorResponse(operation, OperationErrorEvent.as(event).getMessage()); - return; - } - // Create JSON-RPC success response. - try { - constructResponse(operation, EventSerializer.extractPropertiesToParamsPropertyMap(event)); - } catch (EventSerializationException e) { - LOG.severe("Internal Error occurred, when serializing events", e); - throw new InvalidRequestException("Unable to serialize events", operation); - } - } - - @Override - public void putWavelet(WaveId waveId, WaveletId waveletId, RobotWaveletData newWavelet) { - WaveletName waveletName = newWavelet.getWaveletName(); - Preconditions.checkArgument(!openedWavelets.containsKey(waveletName), - "Not allowed to put an already open wavelet in as a new wavelet"); - - // New wavelets are indicated by the temporary marker in their waveId. - if (waveId.getId().startsWith(TEMP_ID_MARKER)) { - tempWaveletNameMap.put(WaveletName.of(waveId, waveletId), waveletName); - } - openedWavelets.put(waveletName, newWavelet); - } - - @Override - public OpBasedWavelet openWavelet(WaveId waveId, WaveletId waveletId, ParticipantId participant) - throws InvalidRequestException { - WaveletName waveletName; - if (waveId.getId().startsWith(TEMP_ID_MARKER)) { - WaveletName tempWaveletName = WaveletName.of(waveId, waveletId); - waveletName = tempWaveletNameMap.get(tempWaveletName); - } else { - waveletName = WaveletName.of(waveId, waveletId); - } - - RobotWaveletData wavelet = openedWavelets.get(waveletName); - if (wavelet == null) { - // Open a wavelet from the server - CommittedWaveletSnapshot snapshot = getWaveletSnapshot(waveletName, participant); - if (snapshot == null) { - if (waveletName.waveletId.equals(IdUtil.buildUserDataWaveletId(participant))) { - // Usually the user data is created by the web client whenever user - // opens a wavelet for the first time. However, if the wavelet is - // fetched for the first time with Robot/Data API - user data should be - // created here. - wavelet = createEmptyRobotWavelet(participant, waveletName); - } else { - throw new InvalidRequestException("Wavelet " + waveletName + " couldn't be retrieved"); - } - - } else { - ObservableWaveletData obsWavelet = FACTORY.create(snapshot.snapshot); - wavelet = new RobotWaveletData(obsWavelet, snapshot.committedVersion); - } - openedWavelets.put(waveletName, wavelet); - } - return wavelet.getOpBasedWavelet(participant); - } - - @Override - public OpBasedWavelet openWavelet(OperationRequest operation, ParticipantId participant) - throws InvalidRequestException { - try { - WaveId waveId = ApiIdSerializer.instance().deserialiseWaveId( - OperationUtil.<String>getRequiredParameter(operation, ParamsProperty.WAVE_ID)); - WaveletId waveletId = ApiIdSerializer.instance().deserialiseWaveletId( - OperationUtil.<String>getRequiredParameter(operation, ParamsProperty.WAVELET_ID)); - return openWavelet(waveId, waveletId, participant); - } catch (InvalidIdException e) { - throw new InvalidRequestException("Invalid id", operation, e); - } - } - - @Override - public ObservableConversationView openConversation(WaveId waveId, WaveletId waveletId, - ParticipantId participant) throws InvalidRequestException { - WaveletName waveletName = WaveletName.of(waveId, waveletId); - - if (!openedConversations.containsKey(waveletName)) { - openedConversations.put( - waveletName, Maps.<ParticipantId, ObservableConversationView> newHashMap()); - } - - Map<ParticipantId, ObservableConversationView> conversations = - openedConversations.get(waveletName); - - if (!conversations.containsKey(participant)) { - OpBasedWavelet wavelet = openWavelet(waveId, waveletId, participant); - conversations.put(participant, conversationUtil.buildConversation(wavelet)); - } - return conversations.get(participant); - } - - @Override - public ObservableConversationView openConversation( - OperationRequest operation, ParticipantId participant) throws InvalidRequestException { - try { - WaveId waveId = ApiIdSerializer.instance().deserialiseWaveId( - OperationUtil.<String>getRequiredParameter(operation, ParamsProperty.WAVE_ID)); - WaveletId waveletId = ApiIdSerializer.instance().deserialiseWaveletId( - OperationUtil.<String>getRequiredParameter(operation, ParamsProperty.WAVELET_ID)); - return openConversation(waveId, waveletId, participant); - } catch (InvalidIdException e) { - throw new InvalidRequestException("Invalid id", operation, e); - } - } - - // OperationResults implementation begins here - - @Override - public void putBlip(String blipId, ConversationBlip newBlip) { - if (blipId.startsWith(TEMP_ID_MARKER)) { - tempBlipIdMap.put(blipId, newBlip.getId()); - } - } - - @Override - public ConversationBlip getBlip(Conversation conversation, String blipId) - throws InvalidRequestException { - // We might need to look up the blip id for new blips. - String actualBlipId = blipId.startsWith(TEMP_ID_MARKER) ? tempBlipIdMap.get(blipId) : blipId; - - ConversationBlip blip = conversation.getBlip(actualBlipId); - if (blip == null) { - throw new InvalidRequestException( - "Blip with id " + blipId + " does not exist or has been deleted"); - } - - return blip; - } - - // OperationResults implementation begins here - - @Override - public ConversationUtil getConversationUtil() { - return conversationUtil; - } - - @Override - public Map<String, JsonRpcResponse> getResponses() { - return Collections.unmodifiableMap(responses); - } - - @Override - public JsonRpcResponse getResponse(String operationId) { - return responses.get(operationId); - } - - @Override - public boolean hasResponse(String operationId) { - return responses.containsKey(operationId); - } - - @Override - public ImmutableSet<WaveletId> getVisibleWaveletIds(OperationRequest operation, ParticipantId participant) - throws InvalidRequestException { - Set<WaveletId> waveletIds = new HashSet<WaveletId>(); - try { - WaveId waveId = ApiIdSerializer.instance().deserialiseWaveId( - OperationUtil.<String>getRequiredParameter(operation, ParamsProperty.WAVE_ID)); - ImmutableSet<WaveletId> ids = waveletProvider.getWaveletIds(waveId); - for (WaveletId waveletId: ids) { - WaveletName waveletName = WaveletName.of(waveId, waveletId); - if (waveletProvider.checkAccessPermission(waveletName, participant)) { - waveletIds.add(waveletId); - } - } - } catch (InvalidIdException ex) { - throw new InvalidRequestException("Invalid id", operation, ex); - } catch (WaveServerException e) { - LOG.severe("Error of access to wave", e); - } - return ImmutableSet.copyOf(waveletIds); - } - - @Override - public CommittedWaveletSnapshot getWaveletSnapshot(WaveletName waveletName, ParticipantId participant) - throws InvalidRequestException { - try { - if (!waveletProvider.checkAccessPermission(waveletName, participant)) { - throw new InvalidRequestException("Access rejected"); - } - return waveletProvider.getSnapshot(waveletName); - } catch (WaveServerException ex) { - LOG.severe("Error of access to wavelet " + waveletName, ex); - return null; - } - } - - @Override - public void getDeltas(WaveletName waveletName, ParticipantId participant, - HashedVersion fromVersion, HashedVersion toVersion, Receiver<TransformedWaveletDelta> receiver) - throws InvalidRequestException { - try { - if (!waveletProvider.checkAccessPermission(waveletName, participant)) { - throw new InvalidRequestException("Access rejected"); - } - Preconditions.checkState(fromVersion.compareTo(toVersion) <= 0); - if (fromVersion.equals(toVersion)) { - return; - } - waveletProvider.getHistory(waveletName, fromVersion, toVersion, receiver); - } catch (WaveServerException ex) { - LOG.severe("Error of access to wavelet " + waveletName, ex); - } - } - - /** - * Stores a response in this context. - * - * @param operationId the id of the robot operation. - * @param response the response to store. - */ - private void setResponse(String operationId, JsonRpcResponse response) { - Preconditions.checkState( - !responses.containsKey(operationId), "Overwriting an existing response"); - responses.put(operationId, response); - } -}
http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/OperationResults.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/OperationResults.java b/src/org/waveprotocol/box/server/robots/OperationResults.java deleted file mode 100644 index 874e5fe..0000000 --- a/src/org/waveprotocol/box/server/robots/OperationResults.java +++ /dev/null @@ -1,54 +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; - -import com.google.wave.api.JsonRpcResponse; - -import org.waveprotocol.wave.model.id.WaveletName; - -import java.util.Map; - -/** - * Interface for accessing robot operation results. - * - * @author [email protected] (Lennard de Rijk) - */ -public interface OperationResults { - - /** - * Returns an unmodifiable view of all wavelets that have been opened when - * performing robot operations. - */ - Map<WaveletName, RobotWaveletData> getOpenWavelets(); - - /** - * Returns an unmodifiable view of all responses that have been generated by - * performing robot operations. - */ - Map<String, JsonRpcResponse> getResponses(); - - /** - * Returns a response for a specific robot operation. - * - * @param operationId the id of the robot operation to get the response for. - * @return returns a {@link JsonRpcResponse} if set else null. - */ - JsonRpcResponse getResponse(String operationId); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/OperationServiceRegistry.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/OperationServiceRegistry.java b/src/org/waveprotocol/box/server/robots/OperationServiceRegistry.java deleted file mode 100644 index 9ddac1b..0000000 --- a/src/org/waveprotocol/box/server/robots/OperationServiceRegistry.java +++ /dev/null @@ -1,45 +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; - -import com.google.wave.api.InvalidRequestException; -import com.google.wave.api.OperationType; - -import org.waveprotocol.box.server.robots.operations.OperationService; - -/** - * Registry for accessing an {@link OperationService} to execute operations in - * the Robot APIs. - * - * @author [email protected] (Lennard de Rijk) - */ -public interface OperationServiceRegistry { - - /** - * Retrieves the {@link OperationService} for the given {@link OperationType}. - * - * @param opType the type of operation to retrieve the service for - * @return {@link OperationService} registered for the given - * {@link OperationType} - * @throws InvalidRequestException if no {@link OperationService} could be - * found. - */ - OperationService getServiceFor(OperationType opType) throws InvalidRequestException; -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/ProfileFetcherModule.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/ProfileFetcherModule.java b/src/org/waveprotocol/box/server/robots/ProfileFetcherModule.java deleted file mode 100644 index 7374bfc..0000000 --- a/src/org/waveprotocol/box/server/robots/ProfileFetcherModule.java +++ /dev/null @@ -1,55 +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; - -import com.google.inject.AbstractModule; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.typesafe.config.Config; -import org.waveprotocol.box.server.robots.operations.FetchProfilesService.ProfilesFetcher; -import org.waveprotocol.box.server.robots.operations.GravatarProfilesFetcher; -import org.waveprotocol.box.server.robots.operations.InitialsProfilesFetcher; - -/** - * Profile Fetcher Module. - * - * @author [email protected] (Vicente J. Ruiz Jurado) - */ -public class ProfileFetcherModule extends AbstractModule { - - - private String profileFetcherType; - - @Inject - public ProfileFetcherModule(Config config) { - this.profileFetcherType = config.getString("core.profile_fetcher_type"); - } - - @Override - protected void configure() { - if ("gravatar".equals(profileFetcherType)) { - bind(ProfilesFetcher.class).to(GravatarProfilesFetcher.class).in(Singleton.class); - } else if ("initials".equals(profileFetcherType)) { - bind(ProfilesFetcher.class).to(InitialsProfilesFetcher.class).in(Singleton.class); - } else { - throw new RuntimeException("Unknown profile fetcher type: " + profileFetcherType); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/RobotApiModule.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/RobotApiModule.java b/src/org/waveprotocol/box/server/robots/RobotApiModule.java deleted file mode 100644 index e757080..0000000 --- a/src/org/waveprotocol/box/server/robots/RobotApiModule.java +++ /dev/null @@ -1,156 +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; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.inject.AbstractModule; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Provides; -import com.google.inject.Singleton; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import com.google.wave.api.RobotSerializer; -import com.google.wave.api.data.converter.EventDataConverterModule; -import com.google.wave.api.robot.HttpRobotConnection; -import com.google.wave.api.robot.RobotConnection; - -import com.typesafe.config.Config; -import net.oauth.OAuthServiceProvider; -import net.oauth.OAuthValidator; -import net.oauth.SimpleOAuthValidator; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.waveprotocol.box.server.robots.active.ActiveApiOperationServiceRegistry; -import org.waveprotocol.box.server.robots.dataapi.DataApiOAuthServlet; -import org.waveprotocol.box.server.robots.dataapi.DataApiOperationServiceRegistry; -import org.waveprotocol.box.server.robots.passive.RobotConnector; - -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; - -/** - * Robot API Module. - * - * @author [email protected] (Lennard de Rijk) - */ -public class RobotApiModule extends AbstractModule { - - private static final int NUMBER_OF_THREADS = 10; - - private static final String AUTHORIZE_TOKEN_PATH = "/OAuthAuthorizeToken"; - private static final String REQUEST_TOKEN_PATH = "/OAuthGetRequestToken"; - private static final String ACCESS_TOKEN_PATH = "/OAuthGetAccessToken"; - private static final String ALL_TOKENS_PATH = "/OAuthGetAllTokens"; - - @Override - protected void configure() { - install(new EventDataConverterModule()); - install(new RobotSerializerModule()); - - bind(String.class).annotatedWith(Names.named("authorize_token_path")).toInstance( - AUTHORIZE_TOKEN_PATH); - bind(String.class).annotatedWith(Names.named("request_token_path")).toInstance( - REQUEST_TOKEN_PATH); - bind(String.class).annotatedWith(Names.named("access_token_path")).toInstance( - ACCESS_TOKEN_PATH); - bind(String.class).annotatedWith(Names.named("all_tokens_path")).toInstance( - ALL_TOKENS_PATH); - } - - @Provides - @Inject - @Singleton - protected RobotConnector provideRobotConnector( - RobotConnection connection, RobotSerializer serializer) { - return new RobotConnector(connection, serializer); - } - - @Provides - @Singleton - protected RobotConnection provideRobotConnection() { - HttpClient httpClient = new HttpClient(new MultiThreadedHttpConnectionManager()); - - ThreadFactory threadFactory = - new ThreadFactoryBuilder().setNameFormat("RobotConnection").build(); - return new HttpRobotConnection( - httpClient, Executors.newFixedThreadPool(NUMBER_OF_THREADS, threadFactory)); - } - - @Provides - @Singleton - @Named("GatewayExecutor") - protected Executor provideGatewayExecutor() { - ThreadFactory threadFactory = - new ThreadFactoryBuilder().setNameFormat("PassiveRobotRunner").build(); - return Executors.newFixedThreadPool(NUMBER_OF_THREADS, threadFactory); - } - - @Provides - @Singleton - @Inject - @Named("ActiveApiRegistry") - protected OperationServiceRegistry provideActiveApiRegistry(Injector injector) { - return new ActiveApiOperationServiceRegistry(injector); - } - - @Provides - @Singleton - @Inject - @Named("DataApiRegistry") - protected OperationServiceRegistry provideDataApiRegistry(Injector injector) { - return new DataApiOperationServiceRegistry(injector); - } - - @Provides - @Singleton - protected OAuthValidator provideOAuthValidator() { - // TODO(ljvderijk): This isn't an industrial strength validator, it grows - // over time. It should be replaced or cleaned out on a regular interval. - return new SimpleOAuthValidator(); - } - - @Provides - @Singleton - protected OAuthServiceProvider provideOAuthServiceProvider(Config config) { - String publicAddress = config.getString("core.http_frontend_public_address"); - // Three urls, first is to get an unauthorized request token, second is to - // authorize the request token, third is to exchange the authorized request - // token with an access token. - String requestTokenUrl = getOAuthUrl(publicAddress, REQUEST_TOKEN_PATH); - String authorizeTokenUrl = getOAuthUrl(publicAddress, AUTHORIZE_TOKEN_PATH); - String accessTokenUrl = getOAuthUrl(publicAddress, ACCESS_TOKEN_PATH); - - return new OAuthServiceProvider(requestTokenUrl, authorizeTokenUrl, accessTokenUrl); - } - - /** - * Returns the full url used to do 3-legged OAuth in the data api. - * - * @param publicAddress the address of the http frontend - * @param postFix the end part of the url - */ - private String getOAuthUrl(String publicAddress, String postFix) { - return String.format( - "http://%s%s%s", publicAddress, DataApiOAuthServlet.DATA_API_OAUTH_PATH, postFix); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/RobotCapabilities.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/RobotCapabilities.java b/src/org/waveprotocol/box/server/robots/RobotCapabilities.java deleted file mode 100644 index c7c7e04..0000000 --- a/src/org/waveprotocol/box/server/robots/RobotCapabilities.java +++ /dev/null @@ -1,128 +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; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.wave.api.ProtocolVersion; -import com.google.wave.api.event.EventType; -import com.google.wave.api.robot.Capability; - -import java.util.Map; - -/** - * Represents the capabilities that have been retrieved from a robot's - * capabilities.xml file. - * - * @author [email protected] (Lennard de Rijk) - */ -public class RobotCapabilities { - - private final Map<EventType, Capability> capabilities; - private final String capabilitiesHash; - private final ProtocolVersion version; - - /** - * Constructs a new {@link RobotCapabilities} object with the given data. - * - * @param capabilitiesMap mapping events to capabilities for this robot. - * @param capabilitiesHash the hash of the robot's capabilities. - * @param version the {@link ProtocolVersion} the robot speaks. - */ - public RobotCapabilities(Map<EventType, Capability> capabilitiesMap, String capabilitiesHash, - ProtocolVersion version) { - Preconditions.checkNotNull(capabilitiesMap, "Capabilities map may not be null"); - Preconditions.checkNotNull(capabilitiesHash, "Capabilities hash may not be null"); - Preconditions.checkNotNull(version, "Version may not be null"); - - this.capabilities = ImmutableMap.copyOf(capabilitiesMap); - this.capabilitiesHash = capabilitiesHash; - this.version = version; - } - - /** - * Returns the capabilities map of the robot. - */ - public Map<EventType, Capability> getCapabilitiesMap() { - return capabilities; - } - - /** - * Returns the capabilities hash. - */ - public String getCapabilitiesHash() { - return capabilitiesHash; - } - - /** - * Returns the {@link ProtocolVersion} that the robot speaks. - */ - public ProtocolVersion getProtocolVersion() { - return version; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((capabilities == null) ? 0 : capabilities.hashCode()); - result = prime * result + ((capabilitiesHash == null) ? 0 : capabilitiesHash.hashCode()); - result = prime * result + ((version == null) ? 0 : version.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof RobotCapabilities)) return false; - RobotCapabilities other = (RobotCapabilities) obj; - if (capabilities == null) { - if (other.capabilities != null) return false; - } else if (!capabilities.equals(other.capabilities)) return false; - if (capabilitiesHash == null) { - if (other.capabilitiesHash != null) return false; - } else if (!capabilitiesHash.equals(other.capabilitiesHash)) return false; - if (version == null) { - if (other.version != null) return false; - } else if (!version.equals(other.version)) return false; - return true; - } - - @Override - public String toString() { - StringBuilder result = - new StringBuilder("RobotCapabilities[version=" + version + ",hash=" + capabilitiesHash); - for (Map.Entry<EventType, Capability> entry : capabilities.entrySet()) { - result - .append(",") - .append(entry.getKey()) - .append(":(") - .append(entry.getValue().getEventType()) - .append(",#") - .append(entry.getValue().getContexts().size()) - .append(",") - .append(entry.getValue().getFilter()) - .append(")"); - } - result.append("]"); - return result.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java b/src/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java deleted file mode 100644 index 32f7bc9..0000000 --- a/src/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java +++ /dev/null @@ -1,153 +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; - -import com.google.common.base.Strings; -import com.google.gxp.base.GxpContext; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.google.inject.name.Named; - -import com.typesafe.config.Config; -import org.waveprotocol.box.server.CoreSettingsNames; -import org.waveprotocol.box.server.account.RobotAccountData; -import org.waveprotocol.box.server.gxp.RobotRegistrationPage; -import org.waveprotocol.box.server.gxp.RobotRegistrationSuccessPage; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.register.RobotRegistrar; -import org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.util.logging.Log; - -import java.io.IOException; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Servlet for Robot Registration. - * - * @author [email protected] (Lennard de Rijk) - */ -@SuppressWarnings("serial") -@Singleton -public class RobotRegistrationServlet extends HttpServlet { - - private static final String CREATE_PATH = "/create"; - - private static final Log LOG = Log.get(RobotRegistrationServlet.class); - - private final RobotRegistrar robotRegistrar; - private final String domain; - private final String analyticsAccount; - - @Inject - private RobotRegistrationServlet(@Named(CoreSettingsNames.WAVE_SERVER_DOMAIN) String domain, - RobotRegistrar robotRegistrar, - Config config) { - this.robotRegistrar = robotRegistrar; - this.domain = domain; - this.analyticsAccount = config.getString("administration.analytics_account"); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String pathInfo = req.getPathInfo(); - if (CREATE_PATH.equals(pathInfo)) { - doRegisterGet(req, resp, ""); - } else { - resp.setStatus(HttpServletResponse.SC_NOT_FOUND); - } - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String pathInfo = req.getPathInfo(); - if (CREATE_PATH.equals(pathInfo)) { - doRegisterPost(req, resp); - } else { - resp.setStatus(HttpServletResponse.SC_NOT_FOUND); - } - } - - /** - * Handles GET request for the register page. - * - * @param message non-null but optional message to show on the page - */ - private void doRegisterGet(HttpServletRequest req, HttpServletResponse resp, String message) - throws IOException { - RobotRegistrationPage.write(resp.getWriter(), new GxpContext(req.getLocale()), domain, message, - analyticsAccount); - resp.setContentType("text/html"); - resp.setStatus(HttpServletResponse.SC_OK); - } - - /** - * Handles POST request for the register page. - */ - private void doRegisterPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String username = req.getParameter("username"); - String location = req.getParameter("location"); - - if (Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(location)) { - doRegisterGet(req, resp, "Please complete all fields."); - return; - } - - ParticipantId id; - try { - id = ParticipantId.of(username + "@" + domain); - } catch (InvalidParticipantAddress e) { - doRegisterGet(req, resp, "Invalid username specified, use alphanumeric characters only."); - return; - } - - RobotAccountData robotAccount; - try{ - robotAccount = robotRegistrar.registerNew(id, location); - } catch (RobotRegistrationException e) { - doRegisterGet(req, resp, e.getMessage()); - return; - } catch (PersistenceException e) { - LOG.severe("Failed to retrieve account data for " + id, e); - doRegisterGet(req, resp, "Failed to retrieve account data for " + id.getAddress()); - return; - } - onRegisterSuccess(req, resp, robotAccount); - } - - /** - * Shows the page that signals that a robot was successfully registered a - * robot. It will show the robot's token and token secret to use for the - * Active API. - * - * @param robotAccount the newly registered robot account. - */ - private void onRegisterSuccess(HttpServletRequest req, HttpServletResponse resp, - RobotAccountData robotAccount) throws IOException { - RobotRegistrationSuccessPage.write(resp.getWriter(), new GxpContext(req.getLocale()), - robotAccount.getId().getAddress(), robotAccount.getConsumerSecret(), analyticsAccount); - resp.setContentType("text/html"); - resp.setStatus(HttpServletResponse.SC_OK); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/RobotSerializerModule.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/RobotSerializerModule.java b/src/org/waveprotocol/box/server/robots/RobotSerializerModule.java deleted file mode 100644 index 26670ac..0000000 --- a/src/org/waveprotocol/box/server/robots/RobotSerializerModule.java +++ /dev/null @@ -1,66 +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; - -import com.google.common.collect.Maps; -import com.google.gson.Gson; -import com.google.inject.AbstractModule; -import com.google.inject.Inject; -import com.google.inject.Provides; -import com.google.inject.Singleton; -import com.google.wave.api.Attachment; -import com.google.wave.api.Element; -import com.google.wave.api.ProtocolVersion; -import com.google.wave.api.RobotSerializer; -import com.google.wave.api.impl.GsonFactory; -import com.google.wave.api.v2.ElementGsonAdaptorV2; - -import java.util.NavigableMap; - -/** - * Guice module for setting up the {@link RobotSerializer}. - * - * @author [email protected] (Lennard de Rijk) - */ -public class RobotSerializerModule extends AbstractModule { - - @Provides - @Singleton - @Inject - RobotSerializer provideRobotSerializer() { - NavigableMap<ProtocolVersion, Gson> gsons = Maps.newTreeMap(); - Gson gsonForPostV2 = new GsonFactory().create(); - gsons.put(ProtocolVersion.V2_2, gsonForPostV2); - // Remove lines below if we want to stop support for <0.22 - gsons.put(ProtocolVersion.V2_1, gsonForPostV2); - - GsonFactory factoryForV2 = new GsonFactory(); - ElementGsonAdaptorV2 elementGsonAdaptorV2 = new ElementGsonAdaptorV2(); - factoryForV2.registerTypeAdapter(Element.class, elementGsonAdaptorV2); - factoryForV2.registerTypeAdapter(Attachment.class, elementGsonAdaptorV2); - gsons.put(ProtocolVersion.V2, factoryForV2.create()); - - return new RobotSerializer(gsons, ProtocolVersion.DEFAULT); - } - - @Override - protected void configure() { - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/RobotWaveletData.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/RobotWaveletData.java b/src/org/waveprotocol/box/server/robots/RobotWaveletData.java deleted file mode 100644 index 6d80fba..0000000 --- a/src/org/waveprotocol/box/server/robots/RobotWaveletData.java +++ /dev/null @@ -1,166 +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; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import org.waveprotocol.box.server.util.WaveletDataUtil; -import org.waveprotocol.wave.model.id.WaveletName; -import org.waveprotocol.wave.model.operation.CapturingOperationSink; -import org.waveprotocol.wave.model.operation.SilentOperationSink; -import org.waveprotocol.wave.model.operation.wave.BasicWaveletOperationContextFactory; -import org.waveprotocol.wave.model.operation.wave.WaveletDelta; -import org.waveprotocol.wave.model.operation.wave.WaveletOperation; -import org.waveprotocol.wave.model.schema.SchemaCollection; -import org.waveprotocol.wave.model.version.HashedVersion; -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.ObservableWaveletData; -import org.waveprotocol.wave.model.wave.data.ReadableWaveletData; -import org.waveprotocol.wave.model.wave.data.WaveletData; -import org.waveprotocol.wave.model.wave.data.impl.ObservablePluggableMutableDocument; -import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl; -import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Represents a Wavelet opened by the Robot API. It gathers operations by - * possibly different participants and can offer up these operations as a list - * of deltas. - * - * <p> - * TODO(ljvderijk): Possible limitation of this class occurs when a robot wants - * to execute operations for multiple users in the same request where operations - * from different users depend on each other. The code will apply each operation - * to the snapshot given upon construction and not the most up to date one. - * - * @author [email protected] (Lennard de Rijk) - */ -public class RobotWaveletData { - - private final ReadableWaveletData snapshot; - - private final HashedVersion snapshotVersion; - - /** - * {@link LinkedHashMap} that maps participants to their - * {@link CapturingOperationSink}. This allows us to return deltas ordered by - * the insertion of participants into this map. - */ - private final LinkedHashMap<ParticipantId, CapturingOperationSink<WaveletOperation>> sinkMap = - Maps.newLinkedHashMap(); - - private final Map<ParticipantId, OpBasedWavelet> waveletMap = Maps.newHashMap(); - - /** - * Constructs a new {@link RobotWaveletData}. The given - * {@link ReadableWaveletData} will be copied by the constructor. - * - * @param snapshot the base {@link ReadableWaveletData} from which - * {@link OpBasedWavelet} are created. - * @param committedVersion the committed version of the given snapshot, used - * to generate deltas. - */ - public RobotWaveletData(ReadableWaveletData snapshot, HashedVersion committedVersion) { - this.snapshot = WaveletDataUtil.copyWavelet(snapshot); - this.snapshotVersion = committedVersion; - } - - /** - * Returns the name of this wavelet. - */ - public WaveletName getWaveletName() { - return WaveletDataUtil.waveletNameOf(snapshot); - } - - /** - * Returns an {@link OpBasedWavelet} on which operations can be performed. The - * operations are collected by this RobotWavelet and can be returned in the - * form of deltas by calling getDeltas(). This method will store a reference - * to the {@link OpBasedWavelet} for each unique author given. - * - * @param opAuthor the author of the operations performed on the returned - * wavelet. - */ - public OpBasedWavelet getOpBasedWavelet(ParticipantId opAuthor) { - if (waveletMap.containsKey(opAuthor)) { - return waveletMap.get(opAuthor); - } - - // Every wavelet needs another document factory because we need to set the - // wavelet after the OpBasedWavelet has been created to inject the - // CapturingOperationSink. - // TODO(ljvderijk): Proper schemas need to be enforced here. - - DocumentFactory<?> docFactory = - ObservablePluggableMutableDocument.createFactory(SchemaCollection.empty()); - - ObservableWaveletData perAuthorWavelet = - WaveletDataImpl.Factory.create(docFactory).create(snapshot); - - SilentOperationSink<WaveletOperation> executor = - SilentOperationSink.Executor.<WaveletOperation, WaveletData>build(perAuthorWavelet); - // Build sink that gathers these ops - CapturingOperationSink<WaveletOperation> output = - new CapturingOperationSink<WaveletOperation>(); - - BasicWaveletOperationContextFactory contextFactory = - new BasicWaveletOperationContextFactory(opAuthor); - OpBasedWavelet w = - new OpBasedWavelet(perAuthorWavelet.getWaveId(), perAuthorWavelet, contextFactory, - ParticipationHelper.DEFAULT, executor, output); - - // Store the new sink and wavelet - sinkMap.put(opAuthor, output); - waveletMap.put(opAuthor, w); - - return w; - } - - /** - * Returns a list of deltas for all the operations performed on this wavelet - * in order of the participants passed into getOpBasedWavelet(). The deltas - * apply to the version given during construction of the - * {@link RobotWaveletData}. - */ - public List<WaveletDelta> getDeltas() { - List<WaveletDelta> deltas = Lists.newArrayList(); - - for (Entry<ParticipantId, CapturingOperationSink<WaveletOperation>> entry : - sinkMap.entrySet()) { - ParticipantId author = entry.getKey(); - List<WaveletOperation> ops = entry.getValue().getOps(); - - if (ops.isEmpty()) { - // No ops to generate delta for - continue; - } - WaveletDelta delta = new WaveletDelta(author, snapshotVersion, ops); - deltas.add(delta); - } - return deltas; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java b/src/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java deleted file mode 100644 index fc3f56e..0000000 --- a/src/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java +++ /dev/null @@ -1,70 +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.active; - -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 active robot API. - * - * @author [email protected] (Lennard de Rijk) - */ -public final class ActiveApiOperationServiceRegistry extends AbstractOperationServiceRegistry { - - // Suppressing warnings about operations that are deprecated but still used by - // the default client libraries - @SuppressWarnings("deprecation") - @Inject - public ActiveApiOperationServiceRegistry(Injector injector) { - super(); - NotifyOperationService notifyOpService = injector.getInstance(NotifyOperationService.class); - // Register all the OperationProviders - register(OperationType.ROBOT_NOTIFY, notifyOpService); - register(OperationType.ROBOT_NOTIFY_CAPABILITIES_HASH, notifyOpService); - 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/active/ActiveApiServlet.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java b/src/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java deleted file mode 100644 index a2b46d3..0000000 --- a/src/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java +++ /dev/null @@ -1,119 +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.active; - -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.OAuthConsumer; -import net.oauth.OAuthMessage; -import net.oauth.OAuthServiceProvider; -import net.oauth.OAuthValidator; -import net.oauth.server.HttpRequestMessage; - -import org.waveprotocol.box.server.account.AccountData; -import org.waveprotocol.box.server.persistence.AccountStore; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.OperationServiceRegistry; -import org.waveprotocol.box.server.robots.dataapi.BaseApiServlet; -import org.waveprotocol.box.server.robots.util.ConversationUtil; -import org.waveprotocol.box.server.waveserver.WaveletProvider; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -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 Active Api. - * - * @author [email protected] (Lennard de Rijk) - */ -@SuppressWarnings("serial") -@Singleton -public class ActiveApiServlet extends BaseApiServlet { - - private static final Log LOG = Log.get(ActiveApiServlet.class); - private final OAuthServiceProvider oauthServiceProvider; - private final AccountStore accountStore; - - @Inject - public ActiveApiServlet(RobotSerializer robotSerializer, - EventDataConverterManager converterManager, WaveletProvider waveletProvider, - @Named("ActiveApiRegistry") OperationServiceRegistry operationRegistry, - ConversationUtil conversationUtil, OAuthServiceProvider oAuthServiceProvider, - OAuthValidator validator, AccountStore accountStore) { - super(robotSerializer, converterManager, waveletProvider, operationRegistry, conversationUtil, - validator); - this.oauthServiceProvider = oAuthServiceProvider; - this.accountStore = accountStore; - } - - /** - * Entry point for the Active Api Calls. - */ - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - OAuthMessage message = new HttpRequestMessage(req, req.getRequestURL().toString()); - // OAuth %-escapes the @ in the username so we need to decode it. - String username = OAuth.decodePercent(message.getConsumerKey()); - - ParticipantId participant; - try { - participant = ParticipantId.of(username); - } catch (InvalidParticipantAddress e) { - LOG.info("Participant id invalid", e); - resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - return; - } - - AccountData account; - try { - account = accountStore.getAccount(participant); - } catch (PersistenceException e) { - LOG.severe("Failed to retrieve account data for " + participant, e); - resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "An unexpected error occured while trying to retrieve account data for " - + participant.getAddress()); - return; - } - if (account == null || !account.isRobot()) { - LOG.info("The account for robot named " + participant + " does not exist"); - resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - return; - } - - OAuthConsumer consumer = - new OAuthConsumer(null, participant.getAddress(), account.asRobot().getConsumerSecret(), - oauthServiceProvider); - OAuthAccessor accessor = new OAuthAccessor(consumer); - - processOpsRequest(req, resp, message, accessor, participant); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java b/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java deleted file mode 100755 index 2e72c00..0000000 --- a/src/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java +++ /dev/null @@ -1,166 +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; - -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.wave.api.AbstractRobot; -import com.typesafe.config.Config; -import org.waveprotocol.box.server.persistence.AccountStore; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.register.RobotRegistrar; -import org.waveprotocol.box.server.robots.util.RobotsUtil.RobotRegistrationException; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * The base for robot agents that run on the WIAB server. - * - * @author [email protected] (Yuri Zelikov) - */ -@SuppressWarnings("serial") -public abstract class AbstractBaseRobotAgent extends AbstractRobot { - - public static class ServerFrontendAddressHolder { - - private final List<String> addresses; - - @Inject - ServerFrontendAddressHolder(Config config) { - this.addresses = config.getStringList("core.http_frontend_addresses"); - } - - public List<String> getAddresses() { - return addresses; - } - } - - public static final String AGENT_PREFIX_URI = "/agent"; - private static final Logger LOG = Logger.getLogger(AbstractBaseRobotAgent.class.getName()); - - /** The wave server domain. */ - private final String waveDomain; - - /** Account store with user and robot accounts. */ - private final AccountStore accountStore; - - /** SSL enabled flag? */ - private final Boolean isSSLEnabled; - - /** The robot registrar. */ - private final RobotRegistrar robotRegistrar; - - private final ServerFrontendAddressHolder frontendAddressHolder; - - /** - * Constructor. Initializes the agent to serve on the URI provided by - * {@link #getRobotUri()} and ensures that the agent is registered in the - * Account store. - * - * @param injector the injector instance. - */ - public AbstractBaseRobotAgent(Injector injector) { - Config config = injector.getInstance(Config.class); - this.waveDomain = config.getString("core.wave_server_domain"); - this.frontendAddressHolder = injector.getInstance(ServerFrontendAddressHolder.class); - this.robotRegistrar = injector.getInstance(RobotRegistrar.class); - this.accountStore = injector.getInstance(AccountStore.class); - this.isSSLEnabled = config.getBoolean("security.enable_ssl"); - ensureRegistered(getFrontEndAddress()); - } - - /** - * Constructor. Initializes the agent to serve on the URI provided by - * {@link #getRobotUri()} and ensures that the agent is registered in the - * Account store. - */ - AbstractBaseRobotAgent(String waveDomain, - ServerFrontendAddressHolder frontendAddressHolder, AccountStore accountStore, - RobotRegistrar robotRegistator, Boolean sslEnabled) { - this.waveDomain = waveDomain; - this.frontendAddressHolder = frontendAddressHolder; - this.robotRegistrar = robotRegistator; - this.accountStore = accountStore; - this.isSSLEnabled = sslEnabled; - ensureRegistered(getFrontEndAddress()); - } - - /** - * Ensures that the robot agent is registered in the {@link AccountStore}. - */ - private void ensureRegistered(String serverFrontendAddress) { - ParticipantId robotId; - try { - robotId = ParticipantId.of(getRobotId() + "@" + waveDomain); - } catch (InvalidParticipantAddress e) { - LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e); - return; - } - try { - String location = serverFrontendAddress + getRobotUri(); - // In order to re-register the agents if the server frontend address has changed. - robotRegistrar.registerOrUpdate(robotId, location); - - } catch (RobotRegistrationException | PersistenceException e) { - LOG.log(Level.SEVERE, "Failed to register the agent:" + getRobotId(), e); - } - } - - @Override - protected String getRobotProfilePageUrl() { - return null; - } - - /** - * Returns the wave domain. - */ - public String getWaveDomain() { - return waveDomain; - } - - /** - * Returns the front end address with correct prefix. - */ - public String getFrontEndAddress() { - //TODO(alown): should this really only get the first one? - return (this.isSSLEnabled ? "https://" : "http://") + frontendAddressHolder.getAddresses().get(0); - } - - /** - * Returns the account store. - */ - protected AccountStore getAccountStore() { - return accountStore; - } - - /** - * Returns the robot URI. - */ - public abstract String getRobotUri(); - - /** - * Returns the robot participant id. - */ - public abstract String getRobotId(); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java b/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java deleted file mode 100755 index f784595..0000000 --- a/src/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java +++ /dev/null @@ -1,272 +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; - -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine; -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.lastEnteredLineOf; - -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.name.Names; -import com.google.wave.api.Blip; -import com.google.wave.api.event.DocumentChangedEvent; -import com.google.wave.api.event.WaveletSelfAddedEvent; - -import com.typesafe.config.Config; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.OptionBuilder; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.cli.PosixParser; -import org.waveprotocol.box.server.CoreSettingsNames; -import org.waveprotocol.box.server.persistence.AccountStore; -import org.waveprotocol.box.server.robots.register.RobotRegistrar; -import org.waveprotocol.box.server.robots.register.RobotRegistrarImpl; - -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * The base for robot agents that run on the WIAB server and interact with users - * by entering commands as text in the blips. - * - * @author [email protected] (Yuri Zelikov) - */ -@SuppressWarnings("serial") -public abstract class AbstractCliRobotAgent extends AbstractBaseRobotAgent { - - /** The options for the command. */ - private final Options options; - private final CommandLineParser parser; - private final HelpFormatter helpFormatter; - - /** - * Constructor. Initializes the agent to serve on the URI provided by - * {@link #getRobotUri()} and ensures that the agent is registered in the - * Account store. - * - * @param injector the injector instance. - */ - public AbstractCliRobotAgent(Injector injector) { - this(injector.getInstance(Key.get(String.class, Names.named(CoreSettingsNames.WAVE_SERVER_DOMAIN))), - - injector - .getInstance(ServerFrontendAddressHolder.class), injector - .getInstance(AccountStore.class), injector.getInstance(RobotRegistrarImpl.class), - injector.getInstance(Config.class).getBoolean("security.enable_ssl")); - } - - /** - * Constructor. Initializes the agent to serve on the URI provided by - * {@link #getRobotUri()} and ensures that the agent is registered in the - * Account store. - */ - AbstractCliRobotAgent(String waveDomain, - ServerFrontendAddressHolder frontendAddressHolder, AccountStore accountStore, - RobotRegistrar robotRegistrar, Boolean sslEnabled) { - super(waveDomain, frontendAddressHolder, accountStore, robotRegistrar, sslEnabled); - parser = new PosixParser(); - helpFormatter = new HelpFormatter(); - options = initOptions(); - } - - /** - * Displays a short description when the robot is added to a wave. - */ - @Override - public void onWaveletSelfAdded(WaveletSelfAddedEvent event) { - String robotAddress = event.getWavelet().getRobotAddress(); - // Display a short description. - appendLine(event.getBlip(), "\n" + robotAddress + ": I am listening.\n" + getShortDescription() - + "\nFor help type " + "\"" + getCommandName() - + " -help\" on a new line and hit \"Enter\"."); - } - - @Override - public void onDocumentChanged(DocumentChangedEvent event) { - Blip blip = event.getBlip(); - String modifiedBy = event.getModifiedBy(); - CommandLine commandLine = null; - try { - commandLine = preprocessCommand(blip.getContent()); - } catch (IllegalArgumentException e) { - appendLine(blip, e.getMessage()); - } - if (commandLine != null) { - if (commandLine.hasOption("help") - // Or if only options. - || (commandLine.getArgs().length - commandLine.getOptions().length <= 1)) { - appendLine(blip, getFullDescription()); - } else { - String robotMessage = maybeExecuteCommand(commandLine, modifiedBy); - appendLine(blip, robotMessage); - } - } - } - - /** - * Validates and parses the input for the command. - * - * @param blipContent the blip contents. - * @return the command line {@link CommandLine} object with parsed data from - * the blip contents or null in case the content doesn't contain a - * command. - * @throws IllegalArgumentException if illegal arguments passed to the - * command. - */ - protected CommandLine preprocessCommand(String blipContent) throws IllegalArgumentException { - CommandLine commandLine = null; - String lastLine = lastEnteredLineOf(blipContent); - if (lastLine != null) { - try { - commandLine = parse(lastLine.split(" ")); - } catch (ParseException e) { - throw new IllegalArgumentException(e); - } - String[] args = commandLine.getArgs(); - if (!args[0].equals(getCommandName())) { - return null; - } - int argsNum = args.length - commandLine.getOptions().length - 1; - // If there are only options in the command - then it is also invalid and - // have to display usage anyway. - if ((argsNum > 0) - && (argsNum < getMinNumOfArguments() || argsNum > getMaxNumOfArguments())) { - String message; - if (getMinNumOfArguments() == getMaxNumOfArguments()) { - message = - String.format("Invalid number of arguments. Expected: %d , actual: %d %s", - getMinNumOfArguments(), argsNum, getUsage()); - } else { - message = - String.format( - "Invalid number of arguments. Expected between %d and %d, actual: %d. %s", - getMinNumOfArguments(), getMaxNumOfArguments(), argsNum, getUsage()); - } - throw new IllegalArgumentException(message); - } - } - return commandLine; - } - - @Override - protected String getRobotProfilePageUrl() { - return null; - } - - /** - * Returns the command options usage. - */ - public String getUsage() { - StringWriter stringWriter = new StringWriter(); - PrintWriter pw = new PrintWriter(stringWriter); - // HelpFormatter doesn't provide other ways to access defaultWidth, so we - // forced to access it in a deprecated way. - // TODO (user) Update this code to remove access of deprecated fields when - // it will be possible. - helpFormatter.printHelp(pw, helpFormatter.defaultWidth, getCommandName() + " " - + getCmdLineSyntax() + " \n", null, options, helpFormatter.defaultLeftPad, - helpFormatter.defaultDescPad, "", false); - pw.flush(); - return stringWriter.toString(); - } - - /** - * Initializes basic options. Override if more options needed. - * - * @return the command options. - */ - protected Options initOptions() { - // Create Options. - Options options = new Options(); - // The robot has only "help" option. - @SuppressWarnings({"static-access", "static"}) - Option help = OptionBuilder.withDescription("Displays help for the command.").create("help"); - options.addOption(help); - return options; - } - - protected CommandLine parse(String... args) throws ParseException { - return getParser().parse(getOptions(), args); - } - - /** - * Returns the command line parser. - */ - protected CommandLineParser getParser() { - return parser; - } - - /** - * Returns the command options. - */ - protected Options getOptions() { - return options; - } - - /** - * Attempts to execute the command. - * - * @param commandLine the commandLine with arguments and/or options entered by - * the user. - * @param modifiedBy the user that entered the content. - * @return the result message: success or failure. - */ - protected abstract String maybeExecuteCommand(CommandLine commandLine, String modifiedBy); - - /** - * Returns the short description of the robot. - */ - public abstract String getShortDescription(); - - /** - * Returns the full robot description. - */ - public abstract String getFullDescription(); - - /** - * Returns the command name for the robot. - */ - public abstract String getCommandName(); - - /** - * Returns the command line syntax. - */ - public abstract String getCmdLineSyntax(); - - /** - * Returns the command use example. - */ - public abstract String getExample(); - - /** - * Returns the minimum number of arguments this command accepts. Should be - * greater than zero and less or equal to {@link #getMaxNumOfArguments()}. - */ - public abstract int getMinNumOfArguments(); - - /** - * Returns the maximum number of arguments this command accepts. - */ - public abstract int getMaxNumOfArguments(); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java b/src/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java deleted file mode 100644 index 9fc0db2..0000000 --- a/src/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java +++ /dev/null @@ -1,109 +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; - -import com.google.wave.api.Blip; - -import org.waveprotocol.box.server.account.HumanAccountDataImpl; -import org.waveprotocol.box.server.authentication.PasswordDigest; -import org.waveprotocol.box.server.persistence.AccountStore; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import javax.annotation.Nullable; - -/** - * Util methods for the robot agents. - * - * @author [email protected] (Yuri Zelikov) - */ -public class RobotAgentUtil { - - public static final String CANNOT_CHANGE_PASSWORD_FOR_USER = "Cannot change password for user: "; - public static final String CANNOT_CREATE_USER = "Cannot create user: "; - - private RobotAgentUtil() { - - } - - /** - * Appends a message followed by a new line to the end of the blip. - * - * @param blip the blip. - * @param msg the message. - */ - public static void appendLine(Blip blip, String msg) { - blip.at(blip.getContent().length()).insert(msg + "\n"); - } - - /** - * Returns the last line of the content if it ends with "\n" or null - * otherwise. - */ - public static String lastEnteredLineOf(@Nullable String blipContent) { - if (blipContent == null || blipContent.isEmpty() || !blipContent.endsWith("\n")) { - return null; - } - blipContent = blipContent.trim(); - String[] split = blipContent.split("\n"); - return split[split.length - 1]; - } - - /** - * Changes the user password. - * - * @param newPassword the new password of the user. - * @param participantId the user wave address. - * @param accountStore the account store with user accounts. - * @throws PersistenceException if the persistence layer fails. - * @throws IllegalArgumentException if the user doesn't exist. - */ - public static void changeUserPassword(String newPassword, ParticipantId participantId, - AccountStore accountStore) throws PersistenceException, IllegalArgumentException { - PasswordDigest newPasswordDigest = new PasswordDigest(newPassword.toCharArray()); - HumanAccountDataImpl account = new HumanAccountDataImpl(participantId, newPasswordDigest); - if (accountStore.getAccount(participantId) != null) { - accountStore.removeAccount(participantId); - accountStore.putAccount(account); - } else { - throw new IllegalArgumentException(String.format("User %s does not exist on this domain.", - participantId.getAddress())); - } - } - - /** - * Creates a new user. - * - * @param accountStore the account store with user accounts. - * @param participantId requested user wave address. - * @param password requested user password - * @throws PersistenceException if the persistence layer fails. - * @throws IllegalArgumentException if the userId is already in use. - */ - public static void createUser(AccountStore accountStore, ParticipantId participantId, String password) - throws PersistenceException, IllegalArgumentException { - if (accountStore.getAccount(participantId) != null) { - throw new IllegalArgumentException(String.format("User %s already exists on this domain.", participantId.getAddress())); - } - - HumanAccountDataImpl account = new HumanAccountDataImpl(participantId, new PasswordDigest(password.toCharArray())); - accountStore.putAccount(account); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/7d8609e7/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java b/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java deleted file mode 100644 index 9dc0720..0000000 --- a/src/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java +++ /dev/null @@ -1,150 +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 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_CHANGE_PASSWORD_FOR_USER; -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.changeUserPassword; - -/** - * Robot agent that handles the password reset for users by admin. - * - * @author [email protected] (Yuri Zelikov) - */ -@SuppressWarnings("serial") -@Singleton -public final class PasswordAdminRobot extends AbstractCliRobotAgent { - - private static final Logger LOG = Logger.getLogger(PasswordAdminRobot.class.getName()); - public static final String ROBOT_URI = AGENT_PREFIX_URI + "/passwd/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 PasswordAdminRobot(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 change the password 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 newPassword = args[2]; - // Add domain to the user id if needed. - userId = userId + (userId.contains("@") ? "" : "@" + getWaveDomain()); - ParticipantId participantId = ParticipantId.of(userId); - changeUserPassword(newPassword, participantId, accountStore); - robotMessage = - String.format("Changed password for user %s, the new password is: %s\n", userId, - newPassword); - LOG.log(Level.INFO, "Password changed for user " + userId + " by " + modifiedBy); - } catch (IllegalArgumentException e) { - LOG.log(Level.SEVERE, userId, e); - robotMessage = e.getMessage(); - } catch (PersistenceException | InvalidParticipantAddress e) { - robotMessage = CANNOT_CHANGE_PASSWORD_FOR_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 "passwdadmin"; - } - - @Override - public String getFullDescription() { - return getShortDescription() + "\n" + getUsage() + "\nExample: " + getCommandName() + " " - + getExample(); - } - - @Override - public String getCmdLineSyntax() { - return "[OPTIONS] [USERNAME] [NEW_PASSWORD]"; - } - - @Override - public String getExample() { - return "user_id new_password"; - } - - @Override - public String getShortDescription() { - return "The command allows the admin to change the password of other user. " - + "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 getRobotName() { - return "PasswdAdmin-Bot"; - } - - @Override - public String getRobotUri() { - return ROBOT_URI; - } - - @Override - public String getRobotId() { - return "passwdadmin-bot"; - } -}
