Package org.eclipse.php.internal.server.core.manager

Source Code of org.eclipse.php.internal.server.core.manager.ServersManager

/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.server.core.manager;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.php.internal.core.util.preferences.XMLPreferencesReader;
import org.eclipse.php.internal.core.util.preferences.XMLPreferencesWriter;
import org.eclipse.php.internal.server.core.Activator;
import org.eclipse.php.internal.server.core.Logger;
import org.eclipse.php.internal.server.core.Server;
import org.osgi.service.prefs.BackingStoreException;

/**
* A manager for PHP Servers.
*
* @author shalom
*/
public class ServersManager implements PropertyChangeListener, IAdaptable {

  /** Servers preferences key */
  public static final String SERVERS_PREFERENCES_KEY = "phpServers"; //$NON-NLS-1$
  /** Default server name preferences key */
  public static final String DEFAULT_SERVER_PREFERENCES_KEY = "defaultPHPServer"; //$NON-NLS-1$

  // defaultServersMap holds a mapping between an IProject to a Server.
  // We take advantage of the NULL wrapping to indicate that a null values
  // will also
  // be mapped to a server (the workspace server).
  private HashMap defaultServersMap = new HashMap();
  // Holds a server name to Server instance mapping.
  private HashMap servers;
  private ArrayList listeners;

  private static ServersManager instance;
  private static final String NODE_QUALIFIER = Activator.PLUGIN_ID
      + ".phpServersPrefs"; //$NON-NLS-1$
  private static final String BASE_URL = "http://localhost"; //$NON-NLS-1$
  public static final String Default_Server_Name = "Default PHP Web Server"; //$NON-NLS-1$

  public static ServersManager getInstance() {
    if (instance == null) {
      instance = new ServersManager();
    }
    return instance;
  }

  private ServersManager() {
    servers = new HashMap();
    listeners = new ArrayList();
    loadServers();
  }

  /**
   * Adds an IServersManagerListener.
   *
   * @param listener
   */
  public static void addManagerListener(IServersManagerListener listener) {
    ArrayList listeners = getInstance().listeners;
    if (!listeners.contains(listener)) {
      listeners.add(listener);
    }
  }

  /**
   * Removes an IServersManagerListener.
   *
   * @param listener
   */
  public static void removeManagerListener(IServersManagerListener listener) {
    getInstance().listeners.remove(listener);
  }

  /**
   * Adds a Server to the manager. If a server with the same name exists in
   * the manager, the existing server will be overidden with the new one and
   * event notifications will be fired for the removal and for the addition.
   * Note: The added server is not saved into the preferences until the
   * {@link #save()} is called.
   *
   * @param server
   *            A Server
   * @see #save()
   */
  public static void addServer(Server server) {
    if (server == null) {
      return;
    }

    ServersManager manager = getInstance();
    Server oldValue = ServersManager.getServer(server);
    if (server != oldValue) {
      manager.servers.remove(oldValue.getName());
      oldValue.removePropertyChangeListener(manager);
      ServerManagerEvent event = new ServerManagerEvent(
          ServerManagerEvent.MANAGER_EVENT_REMOVED, oldValue);
      manager.fireEvent(event);
    }
    oldValue = (Server) manager.servers.put(server.getName(), server);
    if (oldValue != null) {
      oldValue.removePropertyChangeListener(manager);
      ServerManagerEvent event = new ServerManagerEvent(
          ServerManagerEvent.MANAGER_EVENT_REMOVED, oldValue);
      manager.fireEvent(event);
    } else {

    }
    ServerManagerEvent event = new ServerManagerEvent(
        ServerManagerEvent.MANAGER_EVENT_ADDED, server);
    manager.fireEvent(event);

    // Register the manager as a Server lister to get nofitications about
    // attribute changes.
    server.addPropertyChangeListener(manager);
  }

