/******************************************************************************* * Copyright (c) 2012 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.context.tasks.ui; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.core.storage.ICommonStorable; import org.eclipse.mylyn.context.core.ContextCore; import org.eclipse.mylyn.context.core.IInteractionContext; import org.eclipse.mylyn.internal.context.ui.ContextUiPlugin; import org.eclipse.mylyn.internal.context.ui.state.ContextStateManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; /** * Manages the persistence for {@link ContextStateManager}. * * @author Steffen Pingel */ public class ContextStatePersistenceHandler { public static final String FILE_NAME = "context-state.xml"; //$NON-NLS-1$ public ContextStatePersistenceHandler() { } public void activated(IInteractionContext context) { if (!isOnUiThread()) { return; } getStateManager().saveDefaultState(); ICommonStorable storable = getStorable(context.getHandleIdentifier()); if (storable != null) { try { InputStream in = null; if (storable.exists(FILE_NAME)) { in = storable.read(FILE_NAME, null); } try { getStateManager().restoreState(context, in); } finally { if (in != null) { in.close(); } } } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( "Unexpected error restoring the context state for {0}", context.getHandleIdentifier()), e)); //$NON-NLS-1$ } finally { storable.release(); } } else { // StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( // "Context restore failed: No corresponding task for {0} found.", context.getHandleIdentifier()))); //$NON-NLS-1$ } } public void clear(ITask task) { if (!isOnUiThread()) { return; } ICommonStorable storable = getStorable(task); try { storable.delete(FILE_NAME); } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( "Unexpected error deleting the context state for {0}", task.getHandleIdentifier()), e)); //$NON-NLS-1$ } finally { storable.release(); } } public void clear(String contextHandle, boolean activeContext) { // bug 255588: use the handle since the context is null when it is cleared getStateManager().clearState(contextHandle, activeContext); } public void copy(ITask sourceTask, ITask targetTask) { if (!isOnUiThread()) { return; } copyState(sourceTask, targetTask, true); } public void deactivated(IInteractionContext context) { if (!isOnUiThread()) { return; } save(context, true); getStateManager().restoreDefaultState(); } public void merge(ITask sourceTask, ITask targetTask) { if (!isOnUiThread()) { return; } copyState(sourceTask, targetTask, false); } public void save(IInteractionContext context) { save(context, false); } public void save(IInteractionContext context, boolean allowModifications) { if (!isOnUiThread()) { return; } ICommonStorable storable = getStorable(context.getHandleIdentifier()); if (storable != null) { try { OutputStream out = storable.write(FILE_NAME, null); try { getStateManager().saveState(context, out, allowModifications); } finally { out.close(); } } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( "Unexpected error saving the context state for {0}", context.getHandleIdentifier()), e)); //$NON-NLS-1$ } finally { storable.release(); } } else { // StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( // "Context save failed: No corresponding task for {0} found.", context.getHandleIdentifier()))); //$NON-NLS-1$ } } public void saved(ITask task) { if (!isOnUiThread()) { return; } IInteractionContext context = ContextCore.getContextManager().getActiveContext(); if (context != null && task.getHandleIdentifier().equals(context.getHandleIdentifier())) { save(context); } } private void copyState(ITask sourceTask, ITask targetTask, boolean overwrite) { ICommonStorable targetStorable = getStorable(targetTask); try { if (overwrite || !targetStorable.exists(FILE_NAME)) { ICommonStorable sourceStorable = getStorable(sourceTask); try { copyStateFile(sourceStorable, targetStorable, FILE_NAME); } finally { sourceStorable.release(); } } } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( "Unexpected error saving the context state for {0}", targetTask.getHandleIdentifier()), e)); //$NON-NLS-1$ } finally { targetStorable.release(); } } private void copyStateFile(ICommonStorable sourceStorable, ICommonStorable targetStorable, String handle) throws CoreException, IOException { BufferedInputStream in = new BufferedInputStream(sourceStorable.read(handle, null)); try { BufferedOutputStream out = new BufferedOutputStream(targetStorable.write(handle, null)); try { byte[] buffer = new byte[4096]; while (true) { int count = in.read(buffer); if (count == -1) { return; } out.write(buffer, 0, count); } } finally { out.close(); } } finally { in.close(); } } private ContextStateManager getStateManager() { return ContextUiPlugin.getDefault().getStateManager(); } private ICommonStorable getStorable(ITask task) { return ((TaskContextStore) TasksUiPlugin.getContextStore()).getStorable(task); } private ICommonStorable getStorable(String contextHandle) { ITask task = TasksUi.getRepositoryModel().getTask(contextHandle); return (task != null) ? getStorable(task) : null; } private boolean isOnUiThread() { return Display.getCurrent() != null; } }