Package org.apache.slide.projector.application

Source Code of org.apache.slide.projector.application.ApplicationManager$ConfigurationHandler

package org.apache.slide.projector.application;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.slide.projector.Context;
import org.apache.slide.projector.Projector;
import org.apache.slide.projector.SystemContext;
import org.apache.slide.projector.URI;
import org.apache.slide.projector.descriptor.ValueFactory;
import org.apache.slide.projector.descriptor.ValueFactoryManager;
import org.apache.slide.projector.engine.ProcessorManager;
import org.apache.slide.projector.engine.ProjectorClassLoader;
import org.apache.slide.projector.engine.Scheduler;
import org.apache.slide.projector.i18n.MessageManager;
import org.apache.slide.projector.value.ArrayValue;
import org.apache.slide.projector.value.StreamableValue;
import org.apache.slide.projector.value.URIValue;
import org.apache.slide.projector.value.Value;
import org.apache.webdav.lib.Subscriber;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import de.zeigermann.xml.simpleImporter.DefaultSimpleImportHandler;
import de.zeigermann.xml.simpleImporter.SimpleImporter;
import de.zeigermann.xml.simpleImporter.SimplePath;

public class ApplicationManager {
    private final static Logger logger = Logger.getLogger(ApplicationManager.class.getName());

    private final static String APPLICATION_CONFIG = "application.xml";
    private final static Context context = new SystemContext();
    private final static String CLASSES_DIR = "classes/";

    private static ApplicationManager applicationManager;
    private List applicationListeners = new ArrayList();
    private Map installedApplications = new HashMap(); // URI -> Application
    // FIXME: Should be used from applications classpath
    private ProjectorClassLoader factoryClassLoader = new ProjectorClassLoader(this.getClass().getClassLoader(), new URIValue(Projector.getProjectorDir()+CLASSES_DIR));
   
    private ApplicationManager() {
        logger.log(Level.INFO, "Starting application manager");
      Projector.getRepository().subscribe("Update/newmember", new URIValue(Projector.getApplicationsDir()), 1,
          new Subscriber() {
        public void notify(String uri, Map information) {
          logger.log(Level.FINE, "Package manager received add event");
          applicationManager.installApplications();
        }
      }, context.getCredentials());
      Projector.getRepository().subscribe("Delete", new URIValue(Projector.getApplicationsDir()), 1,
          new Subscriber() {
        public void notify(String uri, Map information) {
          logger.log(Level.FINE, "Package manager received delete event");
          applicationManager.installApplications();
        }
      }, context.getCredentials());
      applicationListeners.add(ProcessorManager.getInstance());
      applicationListeners.add(MessageManager.getInstance());
      applicationListeners.add(Scheduler.getInstance());
      installApplications();
    }

    private synchronized void installApplications() {
      Value[] applicationUris;
      List applicationsToInstall = new ArrayList();
      List applicationsToRemove = new ArrayList();
      try {
        List removedApplications = new ArrayList();
        removedApplications.addAll(installedApplications.keySet());
        applicationUris = ((ArrayValue)Projector.getRepository().getChildren(new URIValue(Projector.getApplicationsDir()), context.getCredentials())).getArray();
        for ( int i = 0; i < applicationUris.length; i++ ) {
          String applicationUri = applicationUris[i].toString();
          if ( !applicationUri.endsWith("/") ) {
            applicationUri = applicationUri + "/";
          }
          /* FIXME: Is this needed or can it be fixed in getChildren() ?
          if ( applicationUri.indexOf(Constants.REPOSITORY_DOMAIN) != -1  ) {
            applicationUri = applicationUri.substring(applicationUri.indexOf(Constants.REPOSITORY_DOMAIN)+Constants.REPOSITORY_DOMAIN.length());
          }
          */
          if ( !installedApplications.containsKey(applicationUri) ) {
            Application installedApplication = parseApplication(new URIValue(applicationUri));
            if ( installedApplication != null ) {
              applicationsToInstall.add(installedApplication);
            }
          } else {
            logger.log(Level.FINE, "Application '"+applicationUri+"' already installed");
            removedApplications.remove(applicationUri);
          }
        } 
        for ( Iterator i = removedApplications.iterator(); i.hasNext(); ) {
          Application removedApplication = (Application)installedApplications.get((URI)i.next());
          applicationsToRemove.add(removedApplication);
        }
        // install applications sorted by application dependencies
        List sortedApplications = sortApplications(applicationsToInstall);
        for ( Iterator i = sortedApplications.iterator(); i.hasNext(); ) {
          Application application = (Application)i.next();
            Projector.getRepository().subscribe("Update", application.getUri(), 0,
                new Subscriber() {
              public void notify(String uri, Map information) {
                applicationManager.updateApplication(uri);
              }
            }, context.getCredentials());
          install(Application.MESSAGES, application);
          install(Application.PROCESSORS, application);
        }
          Scheduler.getInstance().install(new URIValue(Projector.getWorkDir() + Scheduler.JOBS), true);
        for ( Iterator i = sortedApplications.iterator(); i.hasNext(); ) {
          Application application = (Application)i.next();
          install(Application.JOBS, application);
        }
        Scheduler.getInstance().saveJobs();
      } catch (IOException e) {
        logger.log(Level.SEVERE, "Could not determine installed applications!", e);
      }
    } 
   