  /**
   * Removes a Server from the manager. In case that that given server is set
   * to be the default server for a project, the project will be set with the
   * workspace default server.
   *
   * @param serverName
   *            The name of the server.
   * @return The removed Server; null if non was found to be removed.
   */
  public static Server removeServer(String serverName) {
    // Do it the long way...
    // Check if the removed server is the workspace default, and if so,
    // replace the default to the
    // first in the list.
    ServersManager manager = ServersManager.getInstance();
    Server removedServer = (Server) manager.servers.remove(serverName);
    Server workspaceDefault = getDefaultServer(null);
    // if (workspaceDefault == null) {
    // // Should not happen
    // Logger.log(IStatus.ERROR,
    // "There is no defined default server for the workspace.");
    // return null;
    // }
    if (removedServer == null) {
      // if the name is not existing, just quit.
      return null;
    }

    if (workspaceDefault == removedServer) {
      // If the workspace default server is the same as the one we wish to
      // remove,
      // we should replace it.
      Server[] servers = getServers();
      if (servers.length > 0) {
        workspaceDefault = servers[0];
        setDefaultServer(null, workspaceDefault);
      }
    }

    // Check that if any one of the mapped projects holds a reference to the
    // removed server.
    // If so, replace it with the new default server.
    Object[] keys = manager.defaultServersMap.keySet().toArray();
    for (Object element : keys) {
      if (removedServer == manager.defaultServersMap.get(element)) {
        setDefaultServer((IProject) element, workspaceDefault);
      }
    }

    // Fire the event for the removal
    removedServer.removePropertyChangeListener(manager);
    ServerManagerEvent event = new ServerManagerEvent(
        ServerManagerEvent.MANAGER_EVENT_REMOVED, removedServer);
    manager.fireEvent(event);
    return removedServer;
  }

  /**
   * Returns a Server from the manager.
   *
   * @param serverName
   *            The name of the server.
   * @return The Server; null if non was found.
   */
  public static Server getServer(String serverName) {
    ServersManager manager = getInstance();
    return (Server) manager.servers.get(serverName);
  }

  public static Server getServer(Server oldServer) {
    ServersManager manager = getInstance();
    for (Iterator iterator = manager.servers.values().iterator(); iterator
        .hasNext();) {
      Server server = (Server) iterator.next();
      if (server.getBaseURL().equals(oldServer.getBaseURL())) {
        return server;
      }
    }
    return oldServer;
  }

  /**
   * Returns all the Servers that are managed by this manager.
   *
   * @return An array of Servers.
   */
  public static Server[] getServers() {
    ServersManager manager = getInstance();
    Collection values = manager.servers.values();
    Server[] servers = new Server[values.size()];
    values.toArray(servers);
    return servers;
  }

  /**
   * Returns the dafault debug server.
   *
   * @return
   */
  public static Server getDefaultServer(IProject project) {
    ServersManager manager = getInstance();
    // First, try to get it from the memory.
    Server server = (Server) manager.defaultServersMap.get(project);
    if (project != null) {
      // In case that the project is not null, check that we have
      // project-specific settings for it.
      // Otherwise, map it to the workspace default server.
      IScopeContext[] preferenceScopes = createPreferenceScopes(project);
      String projectSpecificServer = preferenceScopes[0].getNode(
          NODE_QUALIFIER).get(DEFAULT_SERVER_PREFERENCES_KEY,
          (String) null);
      if (projectSpecificServer == null) {
        // We do not have a project specific setting for this project.
        // Map it to the default workspace server.
        manager.defaultServersMap.put(project,
            manager.defaultServersMap.get(null));
        server = (Server) manager.defaultServersMap.get(null);
      }
    }
    // If the server was no found in our hash, try to load it from the
    // preferences.
    // This part of code should only happen one time when the first call for
    // the
    // getDefaultServer. Once it's done, there is no reason to re-load the
    // servers definitions
    // from the preferences (XML).
    if (server == null) {
      String serverName = null;
      if (project == null) {
        // Get the default workspace server.
        Preferences prefs = Activator.getDefault()
            .getPluginPreferences();
        serverName = prefs.getString(DEFAULT_SERVER_PREFERENCES_KEY);
      } else {
        // Get the projects' default server
        IScopeContext[] preferenceScopes = createPreferenceScopes(project);
        serverName = preferenceScopes[0].getNode(NODE_QUALIFIER).get(
            DEFAULT_SERVER_PREFERENCES_KEY, (String) null);
        if (serverName == null) {
          // Take the workspace Server and make it the project's
          // default server
          Preferences prefs = Activator.getDefault()
              .getPluginPreferences();
          serverName = prefs
              .getString(DEFAULT_SERVER_PREFERENCES_KEY);
        }
      }
      if (serverName != null && !"".equals(serverName)) { //$NON-NLS-1$
        server = (Server) manager.servers.get(serverName);
        // Map this server as the default for the project (if not null)
        // or for the workspace (when the project is null).
        manager.defaultServersMap.put(project, server);
      } else {
        // Create a default server and hook it as a workspace and the
        // project server (can be the same).
        try {
          server = createServer(Default_Server_Name, BASE_URL);

        } catch (MalformedURLException e) {
          // safe server creation
        }
        manager.defaultServersMap.put(null, server);
        manager.defaultServersMap.put(project, server);
        manager.innerSaveDefaultServer(project, server);
        ServersManager.save();
      }
    }

    // fixed bug 197579 - in case of no default server mark the first server
    // as default
    if (server == null) {
      if (manager.servers.size() > 0) {
        server = (Server) manager.servers.values().iterator().next();
        setDefaultServer(null, server);
      }
    }
    return server;
  }

