/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.core.internal.runtime; import static org.xmind.core.internal.XmindCore.PLUGIN_ID; import java.io.File; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileLock; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.xmind.core.util.FileUtils; public class WorkspaceSession { private File tempRoot; private File stampFile; private RandomAccessFile stampFileWrapper; private FileLock stampFileLock; public WorkspaceSession(File tempRoot, File stampFile, RandomAccessFile stampFileWrapper, FileLock stampFileLock) { this.tempRoot = tempRoot; this.stampFile = stampFile; this.stampFileWrapper = stampFileWrapper; this.stampFileLock = stampFileLock; } /** * Create a 'Workspace Stamp File' in the temp dir and lock it. * * @throws CoreException * when we fail to the create or lock of the 'Workspace Stamp * File' */ public static WorkspaceSession openSessionIn(File tempRoot) throws CoreException { if (!tempRoot.isDirectory()) { if (!tempRoot.mkdirs()) { throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "Failed to create temporary directory at " //$NON-NLS-1$ + tempRoot.getAbsolutePath())); } } File stampFile; try { stampFile = File.createTempFile("xmind", ".core", tempRoot); //$NON-NLS-1$ //$NON-NLS-2$ } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "Failed to create workspace stamp file in " //$NON-NLS-1$ + tempRoot.getAbsolutePath(), e)); } RandomAccessFile stampFileWrapper; try { stampFileWrapper = new RandomAccessFile(stampFile, "rw"); //$NON-NLS-1$ } catch (FileNotFoundException e) { stampFile.delete(); throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "Failed to find created workspace stamp file at " //$NON-NLS-1$ + stampFile.getAbsolutePath(), e)); } FileLock stampFileLock = null; try { for (int err = 0; err < 10; err++) { try { stampFileLock = stampFileWrapper.getChannel().tryLock(); } catch (IOException e) { } if (stampFileLock != null) break; Thread.sleep(1); } } catch (InterruptedException e) { } if (stampFileLock == null) { try { stampFileWrapper.close(); } catch (IOException e) { } stampFile.delete(); throw new CoreException( new Status( IStatus.ERROR, PLUGIN_ID, "Failed to lock workspace stamp file. Please make sure you have r/w permission at " //$NON-NLS-1$ + tempRoot.getAbsolutePath())); } return new WorkspaceSession(tempRoot, stampFile, stampFileWrapper, stampFileLock); } public void close() { // Release stamp file lock and delete stamp file. deleteStampFile(); // The last session in a temp dir is responsible for clearing the temp dir. if (!hasOtherSession()) { clearTempRoot(); } } private void deleteStampFile() { if (stampFileLock != null) { try { stampFileLock.release(); } catch (IOException e) { } stampFileLock = null; } if (stampFileWrapper != null) { try { stampFileWrapper.close(); } catch (IOException e) { } stampFileWrapper = null; } if (stampFile != null) { stampFile.delete(); stampFile = null; } } private boolean hasOtherSession() { if (!tempRoot.exists()) return false; String[] stampFileNames = tempRoot.list(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".core"); //$NON-NLS-1$ } }); if (stampFileNames != null && stampFileNames.length > 0) { for (int i = 0; i < stampFileNames.length; i++) { File otherStampFile = new File(tempRoot, stampFileNames[i]); if (isLocked(otherStampFile)) return true; } } return false; } private boolean isLocked(File file) { try { RandomAccessFile s = new RandomAccessFile(file, "rw"); //$NON-NLS-1$ try { FileLock l = s.getChannel().tryLock(); if (l == null) return true; try { l.release(); } catch (IOException e2) { } return false; } finally { s.close(); } } catch (IOException e) { return false; } } private void clearTempRoot() { FileUtils.delete(tempRoot); } }