/** * Aptana Studio * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions). * Please see the license.html included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.syncing.core; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ListenerList; import com.aptana.core.epl.IMemento; import com.aptana.core.epl.XMLMemento; import com.aptana.core.logging.IdeLog; import com.aptana.core.util.StringUtil; import com.aptana.ide.core.io.CoreIOPlugin; import com.aptana.ide.core.io.IConnectionPoint; import com.aptana.ide.core.io.IConnectionPoint15Constants; import com.aptana.ide.core.io.IConnectionPointManager; import com.aptana.ide.syncing.core.events.ISiteConnectionListener; import com.aptana.ide.syncing.core.events.SiteConnectionEvent; /** * @author Max Stepanov */ /* package */final class SiteConnectionManager implements ISiteConnectionManager { protected static final String STATE_FILENAME = "sites"; //$NON-NLS-1$ private static final String ELEMENT_ROOT = "sites"; //$NON-NLS-1$ private static final String ELEMENT_SITE = "site"; //$NON-NLS-1$ private static SiteConnectionManager instance; private List<SiteConnection> connections = Collections.synchronizedList(new ArrayList<SiteConnection>()); private boolean dirty = false; private ListenerList listeners = new ListenerList(); /** * */ private SiteConnectionManager() { } public static SiteConnectionManager getInstance() { if (instance == null) { instance = new SiteConnectionManager(); } return instance; } /** * loadState * * @param path */ /* package */void loadState(IPath path) { File file = path.toFile(); if (file.exists()) { connections.clear(); addConnectionsFrom(path); } } /** * saveState * * @param path */ /* package */void saveState(IPath path) { XMLMemento memento = XMLMemento.createWriteRoot(ELEMENT_ROOT); synchronized (connections) { for (SiteConnection siteConnection : connections) { IMemento child = memento.createChild(ELEMENT_SITE); child.putMemento(storeConnection(siteConnection)); } } FileWriter writer = null; try { writer = new FileWriter(path.toFile()); memento.save(writer); isChanged(); } catch (IOException e) { } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { } } } } public List<ISiteConnection> addConnectionsFrom(IPath path) { List<ISiteConnection> newConnections = readConnectionsFrom(path); for (ISiteConnection connection : newConnections) { connections.add((SiteConnection) connection); } return newConnections; } public List<ISiteConnection> readConnectionsFrom(IPath path) { List<ISiteConnection> newConnections = new ArrayList<ISiteConnection>(); File file = path.toFile(); if (file.exists()) { FileReader reader = null; try { reader = new FileReader(file); XMLMemento memento = XMLMemento.createReadRoot(reader); for (IMemento child : memento.getChildren(ELEMENT_SITE)) { SiteConnection siteConnection = restoreConnection(child); if (siteConnection != null && siteConnection.isValid()) { newConnections.add(siteConnection); } else { IdeLog.logWarning(SyncingPlugin.getDefault(), "Failed to load the site connection due to either source or destination being invalid", //$NON-NLS-1$ IDebugScopes.DEBUG); } } } catch (IOException e) { IdeLog.logError(SyncingPlugin.getDefault(), Messages.SiteConnectionManager_ERR_FailedToLoadConnections, e); } catch (CoreException e) { // could be an 1.5 exported file; try to migrate try { load15State(file); } catch (Exception e1) { IdeLog.logError(SyncingPlugin.getDefault(), Messages.SiteConnectionManager_ERR_FailedToLoadConnections, e1); } } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } } return newConnections; } private IMemento storeConnection(SiteConnection siteConnection) { IMemento saveMemento = XMLMemento.createWriteRoot(ELEMENT_ROOT).createChild(ELEMENT_SITE); siteConnection.saveState(saveMemento); return saveMemento; } private SiteConnection restoreConnection(IMemento memento) { SiteConnection siteConnection = new SiteConnection(); siteConnection.loadState(memento); return siteConnection; } /** * isChanged * * @return */ public boolean isChanged() { for (SiteConnection siteConnection : connections) { if (siteConnection.isChanged()) { dirty = true; } } try { return dirty; } finally { dirty = false; } } /* * (non-Javadoc) * @see * com.aptana.ide.syncing.core.ISiteConnectionManager#addSiteConnection(com.aptana.ide.syncing.core.ISiteConnection) */ public void addSiteConnection(ISiteConnection siteConnection) { if (!(siteConnection instanceof SiteConnection)) { throw new IllegalArgumentException(); } if (!connections.contains(siteConnection)) { connections.add((SiteConnection) siteConnection); dirty = true; broadcastEvent(new SiteConnectionEvent(this, SiteConnectionEvent.POST_ADD, siteConnection)); } } /* * (non-Javadoc) * @see * com.aptana.ide.syncing.core.ISiteConnectionManager#removeSiteConnection(com.aptana.ide.syncing.core.ISiteConnection * ) */ public void removeSiteConnection(ISiteConnection siteConnection) { if (connections.contains(siteConnection)) { connections.remove(siteConnection); dirty = true; broadcastEvent(new SiteConnectionEvent(this, SiteConnectionEvent.POST_DELETE, siteConnection)); } } /* * (non-Javadoc) * @see * com.aptana.ide.syncing.core.ISiteConnectionManager#siteConnectionChanged(com.aptana.ide.syncing.core.ISiteConnection * ) */ public void siteConnectionChanged(ISiteConnection siteConnection) { if (connections.contains(siteConnection)) { dirty = true; broadcastEvent(new SiteConnectionEvent(this, SiteConnectionEvent.POST_CHANGE, siteConnection)); } } /* * (non-Javadoc) * @see * com.aptana.ide.syncing.core.ISiteConnectionManager#cloneSiteConnection(com.aptana.ide.syncing.core.ISiteConnection * ) */ public ISiteConnection cloneSiteConnection(ISiteConnection siteConnection) throws CoreException { if (!(siteConnection instanceof SiteConnection)) { throw new IllegalArgumentException(); } if (siteConnection == DefaultSiteConnection.getInstance()) { // special handling for cloning the default site connection ISiteConnection clone = new SiteConnection(); clone.setName(siteConnection.getName()); clone.setSource(siteConnection.getSource()); clone.setDestination(siteConnection.getDestination()); return clone; } return restoreConnection(storeConnection((SiteConnection) siteConnection)); } /* * (non-Javadoc) * @see com.aptana.ide.syncing.core.ISiteConnectionManager#createSiteConnection() */ public ISiteConnection createSiteConnection() { return new SiteConnection(); } /* * (non-Javadoc) * @see com.aptana.ide.syncing.core.ISiteConnectionManager#getSiteConnections() */ public ISiteConnection[] getSiteConnections() { return connections.toArray(new ISiteConnection[connections.size()]); } /* * (non-Javadoc) * @see com.aptana.ide.syncing.core.ISiteConnectionManager#addListener(com.aptana.ide.syncing.core.events. * ISiteConnectionListener) */ public void addListener(ISiteConnectionListener listener) { listeners.add(listener); } /* * (non-Javadoc) * @see com.aptana.ide.syncing.core.ISiteConnectionManager#removeListener(com.aptana.ide.syncing.core.events. * ISiteConnectionListener) */ public void removeListener(ISiteConnectionListener listener) { listeners.add(listener); } private void broadcastEvent(SiteConnectionEvent event) { final Object[] list = listeners.getListeners(); for (Object listener : list) { ((ISiteConnectionListener) listener).siteConnectionChanged(event); } } /** * Migrating the connection settings in 1.5 to 2.0. * * @param file * the settings file * @throws IOException */ private void load15State(File file) throws IOException, CoreException { StringBuilder contents = new StringBuilder(); BufferedReader input = null; try { input = new BufferedReader(new FileReader(file)); String line = null; while ((line = input.readLine()) != null) { contents.append(line); } } finally { if (input != null) { try { input.close(); } catch (IOException e) { } } } String s = contents.toString(); if (s.indexOf(IConnectionPoint15Constants.DELIMITER) < 0) { s = StringUtil.replace(s, "%%%%", IConnectionPoint15Constants.DELIMITER); //$NON-NLS-1$ s = StringUtil.replace(s, "@@@@", IConnectionPoint15Constants.OBJ_DELIMITER); //$NON-NLS-1$ s = StringUtil.replace(s, "~~~~", IConnectionPoint15Constants.SECTION_DELIMITER); //$NON-NLS-1$ s = StringUtil.replace(s, "!!!!", IConnectionPoint15Constants.TYPE_DELIMITER); //$NON-NLS-1$ s = StringUtil.replace(s, "}}}}", IConnectionPoint15Constants.FILE_DELIMITER); //$NON-NLS-1$ } String[] sections = s.split(IConnectionPoint15Constants.SECTION_DELIMITER); if (sections.length > 0) { load15VirtualFileManagers(sections[0]); } if (sections.length > 1) { load15VirtualFileManagerSyncItems(sections[1]); } } private void load15VirtualFileManagers(String s) throws CoreException { Map<String, List<String>> dataTypes = new HashMap<String, List<String>>(); String[] parts = s.split(IConnectionPoint15Constants.OBJ_DELIMITER); String[] itemParts; for (String item : parts) { itemParts = item.split(IConnectionPoint15Constants.TYPE_DELIMITER); if (itemParts.length == 2) { String type = itemParts[0]; String data = itemParts[1]; if ("null".equals(type)) { //$NON-NLS-1$ continue; } List<String> list = dataTypes.get(type); if (list == null) { list = new ArrayList<String>(); dataTypes.put(type, list); } list.add(data); } } Set<String> types = dataTypes.keySet(); IConnectionPointManager manager = CoreIOPlugin.getConnectionPointManager(); IConnectionPoint connectionPoint; for (String type : types) { List<String> connectionDatas = dataTypes.get(type); for (String connectionData : connectionDatas) { connectionPoint = manager.restore15ConnectionPoint(type, connectionData); if (connectionPoint != null) { manager.addConnectionPoint(connectionPoint); } } } } private void load15VirtualFileManagerSyncItems(String s) { String[] parts = s.split(IConnectionPoint15Constants.OBJ_DELIMITER); String[] itemParts; ISiteConnection connection; for (String item : parts) { itemParts = item.split(IConnectionPoint15Constants.TYPE_DELIMITER); if (itemParts.length == 2) { String type = itemParts[0]; String data = itemParts[1]; if ("null".equals(type)) { //$NON-NLS-1$ continue; } connection = restore15Connection(data); if (connection != null && connection.getSource() != null && connection.getDestination() != null) { addSiteConnection(connection); } } } } private ISiteConnection restore15Connection(String data) { String[] args = data.split(IConnectionPoint15Constants.DELIMITER); if (args.length < 3) { return null; } ISiteConnection siteConnection = createSiteConnection(); siteConnection.setName(args[0]); String sourceId = args[1]; String destinationId = args[2]; IConnectionPoint[] connectionPoints = CoreIOPlugin.getConnectionPointManager().getConnectionPoints(); String id; for (IConnectionPoint connectionPoint : connectionPoints) { id = connectionPoint.getId(); if (id.equals(sourceId)) { siteConnection.setSource(connectionPoint); } else if (id.equals(destinationId)) { siteConnection.setDestination(connectionPoint); } } return siteConnection; } }