/* * 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; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.nio.channels.FileLock; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IProduct; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.service.datalocation.Location; import org.osgi.framework.BundleContext; import org.xmind.core.Core; import org.xmind.core.internal.security.BouncyCastleSecurityProvider; import org.xmind.core.internal.security.Crypto; import org.xmind.core.util.FileUtils; /** * The activator class controls the plug-in life cycle */ public class XmindCore extends Plugin { // The plug-in ID public static final String PLUGIN_ID = "org.xmind.core.runtime"; //$NON-NLS-1$ // The shared instance private static XmindCore plugin; private String stampFile = null; private FileOutputStream stream = null; private FileLock lock = null; /** * The constructor */ public XmindCore() { } /* * (non-Javadoc) * * @see * org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { super.start(context); plugin = this; InternalCore.getInstance().setLogger(new DefaultLogger()); Core.getWorkspace().setWorkingDirectory(makeWorkspacePath()); createStampFile(); Crypto.setProvider(new BouncyCastleSecurityProvider()); } /* * (non-Javadoc) * * @see * org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { deleteStampFile(); checkTempDir(); plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static XmindCore getDefault() { return plugin; } private String findInstancePath() { Location instanceLocation = Platform.getInstanceLocation(); if (instanceLocation == null) { return getDefaultInstancePath(); } URL url = instanceLocation.getURL(); try { url = FileLocator.toFileURL(url); } catch (IOException e) { } String file = url.getFile(); if (file != null && !"".equals(file)) {//$NON-NLS-1$ return file; } return url.toExternalForm(); } protected String getDefaultInstancePath() { String homeDir = System.getProperty("user.home"); //$NON-NLS-1$ String os = Platform.getOS(); if (Platform.OS_WIN32.equals(os)) { return new File(new File(new File(homeDir, "Application Data"), //$NON-NLS-1$ "XMind"), //$NON-NLS-1$ "workspace-cathy").getAbsolutePath(); //$NON-NLS-1$ } else if (Platform.OS_MACOSX.equals(os)) { return new File(new File(new File(homeDir, "Library"), //$NON-NLS-1$ "XMind"), //$NON-NLS-1$ "workspace-cathy").getAbsolutePath(); //$NON-NLS-1$ } else { return new File(new File(homeDir, ".xmind"), //$NON-NLS-1$ "workspace-cathy").getAbsolutePath(); //$NON-NLS-1$ } } private String makeWorkspacePath() { String workspacePath = findInstancePath(); File oldWorkspaceDir = new File(workspacePath, ".xmind"); //$NON-NLS-1$ if (oldWorkspaceDir.isDirectory()) { return ensureDir(oldWorkspaceDir); } IProduct product = Platform.getProduct(); if (product == null) return ensureDir(oldWorkspaceDir); if ("org.xmind.cathy.application".equals(product.getApplication())) { //$NON-NLS-1$ return workspacePath; } return ensureDir(oldWorkspaceDir); } private String ensureDir(File dir) { dir.mkdirs(); return dir.getAbsolutePath(); } /** * 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' */ private void createStampFile() throws CoreException { stampFile = makeStampFilePath(); if (stampFile == null) throw new CoreException( new Status( IStatus.ERROR, PLUGIN_ID, "Failed to prepare the XMind workspace: unable to create a name for the 'Workspace Stamp File'. Please make sure you have permission to modify files at " //$NON-NLS-1$ + Core.getWorkspace().getTempDir())); File file = new File(stampFile); try { stream = new FileOutputStream(file); } catch (IOException e) { throw new CoreException( new Status( IStatus.ERROR, PLUGIN_ID, "Fail to prepare the XMind workspace: unable to create the 'Workspace Stamp File'. Please make sure you have permission to modify files at " //$NON-NLS-1$ + Core.getWorkspace().getTempDir(), e)); } for (int err = 0; err < 5; err++) { try { lock = stream.getChannel().tryLock(); } catch (IOException e) { } if (lock != null) break; } if (lock == null) { try { stream.close(); } catch (IOException e) { } stream = null; file.delete(); throw new CoreException( new Status( IStatus.ERROR, PLUGIN_ID, "Fail to prepare the XMind workspace: unable to lock the 'Workspace Stamp File'. Please make sure you have permission to modify files at " //$NON-NLS-1$ + Core.getWorkspace().getTempDir())); } } private String makeStampFilePath() { String path = null; for (int error = 0; error < 5; error++) { path = Core.getWorkspace().getTempFile( Long.toHexString(System.currentTimeMillis()) + '_' + Integer.toHexString((int) (Math.random() * 1024)) + ".core"); //$NON-NLS-1$ if (!new File(path).exists()) break; path = null; } return path; } private void deleteStampFile() { if (lock != null) { try { lock.release(); } catch (IOException e) { } lock = null; } if (stream != null) { try { stream.close(); } catch (IOException e) { } stream = null; } if (stampFile != null) { new File(stampFile).delete(); stampFile = null; } } /** * If no other XMind instance is running, clears the temp dir. */ private void checkTempDir() { File dir = new File(Core.getWorkspace().getTempDir()); if (!dir.exists() || !dir.canRead()) return; String[] instanceMarkers = dir.list(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".core"); //$NON-NLS-1$ } }); if (instanceMarkers != null && instanceMarkers.length > 0) { for (String name : instanceMarkers) { File file = new File(dir, name); if (isLocked(file)) return; // another XMind Core is using the temp dir } } deleteTempDir(); } private boolean isLocked(File file) { try { FileOutputStream s = new FileOutputStream(file); try { FileLock l = s.getChannel().tryLock(); if (l == null) return true; try { l.release(); } catch (IOException e2) { } return false; } finally { s.close(); } } catch (FileNotFoundException e) { return false; } catch (IOException e) { return true; } } private void deleteTempDir() { FileUtils.delete(new File(Core.getWorkspace().getTempDir())); } }