return new MuxConnector() {
private void connectWavelet(StaticChannelBinder binder,
ObservableWaveletData wavelet) {
WaveletId waveletId = wavelet.getWaveletId();
SlobId objectId = IdHack.objectIdFromWaveletId(waveletId);
WaveletEntry data = wavelets.get(objectId);
Assert.check(data != null, "Unknown wavelet: %s", waveletId);
if (data.getChannelToken() == null) {
// TODO(danilatos): Handle with a nicer message, and maybe try to
// reconnect later.
Window.alert("Could not open a live connection to this wave. "
+ "It will be read-only, changes will not be saved!");
return;
}
String debugSuffix;
if (objectId.equals(convObjectId)) {
debugSuffix = "-c";
} else if (objectId.equals(udwObjectId)) {
debugSuffix = "-u";
} else {
debugSuffix = "-xxx";
}
ReceiveOpChannel<WaveletOperation> storeChannel =
new GaeReceiveOpChannel<WaveletOperation>(
objectId, data.getSignedSessionString(), data.getChannelToken(),
channelService, Logs.create("gaeroc" + debugSuffix)) {
@Override
protected WaveletOperation parse(ChangeData<JavaScriptObject> message)
throws MessageException {
return serializer.deserializeDelta(
message.getPayload().<DeltaJsoImpl>cast());
}
};
WalkaroundOperationChannel channel = new WalkaroundOperationChannel(
Logs.create("channel" + debugSuffix),
createSubmitService(objectId),
storeChannel, Versions.truncate(wavelet.getVersion()),
data.getSession().getClientId(),
indicator);
String id = ModernIdSerialiser.INSTANCE.serialiseWaveletId(waveletId);
binder.bind(id, channel);
}
@Override
public void connect(Command onOpened) {
if (isLive) {
WaveletOperationalizer operationalizer = getWavelets();
StaticChannelBinder binder = new StaticChannelBinder(
operationalizer, getDocumentRegistry());
for (ObservableWaveletData wavelet : operationalizer.getWavelets()) {
if (useUdw || !IdHack.DISABLED_UDW_ID.equals(wavelet.getWaveletId())) {
connectWavelet(binder, wavelet);
}
}
// HACK(ohler): I haven't tried to understand what the semantics of the callback
// are; perhaps we should invoke it even if the wave is static. (It seems to be
// null though.)
if (onOpened != null) {
onOpened.execute();
}
}
}
@Override
public void close() {
throw new AssertionError("close not implemented");
}
};
}
private SubmitDeltaService createSubmitService(final SlobId objectId) {
return new SubmitDeltaService(rpc, wavelets, objectId) {
@Override
public void requestRevision(final SendOpService.Callback callback) {
loadWaveService.fetchWaveRevision(
wavelets.get(objectId).getSignedSessionString(),
new ConnectCallback() {
@Override public void onData(ConnectResponse data) {
// TODO(danilatos): Update session id etc in the operation channel
// in order for (something equivalent to) this to work.
// But don't have submit delta service keep a reference to this map.
// ALSO TODO: channelToken could be null, if a channel could not be opened.
// In this case the object should be opened as readonly.
//wavelets.updateData(
// new WaveletEntry(id, channelToken, sid, xsrfToken, revision, null));
callback.onSuccess(Versions.truncate(data.getObjectVersion()));
}
@Override public void onConnectionError(Throwable e) {
callback.onConnectionError(e);
}