/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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 com.google.dart.tools.update.core.internal; import com.google.dart.tools.core.DartCoreDebug; import com.google.dart.tools.update.core.Revision; import com.google.dart.tools.update.core.UpdateCore; import com.google.dart.tools.update.core.UpdateListener; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.SafeRunner; import java.util.concurrent.CopyOnWriteArrayList; /** * Maintains state during the update process. */ public class UpdateModel { /** * State enum. */ public enum State { UNCHECKED { @Override public void notify(UpdateListener listener) { //no-op } }, FAILED { @Override public void notify(UpdateListener listener) { listener.checkFailed(errorMessage); } }, CHECKING { @Override public void notify(UpdateListener listener) { listener.checkStarted(); } }, CHECKED { @Override public void notify(UpdateListener listener) { listener.checkComplete(); } }, AVAILABLE { @Override public void notify(UpdateListener listener) { listener.updateAvailable(latestRevision); } }, DOWNLOADING { @Override public void notify(UpdateListener listener) { listener.downloadStarted(); } }, DOWNLOADED { @Override public void notify(UpdateListener listener) { listener.downloadComplete(); } }, DOWNLOAD_CANCELLED { @Override public void notify(UpdateListener listener) { listener.downloadCancelled(); } }, INSTALLING { @Override public void notify(UpdateListener listener) { listener.installing(); } }, APPLIED { @Override public void notify(UpdateListener listener) { listener.updateApplied(); } }; public abstract void notify(UpdateListener listener); } /** * Dispatches events in a safe runnable to handle any exceptions. */ private abstract class EventNotifier implements ISafeRunnable { @Override public void handleException(Throwable exception) { UpdateCore.logError(exception); } } private State state = State.UNCHECKED; private static Revision latestRevision = Revision.UNKNOWN; private final CopyOnWriteArrayList<UpdateListener> listeners = new CopyOnWriteArrayList<UpdateListener>(); private static String errorMessage; /** * Add the given update listener. * * @param listener the listener to add */ public void addListener(UpdateListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } /** * Cause the model to transition to the given state (and notify listeners). * * @param state the new state */ public void enterState(State state) { if (DartCoreDebug.TRACE_UPDATE) { UpdateCore.logInfo(this.state + "->" + state);//$NON-NLS-1$ } this.state = state; notifyListeners(state); } /** * Checks to see if an update is currently being downloaded. * * @return <code>true</code> if an update is being downloaded, <code>false</code> otherwise */ public boolean isDownloadingUpdate() { return state == State.DOWNLOADING; } /** * Check if the update process is idle (e.g., not downloading or checking for downloads). * * @return <code>true</code> if idle, <code>false</code> otherwise */ public boolean isIdle() { return state != State.DOWNLOADING && state != State.CHECKING; } /** * Checks to see if an update has been applied (implying we need a restart). * * @return <code>true</code> if an update has been applied, <code>false</code> otherwise */ public boolean isUpdateApplied() { return state == State.APPLIED; } /** * Checks to see if an update is available for download. * * @return <code>true</code> if an update is available, <code>false</code> otherwise */ public boolean isUpdateAvailable() { return state == State.AVAILABLE; } /** * Checks to see if an update is downloaded and ready to be applied. * * @return <code>true</code> if an update is ready to be applied, <code>false</code> otherwise */ public boolean isUpdateReadyToBeApplied() { return state == State.DOWNLOADED; } /** * Remove the given update listener. * * @param listener the listener to remove */ public void removeListener(UpdateListener listener) { listeners.remove(listener); } /** * Caches an error message for state notifications. * * @param msg the error message */ void setErrorMessage(String msg) { errorMessage = msg; } /** * Caches a revision number for state notifications. * * @param revision the latest available revision */ void setLatestAvailableRevision(Revision revision) { latestRevision = revision; } /** * Notify listeners of a state change. * * @param newState the new state */ private void notifyListeners(final State newState) { for (final UpdateListener listener : listeners) { SafeRunner.run(new EventNotifier() { @Override public void run() throws Exception { newState.notify(listener); } }); } } }