http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/WaveWebSocketClient.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/WaveWebSocketClient.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/WaveWebSocketClient.java deleted file mode 100644 index 167ea94..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/WaveWebSocketClient.java +++ /dev/null @@ -1,246 +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.webclient.client; - -import static org.waveprotocol.wave.communication.gwt.JsonHelper.getPropertyAsInteger; -import static org.waveprotocol.wave.communication.gwt.JsonHelper.getPropertyAsObject; -import static org.waveprotocol.wave.communication.gwt.JsonHelper.getPropertyAsString; -import static org.waveprotocol.wave.communication.gwt.JsonHelper.setPropertyAsInteger; -import static org.waveprotocol.wave.communication.gwt.JsonHelper.setPropertyAsObject; -import static org.waveprotocol.wave.communication.gwt.JsonHelper.setPropertyAsString; - -import com.google.common.base.Preconditions; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.RepeatingCommand; -import com.google.gwt.user.client.Cookies; - -import org.waveprotocol.box.common.comms.jso.ProtocolAuthenticateJsoImpl; -import org.waveprotocol.box.common.comms.jso.ProtocolOpenRequestJsoImpl; -import org.waveprotocol.box.common.comms.jso.ProtocolSubmitRequestJsoImpl; -import org.waveprotocol.box.common.comms.jso.ProtocolSubmitResponseJsoImpl; -import org.waveprotocol.box.common.comms.jso.ProtocolWaveletUpdateJsoImpl; -import org.waveprotocol.wave.client.events.ClientEvents; -import org.waveprotocol.wave.client.events.Log; -import org.waveprotocol.wave.client.events.NetworkStatusEvent; -import org.waveprotocol.wave.client.events.NetworkStatusEvent.ConnectionStatus; -import org.waveprotocol.wave.communication.gwt.JsonMessage; -import org.waveprotocol.wave.communication.json.JsonException; -import org.waveprotocol.wave.model.util.CollectionUtils; -import org.waveprotocol.wave.model.util.IntMap; - -import java.util.Queue; -import org.waveprotocol.box.stat.Timer; -import org.waveprotocol.box.stat.Timing; - - -/** - * Wrapper around WebSocket that handles the Wave client-server protocol. - */ -public class WaveWebSocketClient implements WaveSocket.WaveSocketCallback { - private static final int MAX_INITIAL_FAILURES = 2; - private static final Log LOG = Log.get(WaveWebSocketClient.class); - private static final int RECONNECT_TIME_MS = 5000; - private static final String JETTY_SESSION_TOKEN_NAME = "JSESSIONID"; - - /** - * Envelope for delivering arbitrary messages. Each envelope has a sequence - * number and a message. The format must match the format used in the server's - * WebSocketChannel. - * <p> - * Note that this message can not be described by a protobuf, because it - * contains an arbitrary protobuf, which breaks the protobuf typing rules. - */ - private static final class MessageWrapper extends JsonMessage { - static MessageWrapper create(int seqno, String type, JsonMessage message) { - MessageWrapper wrapper = JsonMessage.createJsonMessage().cast(); - setPropertyAsInteger(wrapper, "sequenceNumber", seqno); - setPropertyAsString(wrapper, "messageType", type); - setPropertyAsObject(wrapper, "message", message); - return wrapper; - } - - @SuppressWarnings("unused") // GWT requires an explicit protected ctor - protected MessageWrapper() { - super(); - } - - int getSequenceNumber() { - return getPropertyAsInteger(this, "sequenceNumber"); - } - - String getType() { - return getPropertyAsString(this, "messageType"); - } - - <T extends JsonMessage> T getPayload() { - return getPropertyAsObject(this, "message").<T>cast(); - } - } - - private WaveSocket socket; - private final IntMap<SubmitResponseCallback> submitRequestCallbacks; - - /** - * Lifecycle of a socket is: - * (CONNECTING → CONNECTED → DISCONNECTED)∗ - */ - private enum ConnectState { - CONNECTED, CONNECTING, DISCONNECTED - } - - private ConnectState connected = ConnectState.DISCONNECTED; - private WaveWebSocketCallback callback; - private int sequenceNo; - - private final Queue<JsonMessage> messages = CollectionUtils.createQueue(); - - private final RepeatingCommand reconnectCommand = new RepeatingCommand() { - @Override - public boolean execute() { - if (!connectedAtLeastOnce && !websocketNotAvailable && connectTry > MAX_INITIAL_FAILURES) { - // Let's try to use websocket alternative, seems that websocket it's not working - // (we are under a proxy or similar) - socket = WaveSocketFactory.create(true, urlBase, WaveWebSocketClient.this); - } - connectTry++; - if (connected == ConnectState.DISCONNECTED) { - LOG.info("Attemping to reconnect"); - connected = ConnectState.CONNECTING; - socket.connect(); - } - return true; - } - }; - private final boolean websocketNotAvailable; - private boolean connectedAtLeastOnce = false; - private long connectTry = 0; - private final String urlBase; - - public WaveWebSocketClient(boolean websocketNotAvailable, String urlBase) { - this.websocketNotAvailable = websocketNotAvailable; - this.urlBase = urlBase; - submitRequestCallbacks = CollectionUtils.createIntMap(); - socket = WaveSocketFactory.create(websocketNotAvailable, urlBase, this); - } - - /** - * Attaches the handler for incoming messages. Once the client's workflow has - * been fixed, this callback attachment will become part of - * {@link #connect()}. - */ - public void attachHandler(WaveWebSocketCallback callback) { - Preconditions.checkState(this.callback == null); - Preconditions.checkArgument(callback != null); - this.callback = callback; - } - - /** - * Opens this connection. - */ - public void connect() { - reconnectCommand.execute(); - Scheduler.get().scheduleFixedDelay(reconnectCommand, RECONNECT_TIME_MS); - } - - @Override - public void onConnect() { - connected = ConnectState.CONNECTED; - connectedAtLeastOnce = true; - - // Sends the session cookie to the server via an RPC to work around browser bugs. - // See: http://code.google.com/p/wave-protocol/issues/detail?id=119 - String token = Cookies.getCookie(JETTY_SESSION_TOKEN_NAME); - if (token != null) { - ProtocolAuthenticateJsoImpl auth = ProtocolAuthenticateJsoImpl.create(); - auth.setToken(token); - send(MessageWrapper.create(sequenceNo++, "ProtocolAuthenticate", auth)); - } - - // Flush queued messages. - while (!messages.isEmpty() && connected == ConnectState.CONNECTED) { - send(messages.poll()); - } - - ClientEvents.get().fireEvent(new NetworkStatusEvent(ConnectionStatus.CONNECTED)); - } - - @Override - public void onDisconnect() { - connected = ConnectState.DISCONNECTED; - ClientEvents.get().fireEvent(new NetworkStatusEvent(ConnectionStatus.DISCONNECTED)); - } - - @Override - public void onMessage(final String message) { - LOG.info("received JSON message " + message); - Timer timer = Timing.start("deserialize message"); - MessageWrapper wrapper; - try { - wrapper = MessageWrapper.parse(message); - } catch (JsonException e) { - LOG.severe("invalid JSON message " + message, e); - return; - } finally { - Timing.stop(timer); - } - String messageType = wrapper.getType(); - if ("ProtocolWaveletUpdate".equals(messageType)) { - if (callback != null) { - callback.onWaveletUpdate(wrapper.<ProtocolWaveletUpdateJsoImpl>getPayload()); - } - } else if ("ProtocolSubmitResponse".equals(messageType)) { - int seqno = wrapper.getSequenceNumber(); - SubmitResponseCallback callback = submitRequestCallbacks.get(seqno); - if (callback != null) { - submitRequestCallbacks.remove(seqno); - callback.run(wrapper.<ProtocolSubmitResponseJsoImpl>getPayload()); - } - } - } - - public void submit(ProtocolSubmitRequestJsoImpl message, SubmitResponseCallback callback) { - int submitId = sequenceNo++; - submitRequestCallbacks.put(submitId, callback); - send(MessageWrapper.create(submitId, "ProtocolSubmitRequest", message)); - } - - public void open(ProtocolOpenRequestJsoImpl message) { - send(MessageWrapper.create(sequenceNo++, "ProtocolOpenRequest", message)); - } - - private void send(JsonMessage message) { - switch (connected) { - case CONNECTED: - Timer timing = Timing.start("serialize message"); - String json; - try { - json = message.toJson(); - } finally { - Timing.stop(timing); - } - LOG.info("Sending JSON data " + json); - socket.sendMessage(json); - break; - default: - messages.add(message); - } - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/WebClient.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/WebClient.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/WebClient.java deleted file mode 100644 index 2a7af76..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/WebClient.java +++ /dev/null @@ -1,496 +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.webclient.client; - -import com.google.gwt.core.client.EntryPoint; -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.OptionElement; -import com.google.gwt.dom.client.SelectElement; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.http.client.UrlBuilder; -import com.google.gwt.i18n.client.LocaleInfo; -import com.google.gwt.resources.client.CssResource; -import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.History; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.Window.Location; -import com.google.gwt.user.client.ui.DockLayoutPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.SplitLayoutPanel; -import com.google.gwt.user.client.ui.UIObject; - -import org.waveprotocol.box.webclient.client.i18n.WebClientMessages; -import org.waveprotocol.box.webclient.profile.RemoteProfileManagerImpl; -import org.waveprotocol.box.webclient.search.RemoteSearchService; -import org.waveprotocol.box.webclient.search.Search; -import org.waveprotocol.box.webclient.search.SearchPanelRenderer; -import org.waveprotocol.box.webclient.search.SearchPanelWidget; -import org.waveprotocol.box.webclient.search.SearchPresenter; -import org.waveprotocol.box.webclient.search.SimpleSearch; -import org.waveprotocol.box.webclient.search.WaveStore; -import org.waveprotocol.box.webclient.widget.error.ErrorIndicatorPresenter; -import org.waveprotocol.box.webclient.widget.frame.FramedPanel; -import org.waveprotocol.box.webclient.widget.loading.LoadingIndicator; -import org.waveprotocol.wave.client.account.ProfileManager; -import org.waveprotocol.wave.client.common.safehtml.SafeHtml; -import org.waveprotocol.wave.client.common.safehtml.SafeHtmlBuilder; -import org.waveprotocol.wave.client.common.util.AsyncHolder.Accessor; -import org.waveprotocol.wave.client.debug.logger.LogLevel; -import org.waveprotocol.wave.client.doodad.attachment.AttachmentManagerImpl; -import org.waveprotocol.wave.client.doodad.attachment.AttachmentManagerProvider; -import org.waveprotocol.wave.client.events.ClientEvents; -import org.waveprotocol.wave.client.events.Log; -import org.waveprotocol.wave.client.events.NetworkStatusEvent; -import org.waveprotocol.wave.client.events.NetworkStatusEventHandler; -import org.waveprotocol.wave.client.events.WaveCreationEvent; -import org.waveprotocol.wave.client.events.WaveCreationEventHandler; -import org.waveprotocol.wave.client.events.WaveSelectionEvent; -import org.waveprotocol.wave.client.events.WaveSelectionEventHandler; -import org.waveprotocol.wave.client.wavepanel.event.EventDispatcherPanel; -import org.waveprotocol.wave.client.wavepanel.event.WaveChangeHandler; -import org.waveprotocol.wave.client.wavepanel.event.FocusManager; -import org.waveprotocol.wave.client.widget.common.ImplPanel; -import org.waveprotocol.wave.client.widget.popup.CenterPopupPositioner; -import org.waveprotocol.wave.client.widget.popup.PopupChrome; -import org.waveprotocol.wave.client.widget.popup.PopupChromeFactory; -import org.waveprotocol.wave.client.widget.popup.PopupFactory; -import org.waveprotocol.wave.client.widget.popup.UniversalPopup; -import org.waveprotocol.wave.model.id.IdGenerator; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.waveref.InvalidWaveRefException; -import org.waveprotocol.wave.model.waveref.WaveRef; -import org.waveprotocol.wave.util.escapers.GwtWaverefEncoder; - -import java.util.Date; -import java.util.Set; -import java.util.logging.Logger; -import org.waveprotocol.box.stat.Timing; -import org.waveprotocol.box.webclient.stat.SingleThreadedRequestScope; -import org.waveprotocol.box.webclient.stat.gwtevent.GwtStatisticsEventSystem; -import org.waveprotocol.box.webclient.stat.gwtevent.GwtStatisticsHandler; - -/** - * Entry point classes define <code>onModuleLoad()</code>. - */ -public class WebClient implements EntryPoint { - interface Binder extends UiBinder<DockLayoutPanel, WebClient> { - } - - interface Style extends CssResource { - } - - private static final Binder BINDER = GWT.create(Binder.class); - - private static final WebClientMessages messages = GWT.create(WebClientMessages.class); - - static Log LOG = Log.get(WebClient.class); - // Use of GWT logging is only intended for sending exception reports to the - // server, nothing else in the client should use java.util.logging. - // Please also see WebClientDemo.gwt.xml. - private static final Logger REMOTE_LOG = Logger.getLogger("REMOTE_LOG"); - - private static final String DEFAULT_LOCALE = "default"; - - /** Creates a popup that warns about network disconnects. */ - private static UniversalPopup createTurbulencePopup() { - PopupChrome chrome = PopupChromeFactory.createPopupChrome(); - UniversalPopup popup = - PopupFactory.createPopup(null, new CenterPopupPositioner(), chrome, true); - popup.add(new HTML("<div style='color: red; padding: 5px; text-align: center;'>" - + "<b>" + messages.turbulenceDetected() + "<br></br> " - + messages.saveAndReloadWave() + "</b></div>")); - return popup; - } - - private final ProfileManager profiles = new RemoteProfileManagerImpl(); - private final UniversalPopup turbulencePopup = createTurbulencePopup(); - - @UiField - SplitLayoutPanel splitPanel; - - @UiField - Style style; - - @UiField - FramedPanel waveFrame; - - @UiField - ImplPanel waveHolder; - private final Element loading = new LoadingIndicator().getElement(); - - @UiField(provided = true) - final SearchPanelWidget searchPanel = new SearchPanelWidget(new SearchPanelRenderer(profiles)); - - @UiField - DebugMessagePanel logPanel; - - /** The wave panel, if a wave is open. */ - private StagesProvider wave; - - private final WaveStore waveStore = new SimpleWaveStore(); - - /** - * Create a remote websocket to talk to the server-side FedOne service. - */ - private WaveWebSocketClient websocket; - - private ParticipantId loggedInUser; - - private IdGenerator idGenerator; - - private RemoteViewServiceMultiplexer channel; - - private LocaleService localeService = new RemoteLocaleService(); - - /** - * This is the entry point method. - */ - @Override - public void onModuleLoad() { - - ErrorHandler.install(); - - ClientEvents.get().addWaveCreationEventHandler( - new WaveCreationEventHandler() { - - @Override - public void onCreateRequest(WaveCreationEvent event, Set<ParticipantId> participantSet) { - LOG.info("WaveCreationEvent received"); - if (channel == null) { - throw new RuntimeException("Spaghetti attack. Create occured before login"); - } - openWave(WaveRef.of(idGenerator.newWaveId()), true, participantSet); - } - }); - - setupLocaleSelect(); - setupConnectionIndicator(); - - HistorySupport.init(new HistoryProviderDefault()); - HistoryChangeListener.init(); - - websocket = new WaveWebSocketClient(websocketNotAvailable(), getWebSocketBaseUrl()); - websocket.connect(); - - if (Session.get().isLoggedIn()) { - loggedInUser = new ParticipantId(Session.get().getAddress()); - idGenerator = ClientIdGenerator.create(); - loginToServer(); - } - - setupUi(); - setupStatistics(); - - History.fireCurrentHistoryState(); - LOG.info("SimpleWebClient.onModuleLoad() done"); - } - - private void setupUi() { - // Set up UI - DockLayoutPanel self = BINDER.createAndBindUi(this); - RootPanel.get("app").add(self); - // DockLayoutPanel forcibly conflicts with sensible layout control, and - // sticks inline styles on elements without permission. They must be - // cleared. - self.getElement().getStyle().clearPosition(); - splitPanel.setWidgetMinSize(searchPanel, 300); - AttachmentManagerProvider.init(AttachmentManagerImpl.getInstance()); - - if (LogLevel.showDebug()) { - logPanel.enable(); - } else { - logPanel.removeFromParent(); - } - - setupSearchPanel(); - setupWavePanel(); - - FocusManager.init(); - } - - private void setupSearchPanel() { - // On wave action fire an event. - SearchPresenter.WaveActionHandler actionHandler = - new SearchPresenter.WaveActionHandler() { - @Override - public void onCreateWave() { - ClientEvents.get().fireEvent(new WaveCreationEvent()); - } - - @Override - public void onWaveSelected(WaveId id) { - ClientEvents.get().fireEvent(new WaveSelectionEvent(WaveRef.of(id))); - } - }; - Search search = SimpleSearch.create(RemoteSearchService.create(), waveStore); - SearchPresenter.create(search, searchPanel, actionHandler, profiles); - } - - private void setupWavePanel() { - // Hide the frame until waves start getting opened. - UIObject.setVisible(waveFrame.getElement(), false); - - Document.get().getElementById("signout").setInnerText(messages.signout()); - - // Handles opening waves. - ClientEvents.get().addWaveSelectionEventHandler(new WaveSelectionEventHandler() { - @Override - public void onSelection(WaveRef waveRef) { - openWave(waveRef, false, null); - } - }); - } - - private void setupLocaleSelect() { - final SelectElement select = (SelectElement) Document.get().getElementById("lang"); - String currentLocale = LocaleInfo.getCurrentLocale().getLocaleName(); - String[] localeNames = LocaleInfo.getAvailableLocaleNames(); - for (String locale : localeNames) { - if (!DEFAULT_LOCALE.equals(locale)) { - String displayName = LocaleInfo.getLocaleNativeDisplayName(locale); - OptionElement option = Document.get().createOptionElement(); - option.setValue(locale); - option.setText(displayName); - select.add(option, null); - if (locale.equals(currentLocale)) { - select.setSelectedIndex(select.getLength() - 1); - } - } - } - EventDispatcherPanel.of(select).registerChangeHandler(null, new WaveChangeHandler() { - - @Override - public boolean onChange(ChangeEvent event, Element context) { - UrlBuilder builder = Location.createUrlBuilder().setParameter( - "locale", select.getValue()); - Window.Location.replace(builder.buildString()); - localeService.storeLocale(select.getValue()); - return true; - } - }); - } - - private void setupConnectionIndicator() { - ClientEvents.get().addNetworkStatusEventHandler(new NetworkStatusEventHandler() { - - boolean isTurbulenceDetected = false; - - @Override - public void onNetworkStatus(NetworkStatusEvent event) { - Element element = Document.get().getElementById("netstatus"); - if (element != null) { - switch (event.getStatus()) { - case CONNECTED: - case RECONNECTED: - element.setInnerText(messages.online()); - element.setClassName("online"); - isTurbulenceDetected = false; - turbulencePopup.hide(); - break; - case DISCONNECTED: - element.setInnerText(messages.offline()); - element.setClassName("offline"); - if (!isTurbulenceDetected) { - isTurbulenceDetected = true; - turbulencePopup.show(); - } - break; - case RECONNECTING: - element.setInnerText(messages.connecting()); - element.setClassName("connecting"); - break; - } - } - } - }); - } - - private void setupStatistics() { - Timing.setScope(new SingleThreadedRequestScope()); - Timing.setEnabled(true); - GwtStatisticsEventSystem eventSystem = new GwtStatisticsEventSystem(); - eventSystem.addListener(new GwtStatisticsHandler(), true); - eventSystem.enable(true); - } - - /** - * Returns <code>ws(s)://yourhost[:port]/</code>. - */ - // XXX check formatting wrt GPE - private native String getWebSocketBaseUrl() /*-{return ((window.location.protocol == "https:") ? "wss" : "ws") + "://" + $wnd.__websocket_address + "/";}-*/; - - private native boolean websocketNotAvailable() /*-{ return !window.WebSocket }-*/; - - /** - */ - private void loginToServer() { - assert loggedInUser != null; - channel = new RemoteViewServiceMultiplexer(websocket, loggedInUser.getAddress()); - } - - /** - * Shows a wave in a wave panel. - * - * @param waveRef wave id to open - * @param isNewWave whether the wave is being created by this client session. - * @param participants the participants to add to the newly created wave. - * {@code null} if only the creator should be added - */ - private void openWave(WaveRef waveRef, boolean isNewWave, Set<ParticipantId> participants) { - final org.waveprotocol.box.stat.Timer timer = Timing.startRequest("Open Wave"); - LOG.info("WebClient.openWave()"); - - if (wave != null) { - wave.destroy(); - wave = null; - } - - // Release the display:none. - UIObject.setVisible(waveFrame.getElement(), true); - waveHolder.getElement().appendChild(loading); - Element holder = waveHolder.getElement().appendChild(Document.get().createDivElement()); - Element unsavedIndicator = Document.get().getElementById("unsavedStateContainer"); - StagesProvider wave = - new StagesProvider(holder, unsavedIndicator, waveHolder, waveFrame, waveRef, channel, idGenerator, - profiles, waveStore, isNewWave, Session.get().getDomain(), participants); - this.wave = wave; - wave.load(new Command() { - @Override - public void execute() { - loading.removeFromParent(); - Timing.stop(timer); - } - }); - String encodedToken = History.getToken(); - if (encodedToken != null && !encodedToken.isEmpty()) { - WaveRef fromWaveRef; - try { - fromWaveRef = GwtWaverefEncoder.decodeWaveRefFromPath(encodedToken); - } catch (InvalidWaveRefException e) { - LOG.info("History token contains invalid path: " + encodedToken); - return; - } - if (fromWaveRef.getWaveId().equals(waveRef.getWaveId())) { - // History change was caused by clicking on a link, it's already - // updated by browser. - return; - } - } - History.newItem(GwtWaverefEncoder.encodeToUriPathSegment(waveRef), false); - } - - /** - * An exception handler that reports exceptions using a <em>shiny banner</em> - * (an alert placed on the top of the screen). Once the stack trace is - * prepared, it is revealed in the banner via a link. - */ - static class ErrorHandler implements UncaughtExceptionHandler { - /** Next handler in the handler chain. */ - private final UncaughtExceptionHandler next; - - /** - * Indicates whether an error has already been reported (at most one error - * is ever reported by this handler). - */ - private boolean hasFired; - - private ErrorHandler(UncaughtExceptionHandler next) { - this.next = next; - } - - public static void install() { - GWT.setUncaughtExceptionHandler(new ErrorHandler(GWT.getUncaughtExceptionHandler())); - } - - @Override - public void onUncaughtException(Throwable e) { - if (!hasFired) { - hasFired = true; - final ErrorIndicatorPresenter error = - ErrorIndicatorPresenter.create(RootPanel.get("banner")); - getStackTraceAsync(e, new Accessor<SafeHtml>() { - @Override - public void use(SafeHtml stack) { - error.addDetail(stack, null); - REMOTE_LOG.severe(stack.asString().replace("<br>", "\n")); - } - }); - } - - if (next != null) { - next.onUncaughtException(e); - } - } - - private void getStackTraceAsync(final Throwable t, final Accessor<SafeHtml> whenReady) { - // TODO: Request stack-trace de-obfuscation. For now, just use the - // javascript stack trace. - // - // Use minimal services here, in order to avoid the chance that reporting - // the error produces more errors. In particular, do not use WIAB's - // scheduler to run this command. - // Also, this code could potentially be put behind a runAsync boundary, to - // save whatever dependencies it uses from the initial download. - new Timer() { - @Override - public void run() { - SafeHtmlBuilder stack = new SafeHtmlBuilder(); - - Throwable error = t; - while (error != null) { - String token = String.valueOf((new Date()).getTime()); - stack.appendHtmlConstant("Token: " + token + "<br> "); - stack.appendEscaped(String.valueOf(error.getMessage())).appendHtmlConstant("<br>"); - for (StackTraceElement elt : error.getStackTrace()) { - stack.appendHtmlConstant(" ") - .appendEscaped(maybe(elt.getClassName(), "??")).appendHtmlConstant(".") // - .appendEscaped(maybe(elt.getMethodName(), "??")).appendHtmlConstant(" (") // - .appendEscaped(maybe(elt.getFileName(), "??")).appendHtmlConstant(":") // - .appendEscaped(maybe(elt.getLineNumber(), "??")).appendHtmlConstant(")") // - .appendHtmlConstant("<br>"); - } - error = error.getCause(); - if (error != null) { - stack.appendHtmlConstant("Caused by: "); - } - } - - whenReady.use(stack.toSafeHtml()); - } - }.schedule(1); - } - - private static String maybe(String value, String otherwise) { - return value != null ? value : otherwise; - } - - private static String maybe(int value, String otherwise) { - return value != -1 ? String.valueOf(value) : otherwise; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/WindowTitleHandler.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/WindowTitleHandler.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/WindowTitleHandler.java deleted file mode 100644 index f3b7bba..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/WindowTitleHandler.java +++ /dev/null @@ -1,76 +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.webclient.client; - -import com.google.gwt.user.client.Window; - -import org.waveprotocol.box.webclient.search.WaveStore; -import org.waveprotocol.box.webclient.widget.frame.FramedPanel; -import org.waveprotocol.wave.model.conversation.TitleHelper; -import org.waveprotocol.wave.model.document.WaveContext; - -/** - * Sets the browser window title to the wave title. - * - * @author yur...@apache.org (Yuri Zelikov) - */ -public final class WindowTitleHandler implements WaveStore.Listener { - - private static final String APP_NAME = "WIAB"; - - private static final String DEFAULT_TITLE = "Communicate and collaborate in real-time"; - - private final WaveStore waveStore; - private final FramedPanel waveFrame; - - public static WindowTitleHandler install(WaveStore waveStore, FramedPanel waveFrame) { - return new WindowTitleHandler(waveStore, waveFrame); - } - - private WindowTitleHandler(WaveStore waveStore, FramedPanel waveFrame) { - this.waveStore = waveStore; - this.waveFrame = waveFrame; - init(); - } - - private void init() { - waveStore.addListener(this); - } - - @Override - public void onOpened(WaveContext wave) { - String waveTitle = TitleHelper.getTitle(wave); - String windowTitle = formatTitle(waveTitle); - if (waveTitle == null || waveTitle.isEmpty()) { - windowTitle = DEFAULT_TITLE; - } - Window.setTitle(windowTitle); - waveFrame.setTitleText(waveTitle); - } - - @Override - public void onClosed(WaveContext wave) { - Window.setTitle(DEFAULT_TITLE); - } - - private String formatTitle(String title) { - return title + " - " + Session.get().getAddress() + " - " + APP_NAME; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnection.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnection.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnection.java deleted file mode 100644 index 29b1f24..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnection.java +++ /dev/null @@ -1,53 +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.webclient.client.atmosphere; - -/** - * The atmosphere connection interface for wrapping the javascript - * client in GWT - * - * @author pablo...@gmail.com (Pablo Ojanguren) - * - */ -public interface AtmosphereConnection { - - - /** - * Initiate a connection attempt. - * - */ - void connect(); - - /** - * Initiate an orderly close of the connection. - * - */ - void close(); - - - /** - * Send a message. - * - * @param message - */ - void sendMessage(String message); - - -} \ 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/webclient/client/atmosphere/AtmosphereConnectionImpl.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionImpl.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionImpl.java deleted file mode 100644 index c405f18..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionImpl.java +++ /dev/null @@ -1,232 +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.webclient.client.atmosphere; - -import com.google.gwt.core.client.Callback; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.ScriptInjector; - -/** - * The wrapper implementation of the atmosphere javascript client. - * - * https://github.com/Atmosphere/atmosphere/wiki/jQuery.atmosphere.js-atmosphere - * .js-API - * - * More info about transports - * https://github.com/Atmosphere/atmosphere/wiki/Supported - * -WebServers-and-Browsers - * - * It tries to use Server-Sent Events first and fallback transport to - * long-polling. We ignore Websockets by now because they are the default - * transport on WiAB and atmosphere is the fallback. - * - * http://stackoverflow.com/questions/9397528/server-sent-events-vs-polling - * - * - * @author pablo...@gmail.com (Pablo Ojanguren) - * - */ -public class AtmosphereConnectionImpl implements AtmosphereConnection { - - - private static final class AtmosphereSocket extends JavaScriptObject { - public static native AtmosphereSocket create(AtmosphereConnectionImpl impl, String urlBase) /*-{ - - var client = $wnd.atmosphere; - - var atsocket = { - request: null, - socket: null }; - - var connectionUrl = window.location.protocol + "//" + $wnd.__websocket_address + "/"; - - connectionUrl += 'atmosphere'; - - //console.log("Connection URL is "+urlBase); - atsocket.request = new client.AtmosphereRequest(); - atsocket.request.url = connectionUrl; - atsocket.request.contenType = 'text/plain;charset=UTF-8'; - atsocket.request.transport = 'sse'; - atsocket.request.fallbackTransport = 'long-polling'; - - atsocket.request.onOpen = $entry(function() { - im...@org.waveprotocol.box.webclient.client.atmosphere.AtmosphereConnectionImpl::onConnect()(); - }); - - atsocket.request.onMessage = $entry(function(response) { - - var r = response.responseBody; - - if (r.indexOf('|') == 0) { - - while (r.indexOf('|') == 0 && r.length > 1) { - - r = r.substring(1); - var marker = r.indexOf('}|'); - im...@org.waveprotocol.box.webclient.client.atmosphere.AtmosphereConnectionImpl::onMessage(Ljava/lang/String;)(r.substring(0, marker+1)); - r = r.substring(marker+1); - - } - - } - else { - - im...@org.waveprotocol.box.webclient.client.atmosphere.AtmosphereConnectionImpl::onMessage(Ljava/lang/String;)(r); - - } - - }); - - atsocket.request.onClose = $entry(function(response) { - - client.util.info("Connection closed"); - - im...@org.waveprotocol.box.webclient.client.atmosphere.AtmosphereConnectionImpl::onDisconnect(Ljava/lang/String;)(response); - }); - - - - atsocket.request.onTransportFailure = function(errorMsg, request) { - - client.util.info(errorMsg); - - }; - - - atsocket.request.onReconnect = function(request, response) { - - client.util.info("Reconnected to the server"); - - }; - - atsocket.request.onError = function(response) { - - client.util.info("Unexpected Error"); - - }; - - - return atsocket; - - - }-*/; - - protected AtmosphereSocket() { - } - - - public native void close() /*-{ - this.socket.unsubscribe(); - }-*/; - - public native AtmosphereSocket connect() /*-{ - this.socket = $wnd.atmosphere.subscribe(this.request); - - }-*/; - - public native void send(String data) /*-{ - this.socket.push(data); - }-*/; - } - - - private final AtmosphereConnectionListener listener; - private String urlBase; - private AtmosphereConnectionState state; - private AtmosphereSocket socket = null; - - public AtmosphereConnectionImpl(AtmosphereConnectionListener listener, - String urlBase) { - this.listener = listener; - this.urlBase = urlBase; - - } - - - @Override - public void connect() { - if (socket == null) { - - ScriptInjector.fromUrl("/atmosphere/atmosphere.js").setCallback( - new Callback<Void, Exception>() { - public void onFailure(Exception reason) { - throw new IllegalStateException("atmosphere.js load failed!"); - } - public void onSuccess(Void result) { - - socket = AtmosphereSocket.create(AtmosphereConnectionImpl.this, urlBase); - socket.connect(); - } - }).setWindow(ScriptInjector.TOP_WINDOW).inject(); - } else { - - - if (AtmosphereConnectionState.CLOSED.equals(this.state)) - socket.connect(); - - } - } - - @Override - public void close() { - if (!AtmosphereConnectionState.CLOSED.equals(this.state)) - socket.close(); - - } - - - @Override - public void sendMessage(String message) { - this.state = AtmosphereConnectionState.MESSAGE_PUBLISHED; - socket.send(message); - } - - - - @SuppressWarnings("unused") - private void onConnect() { - this.state = AtmosphereConnectionState.OPENED; - listener.onConnect(); - } - - /** - * This method is called when an Atmosphere onClose event happens: - * - * when an error occurs. when the server or a proxy closes the connection. - * when an expected exception occurs. when the specified transport is not - * supported or fail to connect. - * - * @param response - * - */ - @SuppressWarnings("unused") - private void onDisconnect(String response) { - this.state = AtmosphereConnectionState.CLOSED; - listener.onDisconnect(); - } - - @SuppressWarnings("unused") - private void onMessage(String message) { - this.state = AtmosphereConnectionState.MESSAGE_RECEIVED; - listener.onMessage(message); - } - - -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionListener.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionListener.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionListener.java deleted file mode 100644 index aff7bfd..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionListener.java +++ /dev/null @@ -1,48 +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.webclient.client.atmosphere; - -/** - * The listener interface for the atmosphere client wrapper. - * - * @author pablo...@gmail.com (Pablo Ojanguren) - * - */ -public interface AtmosphereConnectionListener { - - /** - * Called when a successful connection with server is performed - */ - void onConnect(); - - /** - * Called when connection is closed properly or by error - */ - void onDisconnect(); - - /** - * Called when a new message is received from the server - * @param message - */ - void onMessage(String message); - - - -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionState.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionState.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionState.java deleted file mode 100644 index a6b3c94..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/atmosphere/AtmosphereConnectionState.java +++ /dev/null @@ -1,53 +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.webclient.client.atmosphere; - -/** - * Connection state definition inspired by former SocketIO/WebSocket - * implementation - * - * @author pablo...@gmail.com (Pablo Ojanguren) - * - */ -public enum AtmosphereConnectionState { - - MESSAGE_RECEIVED("messageReceived"), - MESSAGE_PUBLISHED("messagePublished"), OPENED("opened"), - CLOSED("closed"), UNKNOWN("unknown"); - - private String value; - private AtmosphereConnectionState(String v) { this.value = v; } - public String value() { return value; } - - public static AtmosphereConnectionState fromString(String val) { - - if (val.equals("messageReceived")) { - return MESSAGE_RECEIVED; - } else if (val.equals("messagePublished")) { - return MESSAGE_PUBLISHED; - } else if (val.equals("opened")) { - return OPENED; - } else if (val.equals("closed")) { - return CLOSED; - } - - return UNKNOWN; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SavedStateMessages.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SavedStateMessages.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SavedStateMessages.java deleted file mode 100644 index 1409154..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SavedStateMessages.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.webclient.client.i18n; - -import com.google.gwt.i18n.client.Messages; -import com.google.gwt.i18n.client.Messages.DefaultMessage; - -/** - * - * @author akaplanov (Andrew Kaplanov) - */ -public interface SavedStateMessages extends Messages { - @DefaultMessage("Saved") - String saved(); - - @DefaultMessage("Unsaved...") - String unsaved(); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SessionMessages.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SessionMessages.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SessionMessages.java deleted file mode 100644 index 5e1a16b..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/SessionMessages.java +++ /dev/null @@ -1,31 +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.webclient.client.i18n; - -import com.google.gwt.i18n.client.Messages; -import com.google.gwt.i18n.client.Messages.DefaultMessage; - -/** - * - * @author akaplanov (Andrew Kaplanov) - */ -public interface SessionMessages extends Messages { - @DefaultMessage("Warning: Session data not available.") - String sessionDataNotAvailable(); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/WebClientMessages.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/WebClientMessages.java b/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/WebClientMessages.java deleted file mode 100644 index 28f3741..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/client/i18n/WebClientMessages.java +++ /dev/null @@ -1,47 +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.webclient.client.i18n; - -import com.google.gwt.i18n.client.Messages; -import com.google.gwt.i18n.client.Messages.DefaultMessage; - -/** - * - * @author akaplanov (Andrew Kaplanov) - */ -public interface WebClientMessages extends Messages { - @DefaultMessage("A turbulence detected!") - String turbulenceDetected(); - - @DefaultMessage("Please save your last changes to somewhere and reload the wave.") - String saveAndReloadWave(); - - @DefaultMessage("Online") - String online(); - - @DefaultMessage("Offline") - String offline(); - - @DefaultMessage("Connecting...") - String connecting(); - - @DefaultMessage("Sign out") - String signout(); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/SnapshotSerializer.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/SnapshotSerializer.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/SnapshotSerializer.java deleted file mode 100644 index 71db08b..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/SnapshotSerializer.java +++ /dev/null @@ -1,196 +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.webclient.common; - -import org.waveprotocol.box.common.comms.DocumentSnapshot; -import org.waveprotocol.box.common.comms.WaveViewSnapshot; -import org.waveprotocol.box.common.comms.WaveletSnapshot; -import org.waveprotocol.box.common.comms.jso.DocumentSnapshotJsoImpl; -import org.waveprotocol.box.common.comms.jso.WaveletSnapshotJsoImpl; -import org.waveprotocol.wave.model.document.operation.DocInitialization; -import org.waveprotocol.wave.model.document.operation.DocOp; -import org.waveprotocol.wave.model.document.operation.impl.DocOpUtil; -import org.waveprotocol.wave.model.id.InvalidIdException; -import org.waveprotocol.wave.model.id.ModernIdSerialiser; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; -import org.waveprotocol.wave.model.operation.OperationException; -import org.waveprotocol.wave.model.util.CollectionUtils; -import org.waveprotocol.wave.model.version.HashedVersion; -import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; -import org.waveprotocol.wave.model.wave.ParticipantId; -import org.waveprotocol.wave.model.wave.data.DocumentFactory; -import org.waveprotocol.wave.model.wave.data.ObservableWaveletData; -import org.waveprotocol.wave.model.wave.data.ReadableBlipData; -import org.waveprotocol.wave.model.wave.data.ReadableWaveletData; -import org.waveprotocol.wave.model.wave.data.WaveViewData; -import org.waveprotocol.wave.model.wave.data.WaveletData; -import org.waveprotocol.wave.model.wave.data.impl.EmptyWaveletSnapshot; -import org.waveprotocol.wave.model.wave.data.impl.WaveViewDataImpl; -import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl; - -import java.util.Collection; - - -/** - * Utility class for serialising/deserialising model objects (and their - * components) to/from their protocol buffer representations. - * - * NOTE: This class is mirrored in the server. Any changes here should also be - * made in - * {@link org.waveprotocol.box.server.common.SnapshotSerializer} - * - * @author Joseph Gentle (jose...@gmail.com) - */ -public class SnapshotSerializer { - private SnapshotSerializer() { - } - - /** - * Serializes a snapshot for a wavelet. - * - * @param wavelet wavelet to snapshot - * @param hashedVersion hashed version of the wavelet - * @return a wavelet snapshot that contains all the information in the - * original wavelet. - */ - public static WaveletSnapshot serializeWavelet(ReadableWaveletData wavelet, - HashedVersion hashedVersion) { - WaveletSnapshot builder = WaveletSnapshotJsoImpl.create(); - - builder.setWaveletId(ModernIdSerialiser.INSTANCE.serialiseWaveletId(wavelet.getWaveletId())); - for (ParticipantId participant : wavelet.getParticipants()) { - builder.addParticipantId(participant.toString()); - } - for (String id : wavelet.getDocumentIds()) { - ReadableBlipData data = wavelet.getDocument(id); - builder.addDocument(serializeDocument(data)); - } - - builder.setVersion(WaveletOperationSerializer.serialize(hashedVersion)); - builder.setLastModifiedTime(wavelet.getLastModifiedTime()); - builder.setCreator(wavelet.getCreator().getAddress()); - builder.setCreationTime(wavelet.getCreationTime()); - - return builder; - } - - /** - * Deserializes the snapshot contained in the {@link WaveletSnapshot} - * into a {@link WaveletData}. - * - * @param snapshot the {@link WaveletSnapshot} to deserialize. - * @throws OperationException if the ops in the snapshot can not be applied. - * @throws InvalidParticipantAddress - * @throws InvalidIdException - */ - public static ObservableWaveletData deserializeWavelet(WaveletSnapshot snapshot, WaveId waveId, - DocumentFactory<?> docFactory) throws OperationException, InvalidParticipantAddress, - InvalidIdException { - ObservableWaveletData.Factory<? extends ObservableWaveletData> factory - = WaveletDataImpl.Factory.create(docFactory); - - ParticipantId author = ParticipantId.of(snapshot.getCreator()); - WaveletId waveletId = - ModernIdSerialiser.INSTANCE.deserialiseWaveletId(snapshot.getWaveletId()); - long creationTime = snapshot.getCreationTime(); - - ObservableWaveletData wavelet = factory.create(new EmptyWaveletSnapshot(waveId, waveletId, - author, WaveletOperationSerializer.deserialize(snapshot.getVersion()), - creationTime)); - - for (String participant : snapshot.getParticipantId()) { - wavelet.addParticipant(ParticipantId.of(participant)); - } - - for (DocumentSnapshot document : snapshot.getDocument()) { - addDocumentSnapshotToWavelet(document, wavelet); - } - - wavelet.setVersion((long) snapshot.getVersion().getVersion()); - wavelet.setLastModifiedTime(snapshot.getLastModifiedTime()); - // The creator and creation time are set when the empty wavelet template is - // created above. - - return wavelet; - } - - /** - * Serializes a document to a document snapshot. - * - * @param document The document to serialize - * @return A snapshot of the given document - */ - public static DocumentSnapshot serializeDocument(ReadableBlipData document) { - DocumentSnapshot builder = DocumentSnapshotJsoImpl.create(); - - builder.setDocumentId(document.getId()); - builder.setDocumentOperation(WaveletOperationSerializer.serialize( - document.getContent().asOperation())); - - builder.setAuthor(document.getAuthor().getAddress()); - for (ParticipantId participant : document.getContributors()) { - builder.addContributor(participant.getAddress()); - } - builder.setLastModifiedVersion(document.getLastModifiedVersion()); - builder.setLastModifiedTime(document.getLastModifiedTime()); - - return builder; - } - - private static void addDocumentSnapshotToWavelet( - DocumentSnapshot snapshot, WaveletData container) throws InvalidParticipantAddress { - DocOp op = WaveletOperationSerializer.deserialize(snapshot.getDocumentOperation()); - DocInitialization docInit = DocOpUtil.asInitialization(op); - - Collection<ParticipantId> contributors = CollectionUtils.newArrayList(); - for (String p : snapshot.getContributor()) { - contributors.add(ParticipantId.of(p)); - } - container.createDocument( - snapshot.getDocumentId(), - new ParticipantId(snapshot.getAuthor()), // We trust the server's snapshot - contributors, - docInit, - snapshot.getLastModifiedTime(), - snapshot.getLastModifiedVersion()); - } - - /** - * Deserialize a wave view snapshot into a WaveViewData object - * - * @param snapshot the snapshot to deserialize - * @return the deserialized snapshot - * @throws OperationException - * @throws InvalidParticipantAddress - * @throws InvalidIdException - */ - public static WaveViewData deserializeWave(WaveViewSnapshot snapshot, - DocumentFactory<?> docFactory) throws OperationException, InvalidParticipantAddress, - InvalidIdException { - WaveId waveId = ModernIdSerialiser.INSTANCE.deserialiseWaveId(snapshot.getWaveId()); - Collection<ObservableWaveletData> wavelets = CollectionUtils.newArrayList(); - for (WaveletSnapshot s : snapshot.getWavelet()) { - wavelets.add(deserializeWavelet(s, waveId, docFactory)); - } - - return WaveViewDataImpl.create(waveId, wavelets); - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/WaveletOperationSerializer.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/WaveletOperationSerializer.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/WaveletOperationSerializer.java deleted file mode 100644 index 251aa39..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/WaveletOperationSerializer.java +++ /dev/null @@ -1,416 +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.webclient.common; - -import org.waveprotocol.wave.communication.Blob; -import org.waveprotocol.wave.communication.Codec; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.AnnotationBoundary; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.ElementStart; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.KeyValuePair; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.KeyValueUpdate; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.ReplaceAttributes; -import org.waveprotocol.wave.federation.ProtocolDocumentOperation.Component.UpdateAttributes; -import org.waveprotocol.wave.federation.ProtocolHashedVersion; -import org.waveprotocol.wave.federation.ProtocolWaveletDelta; -import org.waveprotocol.wave.federation.ProtocolWaveletOperation; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.AnnotationBoundaryJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.ElementStartJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.KeyValuePairJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.KeyValueUpdateJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.ReplaceAttributesJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolDocumentOperationJsoImpl.ComponentJsoImpl.UpdateAttributesJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolHashedVersionJsoImpl; -import org.waveprotocol.wave.federation.jso.ProtocolWaveletOperationJsoImpl; -import org.waveprotocol.wave.model.document.operation.AnnotationBoundaryMap; -import org.waveprotocol.wave.model.document.operation.Attributes; -import org.waveprotocol.wave.model.document.operation.AttributesUpdate; -import org.waveprotocol.wave.model.document.operation.DocOp; -import org.waveprotocol.wave.model.document.operation.DocOpCursor; -import org.waveprotocol.wave.model.document.operation.impl.AnnotationBoundaryMapImpl; -import org.waveprotocol.wave.model.document.operation.impl.AttributesImpl; -import org.waveprotocol.wave.model.document.operation.impl.AttributesUpdateImpl; -import org.waveprotocol.wave.model.document.operation.impl.DocOpBuilder; -import org.waveprotocol.wave.model.operation.wave.AddParticipant; -import org.waveprotocol.wave.model.operation.wave.BlipContentOperation; -import org.waveprotocol.wave.model.operation.wave.BlipOperation; -import org.waveprotocol.wave.model.operation.wave.NoOp; -import org.waveprotocol.wave.model.operation.wave.RemoveParticipant; -import org.waveprotocol.wave.model.operation.wave.SubmitBlip; -import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta; -import org.waveprotocol.wave.model.operation.wave.WaveletBlipOperation; -import org.waveprotocol.wave.model.operation.wave.WaveletOperation; -import org.waveprotocol.wave.model.operation.wave.WaveletOperationContext; -import org.waveprotocol.wave.model.version.HashedVersion; -import org.waveprotocol.wave.model.wave.ParticipantId; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Utility class for serializing/deserializing wavelet operations (and their - * components) to/from their protocol buffer representations (and their - * components). - */ -public class WaveletOperationSerializer { - private WaveletOperationSerializer() { - } - - /** - * Serialize a {@link WaveletOperation} as a {@link ProtocolWaveletOperation}. - * - * @param waveletOp wavelet operation to serialize - * @return serialized protocol buffer wavelet operation - */ - public static ProtocolWaveletOperation serialize(WaveletOperation waveletOp) { - ProtocolWaveletOperation protobufOp = ProtocolWaveletOperationJsoImpl.create(); - - if (waveletOp instanceof NoOp) { - protobufOp.setNoOp(true); - } else if (waveletOp instanceof AddParticipant) { - protobufOp.setAddParticipant(((AddParticipant) waveletOp).getParticipantId().getAddress()); - } else if (waveletOp instanceof RemoveParticipant) { - protobufOp.setRemoveParticipant(((RemoveParticipant) waveletOp).getParticipantId() - .getAddress()); - } else if (waveletOp instanceof WaveletBlipOperation) { - ProtocolWaveletOperation.MutateDocument mutation = - ProtocolWaveletOperationJsoImpl.MutateDocumentJsoImpl.create(); - mutation.setDocumentId(((WaveletBlipOperation) waveletOp).getBlipId()); - mutation.setDocumentOperation(serialize(((WaveletBlipOperation) waveletOp).getBlipOp())); - protobufOp.setMutateDocument(mutation); - } else { - throw new IllegalArgumentException("Unsupported operation type: " + waveletOp); - } - - return protobufOp; - } - - - /** - * Serialize a {@link DocOp} as a {@link ProtocolDocumentOperation}. - * - * @param blipOp document operation to serialize - * @return serialized protocol buffer document operation - */ - public static ProtocolDocumentOperation serialize(BlipOperation blipOp) { - ProtocolDocumentOperation output; - - if (blipOp instanceof BlipContentOperation) { - output = serialize(((BlipContentOperation) blipOp).getContentOp()); - } else if (blipOp instanceof SubmitBlip) { - // we don't support this operation here. - output = ProtocolDocumentOperationJsoImpl.create(); - } else { - throw new IllegalArgumentException("Unsupported operation type: " + blipOp); - } - return output; - } - - /** - * Deserializes a {@link ProtocolWaveletDelta} as a - * {@link TransformedWaveletDelta} - * - * @param protocolDelta protocol buffer wavelet delta to deserialize - * @return deserialized wavelet delta and version - */ - public static TransformedWaveletDelta deserialize(final ProtocolWaveletDelta protocolDelta, - HashedVersion postVersion) { - // TODO(anorth): include the application timestamp when it's plumbed - // through correctly. - WaveletOperationContext dummy = new WaveletOperationContext(null, 0L, 0L); - List<WaveletOperation> ops = new ArrayList<WaveletOperation>(); - for (ProtocolWaveletOperation protocolOp : protocolDelta.getOperation()) { - ops.add(deserialize(protocolOp, dummy)); - } - // This involves an unnecessary copy of the ops, but avoids repeating - // error-prone context calculations. - return TransformedWaveletDelta.cloneOperations( - ParticipantId.ofUnsafe(protocolDelta.getAuthor()), postVersion, 0L, ops); - } - - /** - * Deserialize a {@link ProtocolWaveletOperation} as a - * {@link WaveletOperation}. - * - * @param protobufOp protocol buffer wavelet operation to deserialize - * @return deserialized wavelet operation - */ - public static WaveletOperation deserialize(ProtocolWaveletOperation protobufOp, - WaveletOperationContext ctx) { - if (protobufOp.hasNoOp()) { - return new NoOp(ctx); - } else if (protobufOp.hasAddParticipant()) { - return new AddParticipant(ctx, new ParticipantId(protobufOp.getAddParticipant())); - } else if (protobufOp.hasRemoveParticipant()) { - return new RemoveParticipant(ctx, new ParticipantId(protobufOp.getRemoveParticipant())); - } else if (protobufOp.hasMutateDocument()) { - return new WaveletBlipOperation(protobufOp.getMutateDocument().getDocumentId(), - new BlipContentOperation(ctx, deserialize(protobufOp.getMutateDocument() - .getDocumentOperation()))); - } else { - throw new IllegalArgumentException("Unsupported operation: " + protobufOp); - } - } - - /** - * Deserialize a {@link ProtocolDocumentOperation} into a {@link DocOp}. - * - * @param op protocol buffer document operation to deserialize - * @return deserialized DocOp - */ - public static DocOp deserialize(ProtocolDocumentOperation op) { - DocOpBuilder output = new DocOpBuilder(); - - for (ProtocolDocumentOperation.Component c : op.getComponent()) { - if (c.hasAnnotationBoundary()) { - AnnotationBoundary boundary = c.getAnnotationBoundary(); - if (boundary.getEmpty()) { - output.annotationBoundary(AnnotationBoundaryMapImpl.EMPTY_MAP); - } else { - String[] ends = boundary.getEnd().toArray(new String[boundary.getEnd().size()]); - int changes = boundary.getChange().size(); - String[] changeKeys = new String[changes]; - String[] oldValues = new String[changes]; - String[] newValues = new String[changes]; - for (int i = 0; i < changes; i++) { - KeyValueUpdate kvu = boundary.getChange(i); - changeKeys[i] = kvu.getKey(); - oldValues[i] = kvu.hasOldValue() ? kvu.getOldValue() : null; - newValues[i] = kvu.hasNewValue() ? kvu.getNewValue() : null; - } - output.annotationBoundary(new AnnotationBoundaryMapImpl(ends, changeKeys, oldValues, - newValues)); - } - } else if (c.hasCharacters()) { - output.characters(c.getCharacters()); - } else if (c.hasElementStart()) { - output.elementStart(c.getElementStart().getType(), new AttributesImpl(deserialize(c - .getElementStart().getAttribute()))); - } else if (c.hasElementEnd()) { - output.elementEnd(); - } else if (c.hasRetainItemCount()) { - output.retain(c.getRetainItemCount()); - } else if (c.hasDeleteCharacters()) { - output.deleteCharacters(c.getDeleteCharacters()); - } else if (c.hasDeleteElementStart()) { - output.deleteElementStart(c.getDeleteElementStart().getType(), new AttributesImpl( - deserialize(c.getDeleteElementStart().getAttribute()))); - } else if (c.hasDeleteElementEnd()) { - output.deleteElementEnd(); - } else if (c.hasReplaceAttributes()) { - ReplaceAttributes r = c.getReplaceAttributes(); - if (r.getEmpty()) { - output.replaceAttributes(AttributesImpl.EMPTY_MAP, AttributesImpl.EMPTY_MAP); - } else { - output.replaceAttributes(new AttributesImpl(deserialize(r.getOldAttribute())), - new AttributesImpl(deserialize(r.getNewAttribute()))); - } - } else if (c.hasUpdateAttributes()) { - UpdateAttributes u = c.getUpdateAttributes(); - if (u.getEmpty()) { - output.updateAttributes(AttributesUpdateImpl.EMPTY_MAP); - } else { - String[] triplets = new String[u.getAttributeUpdate().size() * 3]; - int i = 0; - for (KeyValueUpdate kvu : u.getAttributeUpdate()) { - triplets[i++] = kvu.getKey(); - triplets[i++] = kvu.hasOldValue() ? kvu.getOldValue() : null; - triplets[i++] = kvu.hasNewValue() ? kvu.getNewValue() : null; - } - output.updateAttributes(new AttributesUpdateImpl(triplets)); - } - } else { - // throw new - // IllegalArgumentException("Unsupported operation component: " + c); - } - } - - return output.build(); - } - - private static Map<String, String> deserialize(Collection<? extends KeyValuePair> pairs) { - if (pairs.isEmpty()) { - return Collections.emptyMap(); - } else { - Map<String, String> map = new HashMap<String, String>(); - for (KeyValuePair pair : pairs) { - map.put(pair.getKey(), pair.getValue()); - } - return map; - } - } - - /** - * Deserializes a {@link ProtocolHashedVersion} to a {@link HashedVersion} - * POJO. - */ - public static HashedVersion deserialize(ProtocolHashedVersion hashedVersion) { - byte[] hash = Codec.decode(hashedVersion.getHistoryHash().getData()); - return HashedVersion.of((long) hashedVersion.getVersion(), hash); - } - - /** - * Serializes a {@link DocOp} as a {@link ProtocolDocumentOperation}. - * - * @param inputOp document operation to serialize - * @return serialized protocol buffer document operation - */ - public static ProtocolDocumentOperation serialize(DocOp inputOp) { - final ProtocolDocumentOperation output = ProtocolDocumentOperationJsoImpl.create(); - inputOp.apply(new DocOpCursor() { - - private Component addComponent() { - ComponentJsoImpl component = ComponentJsoImpl.create(); - output.addComponent(component); - return component; - } - - private KeyValuePair keyValuePair(String key, String value) { - KeyValuePair pair = KeyValuePairJsoImpl.create(); - pair.setKey(key); - pair.setValue(value); - return pair; - } - - private KeyValueUpdate keyValueUpdate(String key, String oldValue, String newValue) { - KeyValueUpdate kvu = KeyValueUpdateJsoImpl.create(); - kvu.setKey(key); - if (oldValue != null) { - kvu.setOldValue(oldValue); - } - if (newValue != null) { - kvu.setNewValue(newValue); - } - return kvu; - } - - @Override - public void retain(int itemCount) { - addComponent().setRetainItemCount(itemCount); - } - - @Override - public void characters(String characters) { - addComponent().setCharacters(characters); - } - - @Override - public void deleteCharacters(String characters) { - addComponent().setDeleteCharacters(characters); - } - - @Override - public void elementStart(String type, Attributes attributes) { - addComponent().setElementStart(makeElementStart(type, attributes)); - } - - @Override - public void deleteElementStart(String type, Attributes attributes) { - addComponent().setDeleteElementStart(makeElementStart(type, attributes)); - } - - private ElementStart makeElementStart(String type, Attributes attributes) { - ElementStart e = ElementStartJsoImpl.create(); - e.setType(type); - for (String name : attributes.keySet()) { - e.addAttribute(keyValuePair(name, attributes.get(name))); - } - return e; - } - - @Override - public void elementEnd() { - addComponent().setElementEnd(true); - } - - @Override - public void deleteElementEnd() { - addComponent().setDeleteElementEnd(true); - } - - @Override - public void replaceAttributes(Attributes oldAttributes, Attributes newAttributes) { - ReplaceAttributes r = ReplaceAttributesJsoImpl.create(); - if (oldAttributes.isEmpty() && newAttributes.isEmpty()) { - r.setEmpty(true); - } else { - for (String name : oldAttributes.keySet()) { - r.addOldAttribute(keyValuePair(name, oldAttributes.get(name))); - } - - for (String name : newAttributes.keySet()) { - r.addNewAttribute(keyValuePair(name, newAttributes.get(name))); - } - } - addComponent().setReplaceAttributes(r); - } - - @Override - public void updateAttributes(AttributesUpdate attributes) { - UpdateAttributes u = UpdateAttributesJsoImpl.create(); - if (attributes.changeSize() == 0) { - u.setEmpty(true); - } else { - for (int i = 0; i < attributes.changeSize(); i++) { - u.addAttributeUpdate(keyValueUpdate(attributes.getChangeKey(i), - attributes.getOldValue(i), attributes.getNewValue(i))); - } - } - addComponent().setUpdateAttributes(u); - } - - @Override - public void annotationBoundary(AnnotationBoundaryMap map) { - AnnotationBoundary a = AnnotationBoundaryJsoImpl.create(); - if (map.endSize() == 0 && map.changeSize() == 0) { - a.setEmpty(true); - } else { - for (int i = 0; i < map.endSize(); i++) { - a.addEnd(map.getEndKey(i)); - } - for (int i = 0; i < map.changeSize(); i++) { - a.addChange( - keyValueUpdate(map.getChangeKey(i), map.getOldValue(i), map.getNewValue(i))); - } - } - addComponent().setAnnotationBoundary(a); - } - }); - return output; - } - - /** - * Serializes a {@link HashedVersion} POJO to a {@link ProtocolHashedVersion}. - */ - public static ProtocolHashedVersion serialize(HashedVersion hashedVersion) { - Blob b64Hash = new Blob(Codec.encode(hashedVersion.getHistoryHash())); - ProtocolHashedVersion version = ProtocolHashedVersionJsoImpl.create(); - version.setVersion(hashedVersion.getVersion()); - version.setHistoryHash(b64Hash); - return version; - } -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/RemoteCallback.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/RemoteCallback.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/RemoteCallback.java deleted file mode 100644 index bf59a14..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/RemoteCallback.java +++ /dev/null @@ -1,33 +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.webclient.common.communication.callback; - -import org.waveprotocol.box.webclient.common.communication.interchange.StatusCode; - - -/** - * Specialisation of SimpleCallback for non-streaming remote calls. The failure - * type is an interchange status code. - * - * @param <R> type of a successful response. - * @author ano...@google.com (Alex North) - */ -public interface RemoteCallback<R> extends SimpleCallback<R, StatusCode> { -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/SimpleCallback.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/SimpleCallback.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/SimpleCallback.java deleted file mode 100644 index ddff787..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/SimpleCallback.java +++ /dev/null @@ -1,46 +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.webclient.common.communication.callback; - -/** - * A callback for a task which may either succeed or fail. - * - * Exactly one of {@link #onSuccess(Object)} or {@link #onFailure(Object)} - * must be invoked exactly once by receivers of a callback. - * - * @param <R> type of a successful response - * @param <F> type of a failure response - * @author ano...@google.com (Alex North) - */ -public interface SimpleCallback<R, F> { - /** - * Called when the task succeeds. - * - * @param response successful response object for this callback - */ - public void onSuccess(R response); - - /** - * Called when the task fails. - * - * @param reason failure reason for this callback - */ - public void onFailure(F reason); -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingCallback.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingCallback.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingCallback.java deleted file mode 100644 index 7529d13..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingCallback.java +++ /dev/null @@ -1,42 +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.webclient.common.communication.callback; - - -/** - * A callback which may be called multiple times with a stream of responses. - * - * {@link #onUpdate(Object)} may be called any number of times before either - * {@link #onSuccess(Object)} or {@link #onFailure(Object)}. - * - * @param <R> type of a successful response - * @param <U> type of an update response - * @param <F> type of a failure response - * @author ano...@google.com (Alex North) - */ -public interface StreamingCallback<R, U, F> extends SimpleCallback<R, F> { - /** - * Called when an update arrives. - * - * @param update update object to return for this callback - */ - public void onUpdate(U update); - -} http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingRemoteCallback.java ---------------------------------------------------------------------- diff --git a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingRemoteCallback.java b/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingRemoteCallback.java deleted file mode 100644 index b416bc4..0000000 --- a/wave/src/main/java/org/waveprotocol/box/webclient/common/communication/callback/StreamingRemoteCallback.java +++ /dev/null @@ -1,35 +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.webclient.common.communication.callback; - -import org.waveprotocol.box.webclient.common.communication.interchange.StatusCode; - - -/** - * Specialisation of StreamingCallback for streaming remote calls. The failure - * type is an interchange status code. - * - * @param <R> type of a successful response - * @param <U> type of an update response - * @author ano...@google.com (Alex North) - */ -public interface StreamingRemoteCallback<R, U> extends StreamingCallback<R, U, StatusCode>, - RemoteCallback<R> { -}