blob: 408438496b3bbfbbd357801fd3dd510128d40fdc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2013 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.commons.core.storage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.commons.core.CommonsCorePlugin;
import org.eclipse.osgi.util.NLS;
/**
* @author Steffen Pingel
*/
public class CommonStore {
/**
* Delays writing of mementos to avoid blocking UI thread.
*/
private class FlushJob extends Job {
public FlushJob() {
super("Flush context mementos"); //$NON-NLS-1$
setSystem(true);
setPriority(Job.SHORT);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
flushPending();
return Status.OK_STATUS;
}
}
private static final long FLUSH_DELAY = 500;
private boolean scheduled;
private FlushJob flushJob;
private final Map<File, CommonStorable> storableByLocation;
private File location;
public CommonStore(File location) {
Assert.isNotNull(location);
this.storableByLocation = new HashMap<File, CommonStorable>();
this.location = location;
}
public synchronized ICommonStorable get(IPath path) {
File file = getFile(path);
CommonStorable storable = storableByLocation.get(file);
if (storable == null) {
storable = new CommonStorable(this, file);
storableByLocation.put(file, storable);
}
return storable;
}
public File getLocation() {
return location;
}
public void setLocation(File location) {
Assert.isNotNull(location);
this.location = location;
}
public void stop() {
synchronized (this) {
if (flushJob != null) {
flushJob.cancel();
flushJob = null;
}
}
flushPending();
}
private File getFile(IPath path) {
return getFile(path, true);
}
private File getFile(IPath path, boolean create) {
File file = new File(location, path.toOSString());
if (create && !file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
return file;
}
synchronized void schedule() {
if (!scheduled) {
if (flushJob == null) {
flushJob = new FlushJob();
}
flushJob.schedule(FLUSH_DELAY);
}
}
synchronized void flushPending() {
MultiStatus status = new MultiStatus(CommonsCorePlugin.ID_PLUGIN, 0, "Failed to save storable", null); //$NON-NLS-1$
for (CommonStorable memento : storableByLocation.values()) {
if (memento.isDirty()) {
IStatus result = memento.flush();
status.add(result);
}
}
if (!status.isOK()) {
StatusHandler.log(status);
}
}
synchronized void release(CommonStorable storable) {
storableByLocation.remove(storable.getPath());
}
public void move(IPath oldPath, IPath newPath) throws CoreException {
File oldFile = getFile(oldPath, false);
// TODO lock hierarchy and throw an exception if oldFile is in use
if (oldFile.exists()) {
File newFile = getFile(newPath, false);
newFile.getParentFile().mkdirs();
if (!oldFile.renameTo(newFile)) {
throw new CoreException(new Status(IStatus.ERROR, CommonsCorePlugin.ID_PLUGIN, NLS.bind(
"The target path ''{0}'' already exists", newPath))); //$NON-NLS-1$
}
}
}
}