  // Creates a preferences scope for the given project.
  // This scope will be used to search for preferences values.
  private static IScopeContext[] createPreferenceScopes(IProject project) {
    if (project != null) {
      return new IScopeContext[] { new ProjectScope(project),
          InstanceScope.INSTANCE, DefaultScope.INSTANCE };
    }
    return new IScopeContext[] { InstanceScope.INSTANCE,
        DefaultScope.INSTANCE };
  }

  /**
   * Sets the default debug server. In case that the given project is null,
   * the setting if for the workspace. In case that the given server is null,
   * the preferences value stored for the given project will be removed.
   *
   * @param project
   *            A project to assign to a default server.
   * @param server
   *            A default server for the given project.
   */
  public static void setDefaultServer(IProject project, Server server) {
    ServersManager manager = getInstance();
    // Get the default server for the given project.
    // In case that we need to set a new server for the project, make sure
    // we save it as well.
    Server defaultProjectServer = (Server) manager.defaultServersMap
        .get(project);
    if (server != defaultProjectServer) {
      manager.defaultServersMap.put(project, server);
      manager.innerSaveDefaultServer(project, server);
    }
  }

  /**
   * Sets the default debug server. In case that the given project is null,
   * the setting if for the workspace.
   *
   * @param project
   *            A project to assign to a default server.
   * @param serverName
   *            A default server name for the given project.
   */
  public static void setDefaultServer(IProject project, String serverName) {
    ServersManager manager = getInstance();
    Server server = (Server) manager.servers.get(serverName);
    setDefaultServer(project, server);
  }

  /**
   * Creates and adds a server.
   *
   * @param name
   * @param baseURL
   * @return
   * @throws MalformedURLException
   */
  public static Server createServer(String name, String baseURL)
      throws MalformedURLException {
    Server server = new Server(name, "localhost", baseURL, ""); //$NON-NLS-1$ //$NON-NLS-2$
    server = ServersManager.getServer(server);
    addServer(server);
    return server;
  }

  /**
   * Save the listed servers into the preferences.
   */
  public static void save() {
    Server[] servers = getServers();
    XMLPreferencesWriter.write(Activator.getDefault()
        .getPluginPreferences(), SERVERS_PREFERENCES_KEY, servers);
    Activator.getDefault().savePluginPreferences();
  }