    public static ApplicationManager getInstance() {
      if ( applicationManager == null ) {
        applicationManager = new ApplicationManager();
      }
        return applicationManager;
    }
   
    private List sortApplications(List applicationsToInstall) {
      List sortedApplications = new ArrayList();
    for ( Iterator i = applicationsToInstall.iterator(); i.hasNext(); ) {
      Application application = (Application)i.next();
      if ( !sortedApplications.contains(application) ) {
        logger.log(Level.FINE, "Try to install '"+application.getName()+"'");
        addRequiredApplicationsFirst(sortedApplications, applicationsToInstall, application);
      }
    }
      return sortedApplications;
    }

  private void addRequiredApplicationsFirst(List sortedApplications, List applicationsToInstall, Application application) {
    // FIXME: Check application versions
    logger.log(Level.FINE, "Checking for dependencies...");
    for ( Iterator i = application.getDependencies().iterator(); i.hasNext(); ) {
      Dependency dependency = (Dependency)i.next();
      logger.log(Level.FINE, "Dependency on application '"+dependency.getRequiredApplication()+"' found!");
      Application requiredApplication = getApplicationByName(applicationsToInstall, dependency.getRequiredApplication());
      if ( requiredApplication == null ) {
        // check if application is already installed
        requiredApplication = getApplicationByName(installedApplications.entrySet(), dependency.getRequiredApplication());
        if ( requiredApplication == null ) {
          // FIXME: Throw exception and abort startup
          logger.log(Level.SEVERE, "Required application '"+dependency.getRequiredApplication()+"' not found!");
        }
      } else {
        logger.log(Level.FINE, "Required application '"+requiredApplication.getName()+"' not installed but available, so install it first");
        addRequiredApplicationsFirst(sortedApplications, applicationsToInstall, requiredApplication);
      }
    }
    if ( !sortedApplications.contains(application) ) {
      logger.log(Level.FINE, "Adding '"+application.getName()+"' to installation process");
      sortedApplications.add(application);
    }
  }
   
    private Application getApplicationByName(Collection applications, String name) {
    for ( Iterator i = applications.iterator(); i.hasNext(); ) {
      Application application = (Application)i.next();
      if ( application.getName().equals(name)) {
        return application;
      }
    }
    return null;
    }
   
    private Application parseApplication(URI applicationUri) {
      try {
        SimpleImporter importer = new SimpleImporter();
        URI applicationDefinition = new URIValue(applicationUri.toString()+APPLICATION_CONFIG);
        StreamableValue applicationDefinitionResouce = ((StreamableValue)Projector.getRepository().getResource(applicationDefinition, context.getCredentials()));
        if ( applicationDefinitionResouce != null ) {
          InputStream configuration = applicationDefinitionResouce.getInputStream();
          ConfigurationHandler handler = new ConfigurationHandler(applicationUri);
          importer.addSimpleImportHandler(handler);
          importer.parse(new InputSource(configuration));
          return handler.getApplication();
        } else {
          logger.log(Level.SEVERE, "Application definition (application.xml) not found in directory '"+applicationUri+"'. Application will not be installed!");
        }
      } catch (ParserConfigurationException e) {
        logger.log(Level.SEVERE, "Exception while parsing application configuration. Skipping installation...", e);
      } catch (SAXException e) {
        logger.log(Level.SEVERE, "Exception while parsing application configuration. Skipping installation...", e);
      } catch (IOException e) {
        logger.log(Level.SEVERE, "Could not get application information. Skipping installation...", e);
    }       
    return null;
    }
   
    private Application getApplication(List applications, URI applicationUri) {
      for ( Iterator i = applications.iterator(); i.hasNext(); ) {
        Application application = (Application)i.next();
        if ( application.getUri().equals(applicationUri) ) return application;
      }
      return null;
    }
   
