package org.xmind.ui.blackbox; import java.io.File; import java.io.IOException; import java.security.MessageDigest; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.osgi.framework.Bundle; import org.xmind.core.util.FileUtils; import org.xmind.ui.internal.MindMapUIPlugin; import org.xmind.ui.prefs.PrefConstants; /** * @author Jason Wong */ public class BlackBoxManager { private static BlackBoxManager instance = new BlackBoxManager(); public static final String FILE_BLACKBOX = "blackbox"; //$NON-NLS-1$ public static final String FILE_INFO_EXT = ".xbkinfo"; //$NON-NLS-1$ public static final int MD5_LENGTH = 32; public static final int TIMESTAMP_LENGTH = 13; public static final String FILE_XMIND_EXT = ".xbkmap"; //$NON-NLS-1$ private static final String BREAK = "."; //$NON-NLS-1$ private static List<IBlackBoxVersion> versionTrashes = new ArrayList<IBlackBoxVersion>(); private static List<IBlackBoxMap> mapTrashes = new ArrayList<IBlackBoxMap>(); private static String pluginPath; private static String blackboxPath; private IBlackBoxLibrary library; private BlackBoxManager() { } public static BlackBoxManager getInstance() { return instance; } public static void log(String message, Throwable e) { IStatus status = new Status( e == null ? IStatus.WARNING : IStatus.ERROR, message, BlackBox.ID, e); MindMapUIPlugin.getDefault().getLog().log(status); } public static String getPluginPath() { if (pluginPath != null) return pluginPath; Bundle bundle = MindMapUIPlugin.getDefault().getBundle(); String parentFile = Platform.getStateLocation(bundle).toFile() .getParent(); pluginPath = new File(parentFile, BlackBox.ID).getAbsolutePath(); return pluginPath; } public static String getBlackboxPath() { if (blackboxPath != null && new File(blackboxPath).exists()) return blackboxPath; File blackbox = new File(getPluginPath(), FILE_BLACKBOX); FileUtils.ensureDirectory(blackbox); if (blackbox.exists()) blackboxPath = blackbox.getAbsolutePath(); return blackboxPath; } public static void addTrash(IBlackBoxVersion version) { if (version == null) return; versionTrashes.add(version); } public static void addTrash(IBlackBoxMap map) { if (map == null) return; mapTrashes.add(map); } public static void clearTrashes() { if (mapTrashes.size() > 0) { for (IBlackBoxMap m : mapTrashes) { Set<IBlackBoxVersion> versions = m.getVersions(); for (IBlackBoxVersion v : versions) { if (!versionTrashes.contains(v)) { versionTrashes.add(v); } } File metaFile = new File(getBlackboxPath(), m.getID() + FILE_INFO_EXT); if (metaFile != null && metaFile.exists()) { metaFile.delete(); } } mapTrashes.clear(); } if (versionTrashes.size() > 0) { for (IBlackBoxVersion v : versionTrashes) { File trash = v.getFile(); if (trash != null && trash.exists()) { trash.delete(); } } versionTrashes.clear(); } } public static String convertToMD5(String source) { if (source == null) return null; String plainText = source; try { StringBuffer buf = new StringBuffer(); MessageDigest md = MessageDigest.getInstance("MD5"); //$NON-NLS-1$ md.update(plainText.getBytes()); byte b[] = md.digest(); int i; for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) { i += 256; } if (i < 16) { buf.append("0"); //$NON-NLS-1$ } buf.append(Integer.toHexString(i)); } return buf.toString(); } catch (Exception e) { BlackBoxManager.log("Error occurred while generate map id.", e); //$NON-NLS-1$ return null; } } public void doBackup(String source) { if (!isEnable() || source == null) return; IBlackBoxLibrary library = getLibrary(); IBlackBoxMap map = library.findMapBySource(source); String mapID = map == null ? getMapID(source) : map.getID(); String timestamp = String.valueOf(System.currentTimeMillis()); boolean isReliable = !getLibrary().isSavedMap(source); File dest = null; try { dest = backup(source, mapID, timestamp, isReliable); } catch (IOException e) { BlackBoxManager.log("Error occurred while backup src file.", //$NON-NLS-1$ e); return; } if (dest != null) { BlackBoxVersion version = new BlackBoxVersion(mapID, timestamp, isReliable); version.setFile(dest); library.addVersion(source, mapID, version); } } public IBlackBoxMap[] getMaps() { return getLibrary().getMaps(); } public boolean removeMap(IBlackBoxMap map) { if (map == null) return false; return getLibrary().removeMap(map); } public boolean removeVersion(String source, String timestamp) { return removeVersion(findMapBySource(source), timestamp); } public boolean removeVersion(IBlackBoxMap map, String timestamp) { if (map == null) return false; return getLibrary().removeVersion(map, timestamp); } public IBlackBoxMap findMapBySource(String source) { if (source != null) return getLibrary().findMapBySource(source); return null; } public IBlackBoxMap findMapByID(String id) { if (id != null) return getLibrary().findMapByID(id); return null; } public IBlackBoxLibrary getLibrary() { if (library == null) library = new BlackBoxLibrary(); return library; } public void removeSavedMap(String source) { if (!isEnable() || source == null) return; getLibrary().removeSavedMap(source); } /** * @return dest file. */ private File backup(String source, String mapID, String timestamp, boolean isReliable) throws IOException { File src = new File(source); if (!src.exists() || mapID == null) return null; String destName = getDestName(mapID, timestamp, isReliable); File dest = new File(getDestPath(mapID), destName); if (!dest.exists()) dest.createNewFile(); FileUtils.copy(src, dest); return dest; } private String getDestName(String mapID, String timestamp, boolean isReliable) { if (isReliable) return mapID + BREAK + "a" + BREAK + timestamp + FILE_XMIND_EXT; //$NON-NLS-1$ return mapID + BREAK + "b" + BREAK + timestamp + FILE_XMIND_EXT; //$NON-NLS-1$ } private String getDestPath(String mapID) throws IOException { return getBlackboxPath(); } private String getMapID(String source) { return convertToMD5(source); } private boolean isEnable() { return MindMapUIPlugin.getDefault().getPreferenceStore() .getBoolean(PrefConstants.AUTO_BACKUP_ENABLE); } }