  private void innerSaveDefaultServer(IProject project, Server server) {
    Preferences prefs = Activator.getDefault().getPluginPreferences();
    if (project == null && server != null) {
      prefs.setValue(DEFAULT_SERVER_PREFERENCES_KEY, server.getName());
      Activator.getDefault().savePluginPreferences();
    } else if (project != null) {
      String defaultWorkspaceServer = prefs
          .getString(DEFAULT_SERVER_PREFERENCES_KEY);
      IScopeContext[] scopeContexts = createPreferenceScopes(project);
      IEclipsePreferences prefsNode = scopeContexts[0]
          .getNode(NODE_QUALIFIER);
      if (server != null
          && !defaultWorkspaceServer.equals(server.getName())) {
        prefsNode.put(DEFAULT_SERVER_PREFERENCES_KEY, server.getName());
      } else {
        prefsNode.remove(DEFAULT_SERVER_PREFERENCES_KEY);
      }
      try {
        prefsNode.flush();
      } catch (BackingStoreException e) {
        Logger.logException(e);
      }
    }
  }

  // Loads the servers from the preferences store.
  private void loadServers() {
    // Read all the configurations of the servers from the preferences and
    // place them into the
    // servers hash (map name to Server instance).
    HashMap[] serversConfigs = XMLPreferencesReader.read(Activator
        .getDefault().getPluginPreferences(), SERVERS_PREFERENCES_KEY);
    // Then we create the servers from their configurations...
    for (HashMap serverMap : serversConfigs) {
      Server server = new Server();
      server.restoreFromMap(serverMap);
      String serverName = server.getName();
      servers.put(serverName, server);
      // Register the manager as a Server lister to get nofitications
      // about attribute changes.
      server.addPropertyChangeListener(this);
    }
  }

  /**
   * Fires a ServerManagerEvent to all the registered
   * IServersManagerListeners.
   *
   * @param event
   */
  public void fireEvent(ServerManagerEvent event) {
    IServersManagerListener[] allListeners = new IServersManagerListener[listeners
        .size()];
    listeners.toArray(allListeners);
    if (event.getType() == ServerManagerEvent.MANAGER_EVENT_ADDED) {
      fireAddEvent(event, allListeners);
    } else if (event.getType() == ServerManagerEvent.MANAGER_EVENT_REMOVED) {
      fireRemoveEvent(event, allListeners);
    } else if (event.getType() == ServerManagerEvent.MANAGER_EVENT_MODIFIED) {
      fireModifiedEvent(event, allListeners);
    }
  }

  private void fireAddEvent(ServerManagerEvent event,
      IServersManagerListener[] allListeners) {
    for (IServersManagerListener element : allListeners) {
      element.serverAdded(event);
    }
  }

  private void fireRemoveEvent(ServerManagerEvent event,
      IServersManagerListener[] allListeners) {
    for (IServersManagerListener element : allListeners) {
      element.serverRemoved(event);
    }
  }

  private void fireModifiedEvent(ServerManagerEvent event,
      IServersManagerListener[] allListeners) {
    for (IServersManagerListener element : allListeners) {
      element.serverModified(event);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @seejava.beans.PropertyChangeListener#propertyChange(java.beans.
   * PropertyChangeEvent)
   */
  public void propertyChange(PropertyChangeEvent evt) {
    // Listen to any attribute change in the Servers
    Server server = (Server) evt.getSource();
    String oldValue = (String) evt.getOldValue();
    String newValue = (String) evt.getNewValue();
    ServerManagerEvent event = new ServerManagerEvent(
        ServerManagerEvent.MANAGER_EVENT_MODIFIED, server,
        evt.getPropertyName(), oldValue, newValue);
    fireEvent(event);
  }

  /**
   * Finds the local server corresponding to the given project
   *
   * @param project
   */
  public final static Server getLocalServer(IProject project) {
    for (Server server : getServers()) {
      final String documentRoot = server.getDocumentRoot();
      if (documentRoot != null && documentRoot.length() > 0) {
        final Path path = new Path(documentRoot);
        final IPath fullPath = project.getLocation();
        if (fullPath != null && path.isPrefixOf(fullPath)) {
          return server;
        }
      }
    }
    return null;
  }

  public Object getAdapter(Class adapter) {
    return null;
  }
}
TOP

Related Classes of org.eclipse.php.internal.server.core.manager.ServersManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.