  private synchronized void updateApplication(String uri) {
    URI applicationUri = new URIValue(uri);
        logger.log(Level.FINE, "Updating application '"+applicationUri+"'");
        // Compare newly parsed application with previously installed and send diffs
        Application installedApplication = (Application)installedApplications.get(applicationUri);
        Application updatedApplication = parseApplication(applicationUri);
        for ( Iterator i = installedApplication.getContent().entrySet().iterator(); i.hasNext(); ) {
          Map.Entry entry = (Map.Entry)i.next();
            List removed = new ArrayList();
            removed.addAll((List)entry.getValue());
            List updated = updatedApplication.getContent((String)entry.getKey());
            if ( updated != null ) {
              removed.removeAll(updated);
            }
        for ( Iterator j = removed.iterator(); j.hasNext(); ) {
          for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) {
            ((ApplicationListener)k.next()).uninstall((String)entry.getKey(), updatedApplication.getUri(), (URI)j.next());
          }
        }
        }
        for ( Iterator i = updatedApplication.getContent().entrySet().iterator(); i.hasNext(); ) {
          Map.Entry entry = (Map.Entry)i.next();
            List added = new ArrayList();
            added.addAll((List)entry.getValue());
            List installed = installedApplication.getContent((String)entry.getKey());
            if ( installed != null ) {
              added.removeAll(installed);
            }
        for ( Iterator j = added.iterator(); j.hasNext(); ) {
          for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) {
            ((ApplicationListener)k.next()).install((String)entry.getKey(), updatedApplication.getUri(), (URI)j.next());
          }
        }
        }
  } 

  private void install(String type, Application application) {
        logger.log(Level.FINE, "Installing "+type+" of application '"+application.getUri()+"'");
      List contents = (List)application.getContent().get(type);
      if ( contents != null ) {
        for ( Iterator j = contents.iterator(); j.hasNext(); ) {
          URI uri = (URI)j.next();
          for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) {
            ((ApplicationListener)k.next()).install(type, application.getUri(), uri);
          }
        }
      }
      installedApplications.put(application.getUri(), application);
  }
 
  private void uninstall(String type, Application application) {
        logger.log(Level.FINE, "Uninstall "+type+" of application '"+application.getUri()+"'");
    for ( Iterator i = application.getContent().entrySet().iterator(); i.hasNext(); ) {
      Map.Entry entry = (Map.Entry)i.next();
      for ( Iterator j = ((List)entry.getValue()).iterator(); j.hasNext(); ) {
        URI uri = (URI)j.next();
        for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) {
          ((ApplicationListener)k.next()).uninstall((String)entry.getKey(), application.getUri(), uri);
        }
      }
    }
    // FIXME: Remove subscriber
    installedApplications.remove(application.getUri());
  }
 
    private final class ConfigurationHandler extends DefaultSimpleImportHandler {
    private Application application;
    private URI applicationUri;
   
    private ConfigurationHandler(URI applicationUri) {
      this.applicationUri = applicationUri;
    }

    private Application getApplication() {
      return application;
    }
   
    public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) {
            if (path.matches("application")) {
        application = new Application(applicationUri);
            } else if ( path.matches("application/name") ) {
        application.setName(leadingCDdata);     
            } else if ( path.matches("application/display-name") ) {
        application.setDisplayName(leadingCDdata);     
            } else if ( path.matches("application/vendor") ) {
        application.setVendor(leadingCDdata);     
            } else if ( path.matches("application/description") ) {
        application.setDescription(leadingCDdata);     
            } else if ( path.matches("application/version") ) {
        application.setVersion(leadingCDdata);     
            } else if ( path.matches("application/dependencies/requires") ) {
              Dependency dependency = new Dependency(attributes.getValue("application"), attributes.getValue("version"));
        application.addDependency(dependency);     
            } else if ( path.matches("application/resource-types/resource-type") ) {
        String resourceTypeName = attributes.getValue("name");
        String clazz = attributes.getValue("class");
        try {
          ValueFactory descriptorFactory = (ValueFactory)factoryClassLoader.loadClass(clazz).getConstructor(new Class[0]).newInstance(new Object[0]);
          ValueFactoryManager.getInstance().registerDescriptorFactory(descriptorFactory);
          logger.log(Level.FINE, "Successfully registered descriptor factory " + clazz);
                } catch (Exception e) {
                    logger.log(Level.SEVERE, "Descriptor factory " + clazz + " could not loaded!", e);
                }
            } else if ( path.matches("application/content/processors") ) {
              String uri = attributes.getValue("uri");
              application.addContent(Application.PROCESSORS, new URIValue(applicationUri+attributes.getValue("uri")));     
            } else if ( path.matches("application/content/messages") ) {
              application.addContent(Application.MESSAGES, new URIValue(applicationUri+attributes.getValue("uri")));     
            } else if ( path.matches("application/content/jobs") ) {
              application.addContent(Application.JOBS, new URIValue(applicationUri+attributes.getValue("uri")));     
            }
        }
    }
}
TOP

Related Classes of org.apache.slide.projector.application.ApplicationManager$ConfigurationHandler

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.