http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/RobotApiModule.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/RobotApiModule.java b/wave/src/main/java/org/waveprotocol/box/server/robots/RobotApiModule.java deleted file mode 100644 index e757080..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/RobotCapabilities.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/RobotCapabilities.java b/wave/src/main/java/org/waveprotocol/box/server/robots/RobotCapabilities.java deleted file mode 100644 index c7c7e04..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java b/wave/src/main/java/org/waveprotocol/box/server/robots/RobotRegistrationServlet.java deleted file mode 100644 index 32f7bc9..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/RobotSerializerModule.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/RobotSerializerModule.java b/wave/src/main/java/org/waveprotocol/box/server/robots/RobotSerializerModule.java deleted file mode 100644 index 26670ac..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/RobotWaveletData.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/RobotWaveletData.java b/wave/src/main/java/org/waveprotocol/box/server/robots/RobotWaveletData.java deleted file mode 100644 index 6d80fba..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java b/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiOperationServiceRegistry.java deleted file mode 100644 index fc3f56e..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java b/wave/src/main/java/org/waveprotocol/box/server/robots/active/ActiveApiServlet.java deleted file mode 100644 index a2b46d3..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractBaseRobotAgent.java deleted file mode 100755 index 2e72c00..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/AbstractCliRobotAgent.java deleted file mode 100755 index f784595..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/RobotAgentUtil.java deleted file mode 100644 index 9fc0db2..0000000 --- a/wave/src/main/java/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/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordAdminRobot.java deleted file mode 100644 index 7285685..0000000 --- a/wave/src/main/java/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"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java deleted file mode 100644 index a2a0daf..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/passwd/PasswordRobot.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.box.server.robots.agent.passwd; - -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.CANNOT_CHANGE_PASSWORD_FOR_USER; -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.changeUserPassword; - -import com.google.common.collect.ImmutableMap; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Singleton; - -import org.apache.commons.cli.CommandLine; -import org.eclipse.jetty.util.MultiMap; -import org.waveprotocol.box.server.authentication.HttpRequestBasedCallbackHandler; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.agent.AbstractCliRobotAgent; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.Configuration; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - -/** - * Robot agent that allows a user to change her own password. The userId should - * be from this wave domain. - * - * When the robot is added to a wave, it prints basic description and then - * inspects text entered by the user. When a new line char is entered it scans - * the last line of the text in the blip and parses it using Apache CLI command - * line interpreter. If the command found to be valid, the robot validates user - * credentials and then changes the password of the user to a new one. - * - * @author [email protected] (Yuri Zelikov) - */ -@SuppressWarnings("serial") -@Singleton -public final class PasswordRobot extends AbstractCliRobotAgent { - - private static final Logger LOG = Logger.getLogger(PasswordRobot.class.getName()); - public static final String ROBOT_URI = AGENT_PREFIX_URI + "/passwd/user"; - - /** Configuration for the LoginContext. */ - private final Configuration configuration; - - @Inject - public PasswordRobot(Injector injector) { - super(injector); - configuration = injector.getInstance(Configuration.class); - } - - @Override - protected String maybeExecuteCommand(CommandLine commandLine, String modifiedBy) { - String robotMessage = null; - // Get the user that wants to change her own password. - if (!modifiedBy.endsWith("@" + getWaveDomain())) { - // Can change passwords only for users on this wave domain. - robotMessage = - String.format("User %s does not belong to the @%s domain\n", modifiedBy, - getWaveDomain()); - } else { - String[] args = commandLine.getArgs(); - try { - ParticipantId participantId = ParticipantId.of(modifiedBy); - if (args.length == 2) { - // If current password is empty, i.e. "", then user should pass - // only the new password. - args = Arrays.copyOf(args, 3); - args[2] = args[1]; - args[1] = ""; - } - String oldPassword = args[1]; - String newPassword = args[2]; - verifyCredentials(oldPassword, participantId); - changeUserPassword(newPassword, participantId, getAccountStore()); - robotMessage = - String.format("Changed password for user %s, the new password is: %s", modifiedBy, - newPassword); - LOG.info(modifiedBy + " changed password for user: " + modifiedBy); - } catch (IllegalArgumentException e) { - robotMessage = e.getMessage(); - LOG.log(Level.SEVERE, "userId: " + modifiedBy, e); - } catch (PersistenceException e) { - robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy; - LOG.log(Level.SEVERE, "userId: " + modifiedBy, e); - } catch (InvalidParticipantAddress e) { - robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy; - LOG.log(Level.SEVERE, "userId: " + modifiedBy, e); - } catch (LoginException e) { - robotMessage = - CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy - + ". Please verify your old password"; - LOG.log(Level.SEVERE, "userId: " + modifiedBy, e); - } - } - return robotMessage; - } - - /** - * Verifies user credentials. - * - * @param oldPassword the password to verify. - * @param participantId the participantId of the user. - * @throws LoginException if the user provided incorrect password. - */ - private void verifyCredentials(String password, ParticipantId participantId) - throws LoginException { - MultiMap<String> parameters = new MultiMap<String>(); - parameters.putAllValues(ImmutableMap.of("password", password, "address", participantId.getAddress())); - CallbackHandler callbackHandler = new HttpRequestBasedCallbackHandler(parameters); - LoginContext context = new LoginContext("Wave", new Subject(), callbackHandler, configuration); - // If authentication fails, login() will throw a LoginException. - context.login(); - } - - @Override - public String getFullDescription() { - return getShortDescription() + " If your password is empty - enter only the new password.\n" - + getUsage() + "\nExample: " + getCommandName() + " " + getExample(); - } - - @Override - public String getCmdLineSyntax() { - return "[OPTIONS] [OLD_PASSWORD] [NEW_PASSWORD]"; - } - - @Override - public String getExample() { - return "old_password new_password"; - } - - @Override - public String getShortDescription() { - return "The command allows users to change their own password. " - + "Please make sure to use it in a wave without other participants. " - + "It is also advised to remove yourself from the wave " - + "when you finished changing the password."; - } - - @Override - public String getCommandName() { - return "passwd"; - } - - @Override - public String getRobotName() { - return "Passwd-Bot"; - } - - @Override - public int getMinNumOfArguments() { - return 1; - } - - @Override - public int getMaxNumOfArguments() { - return 2; - } - - @Override - public String getRobotUri() { - return ROBOT_URI; - } - - @Override - public String getRobotId() { - return "passwd-bot"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java deleted file mode 100644 index cbf3332..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/registration/RegistrationRobot.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.box.server.robots.agent.registration; - -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Singleton; -import com.typesafe.config.Config; -import org.apache.commons.cli.CommandLine; -import org.waveprotocol.box.server.persistence.AccountStore; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.agent.AbstractCliRobotAgent; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.CANNOT_CREATE_USER; -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.createUser; - -/** - * Robot agent that handles the user registration by an admin - * - * @author [email protected] (Ali Lown) - */ -@SuppressWarnings("serial") -@Singleton -public final class RegistrationRobot extends AbstractCliRobotAgent { - - private static final Logger LOG = Logger.getLogger(RegistrationRobot.class.getName()); - public static final String ROBOT_URI = AGENT_PREFIX_URI + "/registration/admin"; - - /** The address of the admin user as defined in the server configuration. */ - private final String serverAdminId; - - /** Account store with user and robot accounts. */ - private final AccountStore accountStore; - - @Inject - public RegistrationRobot(Injector injector) { - super(injector); - serverAdminId = - injector.getInstance(Config.class).getString("administration.admin_user"); - accountStore = injector.getInstance(AccountStore.class); - } - - @Override - protected String maybeExecuteCommand(CommandLine commandLine, String modifiedBy) { - String robotMessage; - // Verify that the user that attempts to create a user has admin privileges. - if (!modifiedBy.equals(serverAdminId)) { - robotMessage = - "User " + modifiedBy + " is not authorized to use " + getCommandName() + " command."; - } else { - String userId = null; - try { - String[] args = commandLine.getArgs(); - userId = args[1]; - String password = args[2]; - // Add domain to the user id if needed. - userId = userId + (userId.contains("@") ? "" : "@" + getWaveDomain()); - ParticipantId participantId = ParticipantId.of(userId); - createUser(accountStore, participantId, password); - robotMessage = String.format("Created user %s, the password is: %s\n", userId, password); - LOG.log(Level.INFO, "Created user " + userId + " by " + modifiedBy); - } catch (IllegalArgumentException e) { - LOG.log(Level.SEVERE, userId, e); - robotMessage = e.getMessage(); - } catch (PersistenceException | InvalidParticipantAddress e) { - robotMessage = CANNOT_CREATE_USER + userId; - LOG.log(Level.SEVERE, "userId: " + userId, e); - } - } - - return robotMessage; - } - - @Override - public int getMinNumOfArguments() { - return 2; - } - - @Override - public int getMaxNumOfArguments() { - return 2; - } - - @Override - public String getCommandName() { - return "register"; - } - - @Override - public String getFullDescription() { - return getShortDescription() + "\n" + getUsage() + "\nExample: " + getCommandName() + " " - + getExample(); - } - - @Override - public String getCmdLineSyntax() { - return "[OPTIONS] [USERNAME] [PASSWORD]"; - } - - @Override - public String getExample() { - return "user_id password"; - } - - @Override - public String getShortDescription() { - return "The command allows the admin to register other users. " - + "Please make sure to use it in a wave without other participants. " - + "It is also advised to remove yourself from the wave " - + "when you finished creating users."; - } - - @Override - public String getRobotName() { - return "Registration-Bot"; - } - - @Override - public String getRobotUri() { - return ROBOT_URI; - } - - @Override - public String getRobotId() { - return "registration-bot"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java b/wave/src/main/java/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java deleted file mode 100755 index fddab5a..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/robots/agent/welcome/WelcomeRobot.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.waveprotocol.box.server.robots.agent.welcome; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Singleton; -import com.google.wave.api.Wavelet; -import com.typesafe.config.Config; -import org.waveprotocol.box.server.account.RobotAccountData; -import org.waveprotocol.box.server.persistence.PersistenceException; -import org.waveprotocol.box.server.robots.agent.AbstractBaseRobotAgent; -import org.waveprotocol.box.server.robots.util.RobotsUtil; -import org.waveprotocol.wave.model.id.InvalidIdException; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.appendLine; - - -/** - * The robot that adds a "Welcome" wave to the inbox of new users. - * - * @author [email protected] (Yuri Zelikov) - */ -@SuppressWarnings("serial") -@Singleton -public class WelcomeRobot extends AbstractBaseRobotAgent { - - - private static final Logger LOG = Logger.getLogger(WelcomeRobot.class.getName()); - public static final String ROBOT_URI = AGENT_PREFIX_URI + "/welcome"; - - /** The id of the wave that serves as a template for the welcome wave. */ - private WaveId welcomeWaveId = null; - - @Inject - public WelcomeRobot(Injector injector) { - super(injector); - String welcomeWaveIdStr = - injector.getInstance(Config.class).getString("administration.welcome_wave_id"); - if (!"".equals(welcomeWaveIdStr)) { - try { - welcomeWaveId = WaveId.ofChecked(getWaveDomain(), welcomeWaveIdStr); - } catch (InvalidIdException e) { - LOG.log(Level.WARNING, "Problem parsing welcome wave id: " + welcomeWaveIdStr); - } - } - } - - /** - * Greets new users by creating a new wave with welcome message and - * adding it to the inbox of the new user. - * - * @param id the participant id of the new user. - * @throws IOException if there is a problem submitting the new wave. - */ - public void greet(ParticipantId id) throws IOException { - Preconditions.checkNotNull(id); - RobotAccountData account = null; - String rpcUrl = getFrontEndAddress() + "/robot/rpc"; - try { - account = - getAccountStore() - .getAccount(ParticipantId.ofUnsafe(getRobotId() + "@" + getWaveDomain())).asRobot(); - } catch (PersistenceException e) { - LOG.log(Level.WARNING, "Cannot fetch account data for robot id: " + getRobotId(), e); - } - if (account != null) { - setupOAuth(account.getId().getAddress(), account.getConsumerSecret(), rpcUrl); - Wavelet newWelcomeWavelet = newWave(getWaveDomain(), Sets.newHashSet(id.getAddress())); - if (welcomeWaveId != null) { - Wavelet templateWelcomeWavelet = - fetchWavelet(welcomeWaveId, WaveletId.of(getWaveDomain(), "conv+root"), rpcUrl); - RobotsUtil.copyBlipContents(templateWelcomeWavelet.getRootBlip(), - newWelcomeWavelet.getRootBlip()); - } else { - appendLine(newWelcomeWavelet.getRootBlip(), "Welcome to " + getWaveDomain() + "!"); - } - submit(newWelcomeWavelet, rpcUrl); - } - } - - @Override - public String getRobotUri() { - return ROBOT_URI; - } - - @Override - public String getRobotId() { - return "welcome-bot"; - } - - @Override - protected String getRobotName() { - return "Welcome-Bot"; - } -}
