blob: cd453aa58dd010bf85811ea22dc279bd9622e92b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 Mylyn project committers 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
*******************************************************************************/
package org.eclipse.mylyn.internal.context.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipOutputStream;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.context.core.ContextCore;
import org.eclipse.mylyn.context.core.IContextStore;
import org.eclipse.mylyn.context.core.IInteractionContext;
import org.eclipse.mylyn.context.core.IInteractionContextScaling;
/**
* @author Mik Kersten
* @author Steffen Pingel
*/
public class LocalContextStore implements IContextStore {
private File contextDirectory;
private Set<File> contextFiles = null;
private final InteractionContextExternalizer externalizer = new InteractionContextExternalizer();
private final IInteractionContextScaling commonContextScaling;
private final List<IContextStoreListener> listeners = new ArrayList<IContextStoreListener>();
public LocalContextStore(IInteractionContextScaling commonContextScaling) {
this.commonContextScaling = commonContextScaling;
}
public synchronized void setContextDirectory(File directory) {
this.contextDirectory = directory;
for (IContextStoreListener listener : listeners) {
listener.contextStoreMoved(directory);
}
// rootDirectory = new File(TasksUiPlugin.getDefault().getDataDirectory());
// if (!rootDirectory.exists()) {
// rootDirectory.mkdir();
// }
//
// contextDirectory = new File(rootDirectory, ITasksCoreConstants.CONTEXTS_DIRECTORY);
// if (!contextDirectory.exists()) {
// contextDirectory.mkdir();
// }
}
public File getContextDirectory() {
return contextDirectory;
}
/**
* @return false if the map could not be read for any reason
*/
public IInteractionContext loadContext(String handleIdentifier) {
return importContext(handleIdentifier, getFileForContext(handleIdentifier));
}
public IInteractionContext importContext(String handleIdentifier, File file) {
return loadContext(handleIdentifier, file, commonContextScaling);
}
/**
* Creates a file for specified context and activates it
*/
public boolean importContext(IInteractionContext context) {
if (context instanceof InteractionContext) {
externalizer.writeContextToXml(context, getFileForContext(context.getHandleIdentifier()));
return true;
} else {
return false;
}
// contextFiles.add(getFileForContext(context.getHandleIdentifier()));
// activeContext.getContextMap().put(context.getHandleIdentifier(), context);
// if (!activationHistorySuppressed) {
// processActivityMetaContextEvent(new InteractionEvent(InteractionEvent.Kind.COMMAND,
// IInteractionContextManager.ACTIVITY_STRUCTUREKIND_ACTIVATION, context.getHandleIdentifier(),
// IInteractionContextManager.ACTIVITY_ORIGINID_WORKBENCH, null,
// IInteractionContextManager.ACTIVITY_DELTA_ACTIVATED, 1f));
// }
}
public IInteractionContext loadContext(String handleIdentifier, File file, IInteractionContextScaling contextScaling) {
IInteractionContext loadedContext = externalizer.readContextFromXml(handleIdentifier, file, contextScaling);
if (loadedContext == null) {
return new InteractionContext(handleIdentifier, contextScaling);
} else {
return loadedContext;
}
}
/**
* Only saves if active.
*/
public void saveContext(String handleIdentifier) {
// FIXME this should not reference the context manager
IInteractionContext context = ContextCore.getContextManager().getActiveContext();
if (context != null && context.getHandleIdentifier() != null
&& context.getHandleIdentifier().equals(handleIdentifier)) {
saveContext(context);
}
}
public void saveContext(IInteractionContext context, String fileName) {
externalizer.writeContextToXml(context, getFileForContext(fileName));
}
public void saveContext(IInteractionContext context) {
// FIXME this should not reference the context manager
boolean wasPaused = ContextCore.getContextManager().isContextCapturePaused();
try {
// XXX: make this asynchronous by creating a copy
if (!wasPaused) {
// FIXME this should not reference the context manager
ContextCore.getContextManager().setContextCapturePaused(true);
}
if (context instanceof InteractionContext) {
((InteractionContext) context).collapse();
}
externalizer.writeContextToXml(context, getFileForContext(context.getHandleIdentifier()));
if (context.getAllElements().size() == 0) {
removeFromCache(context);
} else {
addToCache(context);
}
} catch (Throwable t) {
StatusHandler.log(new Status(IStatus.ERROR, ContextCorePlugin.PLUGIN_ID, "could not save context", t));
} finally {
if (!wasPaused) {
// FIXME this should not reference the context manager
ContextCore.getContextManager().setContextCapturePaused(false);
}
}
}
private boolean addToCache(IInteractionContext context) {
initCache();
return contextFiles.add(getFileForContext(context.getHandleIdentifier()));
}
private void initCache() {
if (contextFiles == null) {
contextFiles = new HashSet<File>();
File[] files = contextDirectory.listFiles();
for (File file : files) {
contextFiles.add(file);
}
}
}
private boolean removeFromCache(IInteractionContext context) {
if (contextFiles != null) {
return contextFiles.remove(getFileForContext(context.getHandleIdentifier()));
} else {
return false;
}
}
/**
* Consider deleting
*
* @param sourceContextFile
* @param targetcontextHandle
* @return
*/
@Deprecated
public boolean copyContext(File sourceContextFile, String targetcontextHandle) {
if (sourceContextFile.exists()
&& sourceContextFile.getName().endsWith(InteractionContextManager.CONTEXT_FILE_EXTENSION)) {
// FIXME this should not reference the ContextCore
IInteractionContext context = externalizer.readContextFromXml("temp", sourceContextFile,
ContextCore.getCommonContextScaling());
if (context == null) {
return false;
}
}
File targetContextFile = getFileForContext(targetcontextHandle);
targetContextFile.delete();
try {
// FIXME this implementation is broken: it does not refactor the context handle
copy(sourceContextFile, targetContextFile);
contextFiles.add(targetContextFile);
} catch (IOException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextCorePlugin.PLUGIN_ID, "Cold not transfer context: "
+ targetcontextHandle, e));
return false;
}
return true;
}
public IInteractionContext cloneContext(String sourceContextHandle, String destinationContextHandle) {
IInteractionContext context = importContext(destinationContextHandle, getFileForContext(sourceContextHandle));
if (context != null) {
// source.setHandleIdentifier(destinationContextHandle);
saveContext(context);
}
return context;
}
public boolean hasContext(String handleIdentifier) {
Assert.isNotNull(handleIdentifier);
File file = getFileForContext(handleIdentifier);
initCache();
return contextFiles.contains(file);
}
public File getFileForContext(String handleIdentifier) {
String encoded;
try {
encoded = URLEncoder.encode(handleIdentifier, InteractionContextManager.CONTEXT_FILENAME_ENCODING);
File contextDirectory = getContextDirectory();
File contextFile = new File(contextDirectory, encoded + InteractionContextManager.CONTEXT_FILE_EXTENSION);
return contextFile;
} catch (UnsupportedEncodingException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextCorePlugin.PLUGIN_ID,
"Could not determine path for context", e));
}
return null;
}
public void deleteContext(String handleIdentifier) {
try {
File file = getFileForContext(handleIdentifier);
if (file.exists()) {
file.delete();
}
if (contextFiles != null) {
contextFiles.remove(getFileForContext(handleIdentifier));
}
} catch (SecurityException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextCorePlugin.PLUGIN_ID,
"Could not delete context file, insufficient permissions.", e));
}
}
@Deprecated
private void copy(File src, File dest) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dest);
try {
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) == -1) {
out.write(buf, 0, len);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
/**
* Can consider making this API, but it should not expose a zip stream.
*/
public void export(String handleIdentifier, ZipOutputStream outputStream) throws IOException {
IInteractionContext context = loadContext(handleIdentifier);
externalizer.writeContext(context, outputStream);
}
@Deprecated
public void addListener(IContextStoreListener listener) {
listeners.add(listener);
}
@Deprecated
public void removeListener(IContextStoreListener listener) {
listeners.remove(listener);
}
}