http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveViewSubscription.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveViewSubscription.java b/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveViewSubscription.java deleted file mode 100644 index 6281edd..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveViewSubscription.java +++ /dev/null @@ -1,247 +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.frontend; - -import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import org.waveprotocol.box.common.DeltaSequence; -import org.waveprotocol.wave.model.id.IdFilter; -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.version.HashedVersion; -import org.waveprotocol.wave.util.logging.Log; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * A client's subscription to a wave view. - * - * @author [email protected] (Alex North) - */ -final class WaveViewSubscription { - - /** - * State of a wavelet endpoint. - */ - private static final class WaveletChannelState { - /** - * Resulting versions of deltas submitted on this wavelet for which - * the outbound delta has not yet been seen. - */ - public final Collection<Long> submittedEndVersions = Sets.newHashSet(); - /** - * Resulting version of the most recent outbound delta. - */ - public HashedVersion lastVersion = null; - /** - * Whether a submit request is awaiting a response. - */ - public boolean hasOutstandingSubmit = false; - /** - * Outbound deltas held back while a submit is in-flight. - */ - public List<TransformedWaveletDelta> heldBackDeltas = Lists.newLinkedList(); - } - - private static final Log LOG = Log.get(WaveViewSubscription.class); - - private final WaveId waveId; - private final IdFilter waveletIdFilter; - private final ClientFrontend.OpenListener openListener; - private final String channelId; - private final LoadingCache<WaveletId, WaveletChannelState> channels = - CacheBuilder.newBuilder().build(new CacheLoader<WaveletId, WaveletChannelState>() { - @Override - public WaveletChannelState load(WaveletId id) { - return new WaveletChannelState(); - } - }); - - public WaveViewSubscription(WaveId waveId, IdFilter waveletIdFilter, String channelId, - ClientFrontend.OpenListener openListener) { - Preconditions.checkNotNull(waveId, "null wave id"); - Preconditions.checkNotNull(waveletIdFilter, "null filter"); - Preconditions.checkNotNull(openListener, "null listener"); - Preconditions.checkNotNull(channelId, "null channel id"); - - this.waveId = waveId; - this.waveletIdFilter = waveletIdFilter; - this.channelId = channelId; - this.openListener = openListener; - } - - public WaveId getWaveId() { - return waveId; - } - - public ClientFrontend.OpenListener getOpenListener() { - return openListener; - } - - public String getChannelId() { - return channelId; - } - - /** - * Checks whether the subscription includes a wavelet. - */ - public boolean includes(WaveletId waveletId) { - return IdFilter.accepts(waveletIdFilter, waveletId); - } - - /** This client sent a submit request */ - public synchronized void submitRequest(WaveletName waveletName) { - // A given client can only have one outstanding submit per wavelet. - WaveletChannelState state; - try { - state = channels.get(waveletName.waveletId); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - Preconditions.checkState(!state.hasOutstandingSubmit, - "Received overlapping submit requests to subscription %s", this); - LOG.info("Submit oustandinding on channel " + channelId); - state.hasOutstandingSubmit = true; - } - - /** - * A submit response for the given wavelet and version has been sent to this - * client. - */ - public synchronized void submitResponse(WaveletName waveletName, HashedVersion version) { - Preconditions.checkNotNull(version, "Null delta application version"); - WaveletId waveletId = waveletName.waveletId; - WaveletChannelState state; - try { - state = channels.get(waveletId); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - Preconditions.checkState(state.hasOutstandingSubmit); - state.submittedEndVersions.add(version.getVersion()); - state.hasOutstandingSubmit = false; - LOG.info("Submit resolved on channel " + channelId); - - // Forward any queued deltas. - List<TransformedWaveletDelta> filteredDeltas = filterOwnDeltas(state.heldBackDeltas, state); - if (!filteredDeltas.isEmpty()) { - sendUpdate(waveletName, filteredDeltas, null); - } - state.heldBackDeltas.clear(); - } - - /** - * Sends deltas for this subscription (if appropriate). - * - * If the update contains a delta for a wavelet where the delta is actually - * from this client, the delta is dropped. If there's an outstanding submit - * request the delta is queued until the submit finishes. - */ - public synchronized void onUpdate(WaveletName waveletName, DeltaSequence deltas) { - Preconditions.checkArgument(!deltas.isEmpty()); - WaveletChannelState state; - try { - state = channels.get(waveletName.waveletId); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - checkUpdateVersion(waveletName, deltas, state); - state.lastVersion = deltas.getEndVersion(); - if (state.hasOutstandingSubmit) { - state.heldBackDeltas.addAll(deltas); - } else { - List<TransformedWaveletDelta> filteredDeltas = filterOwnDeltas(deltas, state); - if (!filteredDeltas.isEmpty()) { - sendUpdate(waveletName, filteredDeltas, null); - } - } - } - - /** - * Filters any deltas sent by this client from a list of received deltas. - * - * @param deltas received deltas - * @param state channel state - * @return deltas, if none are from this client, or a copy with own client's - * deltas removed - */ - private List<TransformedWaveletDelta> filterOwnDeltas(List<TransformedWaveletDelta> deltas, - WaveletChannelState state) { - List<TransformedWaveletDelta> filteredDeltas = deltas; - if (!state.submittedEndVersions.isEmpty()) { - filteredDeltas = Lists.newArrayList(); - for (TransformedWaveletDelta delta : deltas) { - long deltaEndVersion = delta.getResultingVersion().getVersion(); - if (!state.submittedEndVersions.remove(deltaEndVersion)) { - filteredDeltas.add(delta); - } - } - } - return filteredDeltas; - } - - /** - * Sends a commit notice for this subscription. - */ - public synchronized void onCommit(WaveletName waveletName, HashedVersion committedVersion) { - sendUpdate(waveletName, ImmutableList.<TransformedWaveletDelta>of(), committedVersion); - } - - /** - * Sends an update to the client. - */ - private void sendUpdate(WaveletName waveletName, List<TransformedWaveletDelta> deltas, - HashedVersion committedVersion) { - // Channel id needs to be sent with every message until views can be - // closed, see bug 128. - openListener.onUpdate(waveletName, null, deltas, committedVersion, null, channelId); - } - - /** - * Checks the update targets the next expected version. - */ - private void checkUpdateVersion(WaveletName waveletName, DeltaSequence deltas, - WaveletChannelState state) { - if (state.lastVersion != null) { - long expectedVersion = state.lastVersion.getVersion(); - long targetVersion = deltas.getStartVersion(); - Preconditions.checkState(targetVersion == expectedVersion, - "Subscription expected delta for %s targeting %s, was %s", waveletName, expectedVersion, - targetVersion); - } - } - - @Override - public String toString() { - return "[WaveViewSubscription wave: " + waveId + ", channel: " + channelId + "]"; - } -}
http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveletInfo.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveletInfo.java b/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveletInfo.java deleted file mode 100644 index 79950db..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/frontend/WaveletInfo.java +++ /dev/null @@ -1,286 +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.frontend; - -import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; - -import org.waveprotocol.box.common.DeltaSequence; -import org.waveprotocol.box.server.waveserver.WaveServerException; -import org.waveprotocol.box.server.waveserver.WaveletProvider; -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.version.HashedVersion; -import org.waveprotocol.wave.model.version.HashedVersionFactory; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.wave.data.ReadableWaveletData; -import org.waveprotocol.wave.util.logging.Log; - -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ExecutionException; - -/** - * Provides services to manage and track wavelet participants and wavelet - * subscriptions. - * - * @author [email protected] (Yuri Zelikov) - * @see ClientFrontendImpl - */ -public class WaveletInfo { - private static final Log LOG = Log.get(WaveletInfo.class); - - /** Information we hold in memory for each wavelet. */ - private static class PerWavelet { - private final HashedVersion version0; - private final Set<ParticipantId> explicitParticipants; - private final Set<ParticipantId> implicitParticipants; - private HashedVersion currentVersion; - - PerWavelet(WaveletName waveletName, HashedVersion hashedVersionZero) { - this.explicitParticipants = Sets.newHashSet(); - this.implicitParticipants = Sets.newHashSet(); - this.version0 = hashedVersionZero; - this.currentVersion = version0; - } - - synchronized HashedVersion getCurrentVersion() { - return currentVersion; - } - - synchronized void setCurrentVersion(HashedVersion version) { - this.currentVersion = version; - } - } - - private final LoadingCache<ParticipantId, UserManager> perUser; - private final LoadingCache<WaveId, LoadingCache<WaveletId, PerWavelet>> perWavelet; - private final WaveletProvider waveletProvider; - - /** - * Creates new instance of {@link WaveletInfo}. - * - * @param hashFactory the factory for hashed versions. - * @param provider the {@link WaveletProvider}. - * @return new {@link WaveletInfo} instance. - */ - public static WaveletInfo create(HashedVersionFactory hashFactory, WaveletProvider provider) { - return new WaveletInfo(hashFactory, provider); - } - - WaveletInfo(final HashedVersionFactory hashedVersionFactory, WaveletProvider waveletProvider) { - this.waveletProvider = waveletProvider; - perWavelet = - CacheBuilder.newBuilder().build(new CacheLoader<WaveId, LoadingCache<WaveletId, PerWavelet>>() { - @Override - public LoadingCache<WaveletId, PerWavelet> load(final WaveId waveId) { - return CacheBuilder.newBuilder().build(new CacheLoader<WaveletId, PerWavelet>() { - @Override - public PerWavelet load(WaveletId waveletId) { - WaveletName waveletName = WaveletName.of(waveId, waveletId); - return new PerWavelet(waveletName, hashedVersionFactory - .createVersionZero(waveletName)); - } - }); - } - }); - - perUser = CacheBuilder.newBuilder().build(new CacheLoader<ParticipantId, UserManager>() { - @Override - public UserManager load(ParticipantId from) { - return new UserManager(); - } - }); - } - - /** - * Returns all visible wavelets in the wave specified by subscription which - * are also comply with the subscription filter. - */ - public Set<WaveletId> visibleWaveletsFor(WaveViewSubscription subscription, - ParticipantId loggedInUser) throws WaveServerException { - Set<WaveletId> visible = Sets.newHashSet(); - Set<Entry<WaveletId, PerWavelet>> entrySet; - try { - entrySet = perWavelet.get(subscription.getWaveId()).asMap().entrySet(); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - for (Entry<WaveletId, PerWavelet> entry : entrySet) { - WaveletName waveletName = WaveletName.of(subscription.getWaveId(), entry.getKey()); - if (subscription.includes(entry.getKey()) - && waveletProvider.checkAccessPermission(waveletName, loggedInUser)) { - visible.add(entry.getKey()); - } - } - return visible; - } - - /** - * Initializes front-end information from the wave store, if necessary. - */ - public void initialiseWave(WaveId waveId) throws WaveServerException { - if(LOG.isFineLoggable()) { - LOG.fine("frontend initialiseWave(" + waveId +")"); - } - - try { - if (perWavelet.getIfPresent(waveId) == null) { - LoadingCache<WaveletId, PerWavelet> wavelets = perWavelet.get(waveId); - for (WaveletId waveletId : waveletProvider.getWaveletIds(waveId)) { - ReadableWaveletData wavelet = - waveletProvider.getSnapshot(WaveletName.of(waveId, waveletId)).snapshot; - // Wavelets is a computing map, so get() initializes the entry. - PerWavelet waveletInfo = wavelets.get(waveletId); - synchronized (waveletInfo) { - waveletInfo.currentVersion = wavelet.getHashedVersion(); - if(LOG.isFineLoggable()) { - LOG.fine("frontend wavelet " + waveletId + " @" + wavelet.getHashedVersion().getVersion()); - } - waveletInfo.explicitParticipants.addAll(wavelet.getParticipants()); - } - } - } - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - } - - /** - * Synchronizes the wavelet version and ensures that the deltas are - * contiguous. - * - * @param waveletName the wavelet name. - * @param newDeltas the new deltas. - */ - public void syncWaveletVersion(WaveletName waveletName, DeltaSequence newDeltas) { - HashedVersion expectedVersion; - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - expectedVersion = waveletInfo.getCurrentVersion(); - Preconditions.checkState(expectedVersion.getVersion() == newDeltas.getStartVersion(), - "Expected deltas starting at version %s, got %s", expectedVersion, - newDeltas.getStartVersion()); - waveletInfo.setCurrentVersion(newDeltas.getEndVersion()); - } - } - - /** - * Returns {@link UserManager} for the participant. - */ - public UserManager getUserManager(ParticipantId participantId) { - try { - return perUser.get(participantId); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - } - - /** - * Returns the current wavelet version. - */ - public HashedVersion getCurrentWaveletVersion(WaveletName waveletName) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - return waveletInfo.getCurrentVersion(); - } - } - - /** - * @param waveletName the waveletName. - * @return the wavelet participants. - */ - public Set<ParticipantId> getWaveletParticipants(WaveletName waveletName) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - return ImmutableSet.copyOf(waveletInfo.explicitParticipants); - } - } - - /** - * @param waveletName the waveletName. - * @return the implicit wavelet participants. An implicit participant is not a - * "strict" participant on the wavelet, but rather only opened the - * wave and listens on updates. For example, anyone can open a shared - * wave without becoming explicit participant. - */ - public Set<ParticipantId> getImplicitWaveletParticipants(WaveletName waveletName) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - return ImmutableSet.copyOf(waveletInfo.explicitParticipants); - } - } - - /** - * Notifies that the participant was added from the wavelet. - * - * @param waveletName the wavelet name. - * @param participant the participant. - */ - public void notifyAddedExplicitWaveletParticipant(WaveletName waveletName, - ParticipantId participant) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - waveletInfo.explicitParticipants.add(participant); - } - } - - /** - * Notifies that the participant was removed from the wavelet. - * - * @param waveletName the wavelet name. - * @param participant the participant. - */ - public void notifyRemovedExplicitWaveletParticipant(WaveletName waveletName, - ParticipantId participant) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - waveletInfo.explicitParticipants.remove(participant); - } - } - - /** - * Notifies that an implicit participant opened the wave. - * - * @param waveletName the wavelet name. - * @param participant the participant. - */ - public void notifyAddedImplcitParticipant(WaveletName waveletName, ParticipantId participant) { - PerWavelet waveletInfo = getWavelet(waveletName); - synchronized (waveletInfo) { - if (!waveletInfo.explicitParticipants.contains(participant)) { - waveletInfo.implicitParticipants.add(participant); - } - } - } - - private PerWavelet getWavelet(WaveletName name) { - try { - return perWavelet.get(name.waveId).get(name.waveletId); - } catch (ExecutionException ex) { - throw new RuntimeException(ex); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeClientFrontend.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeClientFrontend.java b/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeClientFrontend.java deleted file mode 100644 index d1ac76b..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeClientFrontend.java +++ /dev/null @@ -1,115 +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.frontend.testing; - -import org.waveprotocol.box.common.DeltaSequence; -import org.waveprotocol.box.common.comms.WaveClientRpc; -import org.waveprotocol.box.server.frontend.ClientFrontend; -import org.waveprotocol.box.server.waveserver.WaveBus; -import org.waveprotocol.box.server.waveserver.WaveletProvider.SubmitRequestListener; -import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta; -import org.waveprotocol.wave.model.id.IdFilter; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletName; -import org.waveprotocol.wave.model.version.HashedVersion; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.wave.data.ReadableWaveletData; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * Implementation of a ClientFrontend which only records requests and will make callbacks when it - * receives wavelet listener events. - */ -public class FakeClientFrontend implements ClientFrontend, WaveBus.Subscriber { - private static class SubmitRecord { - final SubmitRequestListener listener; - final int operations; - SubmitRecord(int operations, SubmitRequestListener listener) { - this.operations = operations; - this.listener = listener; - } - } - - private final Map<WaveId, OpenListener> openListeners = new HashMap<WaveId, OpenListener>(); - - private final Map<WaveletName, SubmitRecord> submitRecords = - new HashMap<WaveletName, SubmitRecord>(); - - public void doSubmitFailed(WaveletName waveletName, String errorMessage) { - SubmitRecord record = submitRecords.remove(waveletName); - if (record != null) { - record.listener.onFailure(errorMessage); - } - } - - /** Reports a submit success with resulting version 0 application timestamp 0 */ - public void doSubmitSuccess(WaveletName waveletName) { - HashedVersion fakeHashedVersion = HashedVersion.of(0, new byte[0]); - doSubmitSuccess(waveletName, fakeHashedVersion, 0); - } - - /** Reports a submit success with the specified resulting version and application timestamp */ - public void doSubmitSuccess(WaveletName waveletName, HashedVersion resultingVersion, - long applicationTimestamp) { - SubmitRecord record = submitRecords.remove(waveletName); - if (record != null) { - record.listener.onSuccess(record.operations, resultingVersion, applicationTimestamp); - } - } - - public void doUpdateFailure(WaveId waveId, String errorMessage) { - OpenListener listener = openListeners.get(waveId); - if (listener != null) { - listener.onFailure(errorMessage); - } - } - - @Override - public void openRequest(ParticipantId participant, WaveId waveId, IdFilter waveletIdFilter, - Collection<WaveClientRpc.WaveletVersion> knownWavelets, OpenListener openListener) { - openListeners.put(waveId, openListener); - } - - @Override - public void submitRequest(ParticipantId loggedInUser, WaveletName waveletName, - ProtocolWaveletDelta delta, String channelId, SubmitRequestListener listener) { - submitRecords.put(waveletName, new SubmitRecord(delta.getOperationCount(), listener)); - } - - @Override - public void waveletCommitted(WaveletName waveletName, HashedVersion version) { - OpenListener listener = openListeners.get(waveletName.waveId); - if (listener != null) { - listener.onUpdate(waveletName, null, DeltaSequence.empty(), version, null, null); - } - } - - @Override - public void waveletUpdate(ReadableWaveletData wavelet, DeltaSequence newDeltas) { - OpenListener listener = openListeners.get(wavelet.getWaveId()); - if (listener != null) { - WaveletName waveletName = WaveletName.of(wavelet.getWaveId(), wavelet.getWaveletId()); - listener.onUpdate(waveletName, null, newDeltas, null, null, null); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeWaveServer.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeWaveServer.java b/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeWaveServer.java deleted file mode 100644 index 712306d..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/frontend/testing/FakeWaveServer.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.frontend.testing; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Maps; - -import org.waveprotocol.box.common.DeltaSequence; -import org.waveprotocol.box.common.comms.WaveClientRpc; -import org.waveprotocol.box.server.common.CoreWaveletOperationSerializer; -import org.waveprotocol.box.server.util.WaveletDataUtil; -import org.waveprotocol.box.server.waveserver.WaveletProvider.SubmitRequestListener; -import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta; -import org.waveprotocol.wave.model.id.IdFilter; -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.version.HashedVersion; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.wave.data.WaveletData; - -import java.util.Collection; -import java.util.Map; - -import javax.annotation.Nullable; - -/** - * A fake single-user wave server which only echoes back submitted deltas and - * corresponding index wave deltas. - * - * @author [email protected] (Michael Kuntzman) - */ -public class FakeWaveServer extends FakeClientFrontend { - /** Fake application timestamp for confirming a successful submit. */ - private static final long APP_TIMESTAMP = 0; - - /** Known wavelet states, excluding index wavelets. */ - private final Map<WaveId, Map<WaveletId, WaveletData>> waves = Maps.newHashMap(); - - /** A history of submitted deltas, per wavelet. Does not store generated index deltas. */ - private final ListMultimap<WaveletName, TransformedWaveletDelta> deltas = - ArrayListMultimap.create(); - - /** The current versions of the user's wavelets, including index wavelets */ - private final Map<WaveletName, HashedVersion> versions = Maps.newHashMap(); - - /** The user that is connected to this server */ - private ParticipantId user = null; - - - @Override - public void openRequest(ParticipantId participant, WaveId waveId, IdFilter waveletIdFilter, - Collection<WaveClientRpc.WaveletVersion> knownWavelets, OpenListener openListener) { - if (user == null) { - user = participant; - } else { - Preconditions.checkArgument(participant.equals(user), "Unexpected user"); - } - - super.openRequest(participant, waveId, waveletIdFilter, knownWavelets, openListener); - - Map<WaveletId, WaveletData> wavelets = waves.get(waveId); - if (wavelets != null) { - // Send any deltas we have in this wave to the client, in the order we got - // them. - for (WaveletData wavelet : wavelets.values()) { - WaveletName name = WaveletName.of(wavelet.getWaveId(), wavelet.getWaveletId()); - waveletUpdate(wavelet, DeltaSequence.of(deltas.get(name))); - } - } - } - - @Override - public void submitRequest(ParticipantId loggedInUser, WaveletName waveletName, - ProtocolWaveletDelta delta, @Nullable String channelId, SubmitRequestListener listener) { - super.submitRequest(loggedInUser, waveletName, delta, channelId, listener); - - Map<WaveletId, WaveletData> wavelets = waves.get(waveletName.waveId); - if (wavelets == null) { - wavelets = Maps.newHashMap(); - waves.put(waveletName.waveId, wavelets); - } - - WaveletData wavelet = wavelets.get(waveletName.waveletId); - if (wavelet == null) { - long dummyCreationTime = System.currentTimeMillis(); - wavelet = WaveletDataUtil.createEmptyWavelet( - waveletName, ParticipantId.ofUnsafe(delta.getAuthor()), - HashedVersion.unsigned(0), dummyCreationTime); - wavelets.put(waveletName.waveletId, wavelet); - } - - // Add the delta to the history and update the wavelet's version. - HashedVersion resultingVersion = updateAndGetVersion(waveletName, delta.getOperationCount()); - TransformedWaveletDelta versionedDelta = CoreWaveletOperationSerializer.deserialize(delta, - resultingVersion, APP_TIMESTAMP); - deltas.put(waveletName, versionedDelta); - - // Confirm submit success. - doSubmitSuccess(waveletName, resultingVersion, APP_TIMESTAMP); - // Send an update echoing the submitted delta. Note: the document state is - // ignored. - waveletUpdate(wavelet, DeltaSequence.of(versionedDelta)); - // Send a corresponding update of the index wave. - } - - /** - * Updates and returns the version of a given wavelet. - * - * @param waveletName of the wavelet whose version to update. - * @param operationsCount applied to the wavelet. - * @return the new hashed version of the wavelet. - */ - private HashedVersion updateAndGetVersion(WaveletName waveletName, int operationsCount) { - // Get the current version. - HashedVersion version = versions.get(waveletName); - - // Calculate the new version. - if (version != null) { - version = HashedVersion.unsigned(version.getVersion() + operationsCount); - } else { - version = HashedVersion.unsigned(operationsCount); - } - - // Store and return the new version. - versions.put(waveletName, version); - return version; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/AccountStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/AccountStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/AccountStore.java deleted file mode 100644 index 877368d..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/AccountStore.java +++ /dev/null @@ -1,63 +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.persistence; - -import org.waveprotocol.box.server.account.AccountData; -import org.waveprotocol.wave.model.wave.ParticipantId; - -/** - * Interface for the storage and retrieval of {@link AccountData}s. - * - * @author [email protected] (Lennard de Rijk) - */ -public interface AccountStore { - /** - * Initialize the account store. - * Implementations are expected to validate any configuration values, validate the state of the - * store, and perform an start-up action needed (e.g. load list of accounts into memory, - * establish connection to database, etc...). - * - * @throws PersistenceException - */ - void initializeAccountStore() throws PersistenceException; - - /** - * Returns an {@link AccountData} for the given username or null if not - * exists. - * - * @param id participant id of the requested account. - */ - AccountData getAccount(ParticipantId id) throws PersistenceException; - - /** - * Puts the given {@link AccountData} in the storage, overrides an existing - * account if the username is already in use. - * - * @param account to store. - */ - void putAccount(AccountData account) throws PersistenceException; - - /** - * Removes an account from storage. - * - * @param id the participant id of the account to remove. - */ - void removeAccount(ParticipantId id) throws PersistenceException; -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentStore.java deleted file mode 100644 index 3452476..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentStore.java +++ /dev/null @@ -1,105 +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.persistence; - -import org.waveprotocol.box.attachment.AttachmentMetadata; -import org.waveprotocol.wave.media.model.AttachmentId; - -import java.io.IOException; -import java.io.InputStream; - -/** - * An attachment store is a place for storing attachment data. - * - * @author [email protected] (Joseph Gentle) - * @author [email protected] (A. Kaplanov) - */ -public interface AttachmentStore { - - interface AttachmentData { - - public InputStream getInputStream() throws IOException; - - public long getSize(); - } - - /** - * Fetch an attachment metadata. - * - * @param attachmentId - * @return the attachment metadata, or null if the metadata - * does not exist - */ - AttachmentMetadata getMetadata(AttachmentId attachmentId) throws IOException; - - /** - * Fetch an attachment with the specified id. - * - * @param attachmentId - * @return the attachment with the specified id, or null if the attachment - * does not exist - */ - AttachmentData getAttachment(AttachmentId attachmentId) throws IOException; - - /** - * Fetch an attachment thumbnail. - * - * @param attachmentId - * @return the attachment thumbnail - */ - AttachmentData getThumbnail(AttachmentId attachmentId) throws IOException; - - /** - * Store a new attachment with the specified id and data. - * - * @param attachmentId - * @param metaData attachment metadata - * @throws IOException - */ - void storeMetadata(AttachmentId attachmentId, AttachmentMetadata metaData) throws IOException; - - /** - * Store a new attachment with the specified id and data. - * - * @param attachmentId - * @param data A stream which contains the data to be stored - * @throws IOException - */ - void storeAttachment(AttachmentId attachmentId, InputStream data) throws IOException; - - /** - * Store a new attachment with the specified id and data. - * - * @param attachmentId - * @param metaData attachment metadata - * @throws IOException - */ - void storeThumbnail(AttachmentId attachmentId, InputStream dataData) throws IOException; - - /** - * Delete the specified attachment from the store. If the attachment does - * not exist, this has no effect. - * - * The behavior of calling any methods on an open AttachmentData object is - * undefined (implementation-specific). - * - * @param attachmentId - */ - void deleteAttachment(AttachmentId attachmentId); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentUtil.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentUtil.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentUtil.java deleted file mode 100644 index c61af57..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/AttachmentUtil.java +++ /dev/null @@ -1,101 +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.persistence; - -import org.waveprotocol.box.server.persistence.AttachmentStore.AttachmentData; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import org.waveprotocol.wave.model.id.IdConstants; -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.waveref.InvalidWaveRefException; -import org.waveprotocol.wave.model.waveref.WaveRef; -import org.waveprotocol.wave.util.escapers.jvm.JavaWaverefEncoder; -import org.waveprotocol.wave.util.logging.Log; - -/** - * Some utility methods for managing attachment data objects - * - * @author [email protected] (Joseph Gentle) - */ -public class AttachmentUtil { - private static final Log LOG = Log.get(AttachmentUtil.class); - - private AttachmentUtil() {} - - /** - * Write an input stream to an output stream. This will often be useful for - * implementors of AttachmentData.writeDataTo(). - * - * @param source The InputStream to read from - * @param dest The OutputStream to write to - * @throws IOException - */ - public static void writeTo(InputStream source, OutputStream dest) throws IOException { - byte[] buffer = new byte[256]; - int length; - while ((length = source.read(buffer)) != -1) { - dest.write(buffer, 0, length); - } - } - - /** - * Write the attachment out to a string. - * - * @param encoding The string encoding format of the data. Eg, "UTF-8". - * @return A string representation of the attachment data. - * @throws IOException - */ - public static String writeAttachmentDataToString( - AttachmentData data, String encoding) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - writeTo(data.getInputStream(), stream); - return stream.toString(encoding); - } - - /** - * Decode wavelet name. - * - * @param waveRefStr encoded name. - * @return WaveletName object. - */ - public static WaveletName waveRef2WaveletName(String waveRefStr) { - WaveRef waveRef = null; - try { - waveRef = JavaWaverefEncoder.decodeWaveRefFromPath(waveRefStr); - } catch (InvalidWaveRefException e) { - LOG.warning("Cannot decode: " + waveRefStr, e); - return null; - } - - WaveId waveId = waveRef.getWaveId(); - WaveletId waveletId = - waveRef.getWaveletId() != null ? waveRef.getWaveletId() : WaveletId.of(waveId.getDomain(), - IdConstants.CONVERSATION_ROOT_WAVELET); - - WaveletName waveletName = WaveletName.of(waveId, waveletId); - return waveletName; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/FakePermissiveAccountStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/FakePermissiveAccountStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/FakePermissiveAccountStore.java deleted file mode 100644 index fcefc18..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/FakePermissiveAccountStore.java +++ /dev/null @@ -1,68 +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.persistence; - -import org.waveprotocol.box.server.account.AccountData; -import org.waveprotocol.box.server.account.HumanAccountDataImpl; -import org.waveprotocol.box.server.authentication.PasswordDigest; -import org.waveprotocol.wave.model.util.CollectionUtils; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.util.Map; - -/** - * An account store which on-the-fly creates a userdata object for any account - * requested. The created user has an empty password. - * - * This class exists to ease development until persistence is in. It will be - * removed once persistence works. - * - * @author [email protected] (Joseph Gentle) - */ -public class FakePermissiveAccountStore implements AccountStore { - Map<ParticipantId, AccountData> accounts = CollectionUtils.newHashMap(); - - @Override - public AccountData getAccount(ParticipantId id) { - AccountData account = accounts.get(id); - - if (account == null && !id.getAddress().startsWith("xxx")) { - account = new HumanAccountDataImpl(id, new PasswordDigest("".toCharArray())); - accounts.put(id, account); - } - - return account; - } - - @Override - public void initializeAccountStore() { - // Nothing to initialize. - } - - @Override - public void putAccount(AccountData account) { - accounts.put(account.getId(), account); - } - - @Override - public void removeAccount(ParticipantId id) { - accounts.remove(id); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/FileNotFoundPersistenceException.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/FileNotFoundPersistenceException.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/FileNotFoundPersistenceException.java deleted file mode 100644 index c12b8a8..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/FileNotFoundPersistenceException.java +++ /dev/null @@ -1,44 +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.persistence; - -/** - * {@link Exception} thrown when a persistence operation can not locate a file. - * - * @author [email protected] (Lennard de Rijk) - */ -public class FileNotFoundPersistenceException extends PersistenceException { - - public FileNotFoundPersistenceException() { - super(); - } - - public FileNotFoundPersistenceException(String message, Throwable cause) { - super(message, cause); - } - - public FileNotFoundPersistenceException(String message) { - super(message); - } - - public FileNotFoundPersistenceException(Throwable cause) { - super(cause); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceException.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceException.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceException.java deleted file mode 100644 index 57c417e..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceException.java +++ /dev/null @@ -1,44 +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.persistence; - -/** - * {@link Exception} thrown when a persistence operation has failed. - * - * @author [email protected] (Tad Glines) - */ -public class PersistenceException extends Exception { - - public PersistenceException() { - super(); - } - - public PersistenceException(String message, Throwable cause) { - super(message, cause); - } - - public PersistenceException(String message) { - super(message); - } - - public PersistenceException(Throwable cause) { - super(cause); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceModule.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceModule.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceModule.java deleted file mode 100644 index 2ce3a32..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceModule.java +++ /dev/null @@ -1,154 +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.persistence; - -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.persistence.file.FileAccountStore; -import org.waveprotocol.box.server.persistence.file.FileAttachmentStore; -import org.waveprotocol.box.server.persistence.file.FileDeltaStore; -import org.waveprotocol.box.server.persistence.file.FileSignerInfoStore; -import org.waveprotocol.box.server.persistence.memory.MemoryDeltaStore; -import org.waveprotocol.box.server.persistence.memory.MemoryStore; -import org.waveprotocol.box.server.persistence.mongodb.MongoDbProvider; -import org.waveprotocol.box.server.waveserver.DeltaStore; -import org.waveprotocol.wave.crypto.CertPathStore; - -/** - * Module for setting up the different persistence stores. - * - *<p> - * The valid names for the cert store are 'memory', 'file' and 'mongodb' - * - *<p> - *The valid names for the attachment store are 'disk' and 'mongodb' - * - *<p> - *The valid names for the account store are 'memory', 'file' and 'mongodb'. - * - * @author [email protected] (Lennard de Rijk) - */ -public class PersistenceModule extends AbstractModule { - - private final String signerInfoStoreType; - - private final String attachmentStoreType; - - private final String accountStoreType; - - private final String deltaStoreType; - - private MongoDbProvider mongoDbProvider; - - private final String mongoDBHost; - - private final String mongoDBPort; - - private final String mongoDBdatabase; - - - @Inject - public PersistenceModule(Config config) { - this.signerInfoStoreType = config.getString("core.signer_info_store_type"); - this.attachmentStoreType = config.getString("core.attachment_store_type"); - this.accountStoreType = config.getString("core.account_store_type"); - this.deltaStoreType = config.getString("core.delta_store_type"); - this.mongoDBHost = config.getString("core.mongodb_host"); - this.mongoDBPort = config.getString("core.mongodb_port"); - this.mongoDBdatabase = config.getString("core.mongodb_database"); - } - - /** - * Returns a {@link MongoDbProvider} instance. - */ - public MongoDbProvider getMongoDbProvider() { - if (mongoDbProvider == null) { - mongoDbProvider = new MongoDbProvider(mongoDBHost, mongoDBPort, mongoDBdatabase); - } - return mongoDbProvider; - } - - @Override - protected void configure() { - bindCertPathStore(); - bindAttachmentStore(); - bindAccountStore(); - bindDeltaStore(); - } - - /** - * Binds the CertPathStore implementation to the store specified in the - * properties. - */ - private void bindCertPathStore() { - if (signerInfoStoreType.equalsIgnoreCase("memory")) { - bind(CertPathStore.class).to(MemoryStore.class).in(Singleton.class); - } else if (signerInfoStoreType.equalsIgnoreCase("file")) { - bind(CertPathStore.class).to(FileSignerInfoStore.class).in(Singleton.class); - } else if (signerInfoStoreType.equalsIgnoreCase("mongodb")) { - MongoDbProvider mongoDbProvider = getMongoDbProvider(); - bind(CertPathStore.class).toInstance(mongoDbProvider.provideMongoDbStore()); - } else { - throw new RuntimeException( - "Invalid certificate path store type: '" + signerInfoStoreType + "'"); - } - } - - private void bindAttachmentStore() { - if (attachmentStoreType.equalsIgnoreCase("disk")) { - bind(AttachmentStore.class).to(FileAttachmentStore.class).in(Singleton.class); - } else if (attachmentStoreType.equalsIgnoreCase("mongodb")) { - MongoDbProvider mongoDbProvider = getMongoDbProvider(); - bind(AttachmentStore.class).toInstance(mongoDbProvider.provideMongoDbStore()); - } else { - throw new RuntimeException("Invalid attachment store type: '" + attachmentStoreType + "'"); - } - } - - private void bindAccountStore() { - if (accountStoreType.equalsIgnoreCase("memory")) { - bind(AccountStore.class).to(MemoryStore.class).in(Singleton.class); - } else if (accountStoreType.equalsIgnoreCase("file")) { - bind(AccountStore.class).to(FileAccountStore.class).in(Singleton.class); - } else if (accountStoreType.equalsIgnoreCase("fake")) { - bind(AccountStore.class).to(FakePermissiveAccountStore.class).in(Singleton.class); - } else if (accountStoreType.equalsIgnoreCase("mongodb")) { - MongoDbProvider mongoDbProvider = getMongoDbProvider(); - bind(AccountStore.class).toInstance(mongoDbProvider.provideMongoDbStore()); - } else { - throw new RuntimeException("Invalid account store type: '" + accountStoreType + "'"); - } - } - - private void bindDeltaStore() { - if (deltaStoreType.equalsIgnoreCase("memory")) { - bind(DeltaStore.class).to(MemoryDeltaStore.class).in(Singleton.class); - } else if (deltaStoreType.equalsIgnoreCase("file")) { - bind(DeltaStore.class).to(FileDeltaStore.class).in(Singleton.class); - } else if (deltaStoreType.equalsIgnoreCase("mongodb")) { - MongoDbProvider mongoDbProvider = getMongoDbProvider(); - bind(DeltaStore.class).toInstance(mongoDbProvider.provideMongoDbDeltaStore()); - } else { - throw new RuntimeException("Invalid delta store type: '" + deltaStoreType + "'"); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceStartException.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceStartException.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceStartException.java deleted file mode 100644 index aaa693a..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/PersistenceStartException.java +++ /dev/null @@ -1,34 +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.persistence; - -/** - * {@link Exception} thrown when a persistence system fails to start. - * - * @author [email protected] (Lennard de Rijk) - * - */ -public class PersistenceStartException extends RuntimeException { - - public PersistenceStartException(String message, Throwable e) { - super(message, e); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/SignerInfoStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/SignerInfoStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/SignerInfoStore.java deleted file mode 100644 index 7447170..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/SignerInfoStore.java +++ /dev/null @@ -1,32 +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.persistence; - -import org.waveprotocol.wave.crypto.CertPathStore; - -/** - * Extends {@link CertPathStore} to include initialization method. - * For use in persistence implementations. - * - * @author [email protected](Tad Glines) - */ -public interface SignerInfoStore extends CertPathStore { - void initializeSignerInfoStore() throws PersistenceException; -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/file/DeltaIndex.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/DeltaIndex.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/file/DeltaIndex.java deleted file mode 100644 index a34250b..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/DeltaIndex.java +++ /dev/null @@ -1,213 +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.persistence.file; - -import com.google.common.base.Preconditions; - -import org.waveprotocol.wave.model.util.Pair; - -import java.io.EOFException; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * An index for quickly accessing deltas. The index is an array of longs, one for each version. - * - * The index must return the offset of a delta applied at a version, and of a delta leading to - * a version. - * - * Internal format: - * - * Let's assume that operations are 10 bytes long. Deltas are separated by |. - * <pre> - * Deltas: | 0 1 2 | 3 | 4 5 | - * offset 0 30 40 60 - * - * Index: 0 -1 -1 30 40 -41 - * </pre> - * The file contains a negative value for any version for which there is not a delta. This will - * happen whenever the previous delta contains multiple ops. This negative value is ~offset of - * the delta containing the op, so that finding the delta leading to a version is easy: just read - * the previous index entry. - * - * @author [email protected] (Joseph Gentle) - */ -public class DeltaIndex { - /** Returned from methods when there is no record for a specified version. */ - public static final int NO_RECORD_FOR_VERSION = -1; - - private static final int RECORD_LENGTH = 8; - private final File fileRef; - private RandomAccessFile file; - - public DeltaIndex(File indexFile) { - this.fileRef = indexFile; - } - - /** - * Open the index. - * - * @param baseCollection the collection which the index indexes. - * @throws IOException - */ - public void openForCollection(FileDeltaCollection baseCollection) throws IOException { - if (!fileRef.exists()) { - fileRef.mkdirs(); - rebuildIndexFromDeltas(baseCollection); - } else { - // TODO(josephg): For now, we just rebuild the index anyway. - rebuildIndexFromDeltas(baseCollection); - } - } - - private void checkOpen() { - Preconditions.checkState(file != null, "Index file not open"); - } - - /** - * Rebuild the index based on a delta collection. This will wipe the index file. - * - * @param collection - * @throws IOException - */ - public void rebuildIndexFromDeltas(FileDeltaCollection collection) throws IOException { - if (file != null) { - file.close(); - } - - if (fileRef.exists()) { - fileRef.delete(); - } - - file = FileUtils.getOrCreateFile(fileRef); - - for (Pair<Pair<Long, Integer>, Long> pair : collection.getOffsetsIterator()) { - addDelta(pair.first.first, pair.first.second, pair.second); - } - } - - /** - * Get the delta file offset for the specified version. - * - * @param version - * @return the offset on success, NO_RECORD_FOR_VERSION if there's no record. - * @throws IOException - */ - public long getOffsetForVersion(long version) throws IOException { - if (!seekToPosition(version)) { - return NO_RECORD_FOR_VERSION; - } - long offset = file.readLong(); - return offset < 0 ? NO_RECORD_FOR_VERSION : offset; - } - - /** - * Get the delta file offset for the specified end version. - * - * @param version - * @return the offset on success, NO_RECORD_FOR_VERSION if there's no record. - * @throws IOException - */ - public long getOffsetForEndVersion(long version) throws IOException { - if (!seekToPosition(version - 1)) { - return NO_RECORD_FOR_VERSION; - } - long offset = file.readLong(); - try { - if (file.readLong() < 0) { - // user tried to read something which isn't an end version - return NO_RECORD_FOR_VERSION; - } - } catch (EOFException e) { - // it's ok to hit the end of the file, for the last end version - } - return offset < 0 ? ~offset : offset; - } - - /** - * Seeks to the corresponding version, if it is valid. - * - * @param version version to seek to. - * @return true iff the position is valid - * @throws IOException - */ - private boolean seekToPosition(long version) throws IOException { - if (version < 0) { - return false; - } - checkOpen(); - - long position = version * RECORD_LENGTH; - if (position >= file.length()) { - return false; - } - - file.seek(position); - return true; - } - - /** - * Indexes a new delta. - * - * @param version the version at which the delta is applied - * @param numOperations number of operations in the delta - * @param offset offset at which the delta is stored - */ - public void addDelta(long version, int numOperations, long offset) - throws IOException { - checkOpen(); - - long position = version * RECORD_LENGTH; - // We're expected to append the new delta - long fileLength = file.length(); - Preconditions.checkState(position == fileLength, - "position = %d, file=%d", position, fileLength); - file.seek(position); - file.writeLong(offset); - // fill in the additional positions with the 1-complement of the offset, - for (int i = 1; i < numOperations; i++) { - file.writeLong(~offset); - } - } - - /** - * @return number of records in the index - */ - public long length() { - checkOpen(); - - long fileLength; - try { - fileLength = file.length(); - } catch (IOException e) { - // This shouldn't happen in practice. - throw new RuntimeException("IO error reading index file length", e); - } - return fileLength / RECORD_LENGTH; - } - - public void close() throws IOException { - if (file != null) { - file.close(); - file = null; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAccountStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAccountStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAccountStore.java deleted file mode 100644 index 8485815..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAccountStore.java +++ /dev/null @@ -1,135 +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.persistence.file; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import com.google.inject.Inject; -import com.typesafe.config.Config; -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.persistence.protos.ProtoAccountDataSerializer; -import org.waveprotocol.box.server.persistence.protos.ProtoAccountStoreData.ProtoAccountData; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.util.logging.Log; - -import java.io.*; -import java.util.Map; - -/** - * A flat file based implementation of {@link AccountStore} - * - * @author [email protected] (Tad Glines) - */ -public class FileAccountStore implements AccountStore { - private static final String ACCOUNT_FILE_EXTENSION = ".account"; - private final String accountStoreBasePath; - private final Map<ParticipantId, AccountData> accounts = Maps.newHashMap(); - - private static final Log LOG = Log.get(FileAccountStore.class); - - @Inject - public FileAccountStore(Config config) { - this.accountStoreBasePath = config.getString("core.account_store_directory"); - } - - @Override - public void initializeAccountStore() throws PersistenceException { - FileUtils.performDirectoryChecks(accountStoreBasePath, ACCOUNT_FILE_EXTENSION, "account store", - LOG); - } - - @Override - public AccountData getAccount(ParticipantId id) throws PersistenceException { - synchronized (accounts) { - AccountData account = accounts.get(id); - if (account == null) { - account = readAccount(id); - if (account != null) { - accounts.put(id, account); - } - } - return account; - } - } - - @Override - public void putAccount(AccountData account) throws PersistenceException { - synchronized (accounts) { - Preconditions.checkNotNull(account); - writeAccount(account); - accounts.put(account.getId(), account); - } - } - - @Override - public void removeAccount(ParticipantId id) throws PersistenceException { - synchronized (accounts) { - File file = new File(participantIdToFileName(id)); - if (file.exists()) { - if (!file.delete()) { - throw new PersistenceException("Failed to delete account data associated with " - + id.getAddress()); - } - } - accounts.remove(id); - } - } - - private String participantIdToFileName(ParticipantId id) { - return accountStoreBasePath + File.separator + id.getAddress().toLowerCase() - + ACCOUNT_FILE_EXTENSION; - } - - private AccountData readAccount(ParticipantId id) throws PersistenceException { - File accountFile = new File(participantIdToFileName(id)); - FileInputStream file = null; - try { - if (!accountFile.exists()) { - return null; - } - file = new FileInputStream(accountFile); - ProtoAccountData data = ProtoAccountData.newBuilder().mergeFrom(file).build(); - return ProtoAccountDataSerializer.deserialize(data); - } catch (IOException e) { - LOG.severe("Failed to read account data from file: " + accountFile.getAbsolutePath(), e); - throw new PersistenceException(e); - } finally { - FileUtils.closeAndIgnoreException(file, accountFile, LOG); - } - } - - private void writeAccount(AccountData account) throws PersistenceException { - File accountFile = new File(participantIdToFileName(account.getId())); - OutputStream file = null; - try { - file = new FileOutputStream(accountFile); - ProtoAccountData data = ProtoAccountDataSerializer.serialize(account); - file.write(data.toByteArray()); - file.flush(); - } catch (IOException e) { - LOG.severe("Failed to write account data to file: " + accountFile.getAbsolutePath(), e); - throw new PersistenceException(e); - } finally { - FileUtils.closeAndIgnoreException(file, accountFile, LOG); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAttachmentStore.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAttachmentStore.java b/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAttachmentStore.java deleted file mode 100644 index 64097ea..0000000 --- a/wave/src/main/java/org/waveprotocol/box/server/persistence/file/FileAttachmentStore.java +++ /dev/null @@ -1,176 +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.persistence.file; - -import com.google.inject.Inject; -import com.typesafe.config.Config; -import org.waveprotocol.box.attachment.AttachmentMetadata; -import org.waveprotocol.box.attachment.AttachmentProto; -import org.waveprotocol.box.attachment.proto.AttachmentMetadataProtoImpl; -import org.waveprotocol.box.server.persistence.AttachmentStore; -import org.waveprotocol.wave.media.model.AttachmentId; -import org.waveprotocol.wave.model.util.CharBase64; - -import java.io.*; - -/** - * An implementation of AttachmentStore which uses files on disk - * - * @author [email protected] (Joseph Gentle) - * @author [email protected] (A. Kaplanov) - */ -public class FileAttachmentStore implements AttachmentStore { - - private final static String META_EXT = ".meta"; - private final static String THUMBNAIL_EXT = ".thumbnail"; - - /** - * The directory in which the attachments are stored. - */ - private final String basePath; - - @Inject - public FileAttachmentStore(Config config) { - this.basePath = config.getString("core.attachment_store_directory"); - new File(basePath).mkdirs(); - } - - @Override - public AttachmentMetadata getMetadata(AttachmentId attachmentId) throws IOException { - File file = new File(getMetadataPath(attachmentId)); - if (!file.exists()) { - return null; - } - AttachmentProto.AttachmentMetadata protoMetadata = - AttachmentProto.AttachmentMetadata.parseFrom(new FileInputStream(file)); - return new AttachmentMetadataProtoImpl(protoMetadata); - } - - @Override - public AttachmentData getAttachment(AttachmentId attachmentId) throws IOException { - final File file = new File(getAttachmentPath(attachmentId)); - if (!file.exists()) { - return null; - } - return new AttachmentData() { - - @Override - public InputStream getInputStream() throws IOException { - return new FileInputStream(file); - } - - @Override - public long getSize() { - return file.length(); - } - }; - } - - @Override - public AttachmentData getThumbnail(AttachmentId attachmentId) throws IOException { - final File file = new File(getThumbnailPath(attachmentId)); - if (!file.exists()) { - return null; - } - return new AttachmentData() { - - @Override - public InputStream getInputStream() throws IOException { - return new FileInputStream(file); - } - - @Override - public long getSize() { - return file.length(); - } - }; - } - - @Override - public void storeMetadata(AttachmentId attachmentId, AttachmentMetadata metaData) throws IOException { - File file = new File(getMetadataPath(attachmentId)); - if (file.exists()) { - throw new IOException("Attachment already exist"); - } - FileOutputStream stream = new FileOutputStream(file); - AttachmentMetadataProtoImpl proto = new AttachmentMetadataProtoImpl(metaData); - proto.getPB().writeTo(stream); - stream.close(); - } - - @Override - public void storeAttachment(AttachmentId attachmentId, InputStream data) throws IOException { - File file = new File(getAttachmentPath(attachmentId)); - if (file.exists()) { - throw new IOException("Attachment already exist"); - } - FileOutputStream stream = new FileOutputStream(file); - writeTo(data, stream); - stream.close(); - } - - @Override - public void storeThumbnail(AttachmentId attachmentId, InputStream data) throws IOException { - File file = new File(getThumbnailPath(attachmentId)); - if (file.exists()) { - throw new IOException("Attachment already exist"); - } - FileOutputStream stream = new FileOutputStream(file); - writeTo(data, stream); - stream.close(); - } - - @Override - public void deleteAttachment(AttachmentId attachmentId) { - File file = new File(getAttachmentPath(attachmentId)); - if (file.exists()) { - file.delete(); - } - } - - private String getMetadataPath(AttachmentId attachmentId) { - return basePath + File.separatorChar + encodeId(attachmentId) + META_EXT; - } - - private String getAttachmentPath(AttachmentId attachmentId) { - return basePath + File.separatorChar + encodeId(attachmentId); - } - - private String getThumbnailPath(AttachmentId attachmentId) { - return basePath + File.separatorChar + encodeId(attachmentId) + THUMBNAIL_EXT; - } - - private static void writeTo(InputStream source, OutputStream dest) throws IOException { - byte[] buffer = new byte[256]; - int length; - while ((length = source.read(buffer)) != -1) { - dest.write(buffer, 0, length); - } - } - - private static String encodeId(AttachmentId id) { - try { - return CharBase64.encode(id.serialise().getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - -}
