Package org.apache.slide.projector.engine

Source Code of org.apache.slide.projector.engine.ProcessorManager

package org.apache.slide.projector.engine;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
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 org.apache.slide.projector.ConfigurableProcessor;
import org.apache.slide.projector.ConfigurationException;
import org.apache.slide.projector.Context;
import org.apache.slide.projector.EnvironmentConsumer;
import org.apache.slide.projector.ProcessException;
import org.apache.slide.projector.Processor;
import org.apache.slide.projector.Projector;
import org.apache.slide.projector.Result;
import org.apache.slide.projector.URI;
import org.apache.slide.projector.application.Application;
import org.apache.slide.projector.application.ApplicationListener;
import org.apache.slide.projector.descriptor.ParameterDescriptor;
import org.apache.slide.projector.descriptor.ProcessorDescriptor;
import org.apache.slide.projector.descriptor.ResultDescriptor;
import org.apache.slide.projector.descriptor.ValidationException;
import org.apache.slide.projector.i18n.DefaultMessage;
import org.apache.slide.projector.i18n.ErrorMessage;
import org.apache.slide.projector.processor.SimpleProcessor;
import org.apache.slide.projector.processor.process.Process;
import org.apache.slide.projector.value.AnyValue;
import org.apache.slide.projector.value.NullValue;
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.helpers.AttributesImpl;

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

/**
* The ProcessorManager is responsible for loading processors and their
* configuration. Because every processor is located via its URI, it might be
* possible to handle different versions of the same processor.
* They are reloaded if an event occurs that indicates, that the class or configuration has changed
* or was updated.
*/
public class ProcessorManager implements ApplicationListener, Subscriber {
    public final static URI BINARY = new URIValue("image");
    public final static URI LOCALE_RESOLVER = new URIValue("localeResolver");
    public final static URI URL = new URIValue("url");
    public final static URI THREAD = new URIValue("thread");

    private final static String CLASSES_DIR = "classes/";

    private final static Logger logger = Logger.getLogger(ProcessorManager.class.getName());
    private final static String PROCESSOR_CONFIG = "processors.xml";
    private final static URI SMALL_DEFAULT_ICON = new URIValue("/files/contelligent/images/process.jpg");
    private final static URI LARGE_DEFAULT_ICON = new URIValue("/files/contelligent/images/process.jpg");

    private static ProcessorManager processorManager = new ProcessorManager();
   
    private Map configurationToApplication = new HashMap(); // URI -> URI
    private Map installedProcessors = new HashMap();
    private Map processorMap = new HashMap(256); // URI -> Processor
    private Map configuredProcessors = new HashMap(128);
    private Map configurationListeners = new HashMap(128);
    private Map processorDescriptors = new HashMap(256); // URI -> ProcessorDescriptor
    private ProjectorClassLoader processorClassLoader = new ProjectorClassLoader(this.getClass().getClassLoader(), new URIValue(Projector.getProjectorDir()+CLASSES_DIR));
   
    private ProcessorManager() {
    }
     
    public void install(String type, URI applicationUri, URI configurationUri) {
      if ( type == Application.PROCESSORS ) {
        install(applicationUri, configurationUri);
        configurationToApplication.put(configurationUri, applicationUri);
      }
    }
   
    public void uninstall(String type, URI applicationUri, URI configurationUri) {
      if ( type == Application.PROCESSORS ) {
        uninstall(applicationUri, configurationUri);
        configurationToApplication.remove(configurationUri);
      }
    }
   
    public void update(String type, URI applcationUri, URI configurationUri) {
      if ( type == Application.PROCESSORS ) {
        update(applcationUri, configurationUri);
      }
    }
   
    private void install(URI applicationUri, URI configurationUri) {
      logger.log(Level.FINE, "Installing processors '"+configurationUri+"'");
      try {
        InputStream configuration = ((StreamableValue)Projector.getRepository().getResource(configurationUri, Projector.getCredentials())).getInputStream();
        SimpleImporter importer = new SimpleImporter();
        List alreadyInstalledProcessors = (List)installedProcessors.get(configurationUri);
        if ( alreadyInstalledProcessors == null ) alreadyInstalledProcessors = new ArrayList();
        ConfigurationHandler handler = new ConfigurationHandler(applicationUri, alreadyInstalledProcessors);
        importer.addSimpleImportHandler(handler);
        importer.parse(new InputSource(configuration));
        List removedProcessors = new ArrayList();
        alreadyInstalledProcessors.addAll(handler.getAddedProcessors());
        for ( Iterator i = handler.getRemovedProcessors().iterator(); i.hasNext(); ) {
          URI removedProcessorUri = (URI)i.next();
          uninstallProcessor(removedProcessorUri);
          alreadyInstalledProcessors.remove(removedProcessorUri);
        }
        installedProcessors.put(configurationUri, alreadyInstalledProcessors);
        Projector.getRepository().subscribe("Update", configurationUri, 0, this, Projector.getCredentials());
      } catch (Exception exception) {
        logger.log(Level.SEVERE, "Error while parsing configuration", exception);
      }
    }

    public void uninstall(URI applicationUri, URI configurationUri) {
      logger.log(Level.FINE, "Uninstalling processors '"+configurationUri+"'");
      List processors = (List)installedProcessors.get(configurationUri);
      for ( Iterator j = processors.iterator(); j.hasNext(); ) {
        URI processorUri = (URI)j.next();
        uninstallProcessor(processorUri);
      }
    installedProcessors.remove(configurationUri);
    Projector.getRepository().unsubscribe(configurationUri, this, Projector.getCredentials());
    }
   
    private void uninstallProcessor(URI processorUri) {
    processorMap.remove(processorUri);
    ProcessorDescriptor processorDescriptor = getProcessorDescriptor(processorUri);
    URI processorConfiguration = processorDescriptor.getConfiguration();
    if ( processorConfiguration != null ) {
      configuredProcessors.remove(processorConfiguration);
      Subscriber subscriber = (Subscriber)configurationListeners.get(processorConfiguration);
      Projector.getRepository().unsubscribe(processorConfiguration, subscriber, Projector.getCredentials());
      configurationListeners.remove(processorConfiguration);
    }
    processorDescriptors.remove(processorUri);
    logger.log(Level.FINE, "Removing processor: "+processorUri);
    }
   
    private void update(URI applicationUri, URI configurationUri) {
    Projector.getRepository().unsubscribe(configurationUri, this, Projector.getCredentials());
      install(applicationUri, configurationUri);
    }
   
    public static ProcessorManager getInstance() {
        return processorManager;
    }

  public void notify(String uri, Map information) {
    URI configurationUri = new URIValue(uri);
    update((URI)configurationToApplication.get(configurationUri), configurationUri);
  }

  public Processor getProcessor(URI uri) throws ProcessException {
        if ( processorMap.containsKey(uri) ) {
            return (Processor)processorMap.get(uri);
        }
        logger.log(Level.SEVERE, "Requested processor with URI=" + uri+ " not found!");
        throw new ProcessException(new ErrorMessage("processorNotFound", new Object[] {uri.toString()}));
    }

    public URI getURI(Processor processor) throws ProcessException  {
        for ( Iterator i = processorMap.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry entry = (Map.Entry)i.next();
            if ( entry.getValue() == processor ) {
                return ((URI)entry.getKey());
            }
        }
        logger.log(Level.SEVERE, "Requested URI for processor=" + processor + " not found!");
        throw new ProcessException(new ErrorMessage("processorNotFound", new Object[] {processor.toString()}));
    }

    public Result process(URI processorUri, Map parameters, Context context) throws Exception {
        Processor  processor = getProcessor(processorUri);
        return process(processor, parameters, context);
    }
   
    public static Result process(Processor processor, Map parameters, Context context) throws Exception {
      ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors();
      prepareValues(parameterDescriptors, parameters, context);
      return processor.process(parameters, context);
    }
   
    public Value process(URI simpleProcessorUri, Object input, Context context) throws Exception {
        return process(simpleProcessorUri, input, null, context);
    }

    public Value process(URI simpleProcessorUri, Object input, String resultKey, Context context) throws Exception {
        Processor  processor = getProcessor(simpleProcessorUri);
        ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors();
        if ( parameterDescriptors.length > 1 && countRequiredParameters(parameterDescriptors) > 1 ) {
            throw new ProcessException(new ErrorMessage("valueProcessorNeedsTooManyParametersException"));
        }
        if ( resultKey  == null ) {
            ResultDescriptor resultDescriptor = processor.getResultDescriptor();
            if ( resultDescriptor.getResultEntryDescriptors().length == 0 ) {
                throw new ProcessException(new ErrorMessage("parameterProcessingException", new String[] { simpleProcessorUri.toString() }));
            } else {
                resultKey = resultDescriptor.getResultEntryDescriptors()[0].getName();
            }
        }
        if ( input == null && parameterDescriptors.length == 1 && parameterDescriptors[0].isRequired()) {
            throw new ProcessException(new ErrorMessage("requiredParameterMissing", new String[]{parameterDescriptors[0].getName()}));
        } else if ( input == null && parameterDescriptors.length > 1 ) {
            ParameterDescriptor requiredParameter = getRequiredParameter(parameterDescriptors);
            if ( requiredParameter != null ) throw new ProcessException(new ErrorMessage("requiredParameterMissing", new String[]{ requiredParameter.getName()}));
        } else {
            try {
                // check for SimpleProcessor to avoid HashMap creation
                if ( processor instanceof EnvironmentConsumer ) {
                    Process.checkRequirements((EnvironmentConsumer)processor, context);
                }
                if ( processor instanceof SimpleProcessor ) {
                    Value preparedValue = prepareValue(parameterDescriptors[0], input, context);
                    input = ((SimpleProcessor)processor).process(preparedValue, context);
                } else {
                    Map parameters = new HashMap();
                    if ( parameterDescriptors.length == 1 ) {
                        parameters.put(parameterDescriptors[0].getName(), prepareValue(parameterDescriptors[0], input, context));
                    } else {
                      for ( int i = 0; i < parameterDescriptors.length; i++ ) {
                            if ( parameterDescriptors[i].isRequired() ) {
                                parameters.put(parameterDescriptors[i].getName(), prepareValue(parameterDescriptors[i], input, context));
                            } else {
                                parameters.put(parameterDescriptors[i].getName(), parameterDescriptors[i].getDefaultValue());
                            }
                        }
                     
                    }
                    Result processorResult = processor.process(parameters, context);
                    input = processorResult.getResultEntries().get(resultKey);
                }
            } catch ( Exception exception ) {
                throw new ProcessException(new ErrorMessage("parameterProcessingException", new String[] { simpleProcessorUri.toString(), exception.getMessage() }), exception);
            }
        }
        return (Value)input;
    }

    public static void prepareValues(ParameterDescriptor[] parameterDescriptors, Map parameters, Context context) throws Exception {
      for ( int i = 0; i < parameterDescriptors.length; i++ ) {
        String parameterName = parameterDescriptors[i].getName();
        Object parameterValue = parameters.get(parameterName);
        Value preparedValue = prepareValue(parameterDescriptors[i], parameterValue, context);
        parameters.put(parameterName, preparedValue);
      }
    }
   
    public static Value prepareValue(ParameterDescriptor parameterDescriptor, Object value, Context context) throws Exception {
      Value preparedValue;
      if ( value instanceof AnyValue ) {
         value = ((AnyValue)value).load(context);
      }
      if ( value == null || value instanceof NullValue ) {
            if ( parameterDescriptor.isRequired() ) {
                throw new ValidationException(new ErrorMessage("requiredParameterMissing", new String[] { parameterDescriptor.getName() }));
            } else {
                preparedValue = parameterDescriptor.getDefaultValue();
            }
      } else {
          preparedValue = parameterDescriptor.getValueDescriptor().valueOf(value, context);
          parameterDescriptor.getValueDescriptor().validate(preparedValue, context);
      }
      return preparedValue;
    }

    public ProcessorDescriptor getProcessorDescriptor(URI uri) {
      return (ProcessorDescriptor)processorDescriptors.get(uri);
    }

    public ProcessorDescriptor getProcessorDescriptor(Processor processor) {
        for ( Iterator i = processorDescriptors.values().iterator(); i.hasNext(); ) {
          ProcessorDescriptor processorDescriptor = (ProcessorDescriptor)i.next();
            if ( processorDescriptor.getProcessor() == processor ) return processorDescriptor;
        }
        return null;
    }

    private void registerProcessor(URI uri, Processor processor) {
    }

    private static int countRequiredParameters(ParameterDescriptor[] descriptors) {
        int count = 0;
        for ( int i = 0; i < descriptors.length; i++ ) {
            if ( descriptors[i].isRequired() ) {
                count++;
            }
        }
        return count;
    }

    private static ParameterDescriptor getRequiredParameter(ParameterDescriptor[] descriptors) {
        for ( int i = 0; i < descriptors.length; i++ ) {
            if ( descriptors[i].isRequired() ) {
                return descriptors[i];
            }
        }
        return null;
    }

    public class ConfigurationHandler extends DefaultSimpleImportHandler {
      URI applicationUri;
      List addedProcessors = new ArrayList();
      List removedProcessors = new ArrayList();
       
      public ConfigurationHandler(URI applicationUri, List installedProcessors) {
        this.applicationUri = applicationUri;
        removedProcessors.addAll(installedProcessors);
      }
     
      public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) {
            if (path.matches("processor")) {
              boolean modified = false, added = false;
              URI uri = new URIValue(attributes.getValue("uri"));
              removedProcessors.remove(uri);
              String configURI = attributes.getValue("config-uri");
                String processorName = attributes.getValue("name");
                String descriptionKey = attributes.getValue("description");
                String smallIcon = attributes.getValue("small-icon");
                String largeIcon = attributes.getValue("large-icon");
                String clazz = attributes.getValue("class");
                String bookmark = attributes.getValue("bookmark");
                Processor processor = (Processor)processorMap.get(uri);
                ProcessorDescriptor processorDescriptor = (ProcessorDescriptor)processorDescriptors.get(uri);
                try {
                  if ( processor == null ) {
                    processor = (Processor)processorClassLoader.loadClass(clazz).getConstructor(new Class[0]).newInstance(new Object[0]);
                    added = true;
                    modified = true;
                  }
                  if ( processorDescriptor == null ) {
                    processorDescriptor = new ProcessorDescriptor(uri);
                    modified = true;
                  }
                  if ( processorName == null ) processorName = uri.toString();
                  if ( processorDescriptor.getName() == null || !processorDescriptor.getName().equals(processorName) ) {
                    processorDescriptor.setName(processorName);
                    modified = true;
                  }
                  if ( descriptionKey == null ) {
                    descriptionKey = "processorManager/noProcessorDescriptionAvailable";
                  }
                  DefaultMessage description = null;
                  if ( processorDescriptor.getDescription() == null || !processorDescriptor.getDescription().getId().equals(descriptionKey) ) {
                    description = new DefaultMessage(descriptionKey);
                    processorDescriptor.setDescription(description);
                    modified = true;
                  }
                  if ( processorDescriptor.getProcessor() != processor ) {
                    processorDescriptor.setProcessor(processor);
                    modified = true;
                  }
                  URI smallIconUri = SMALL_DEFAULT_ICON, largeIconUri = LARGE_DEFAULT_ICON;
                  if ( smallIcon != null ) smallIconUri = new URIValue(smallIcon);
                  if ( largeIcon != null ) largeIconUri = new URIValue(largeIcon);
                  if ( processorDescriptor.getSmallIcon() == null || !processorDescriptor.getSmallIcon().equals(smallIconUri) ) {
                    processorDescriptor.setSmallIcon(smallIconUri);
                    modified = true;
                  }
                  if ( processorDescriptor.getLargeIcon() == null || !processorDescriptor.getLargeIcon().equals(largeIconUri) ) {
                      processorDescriptor.setLargeIcon(largeIconUri);
                    modified = true;
                  }
                  if ( bookmark != null ) {
                    boolean isBookmark = Boolean.valueOf(bookmark).booleanValue();
                    if ( processorDescriptor.isBookmark() != isBookmark ) {
                      processorDescriptor.setBookmark(isBookmark);
                      modified = true;
                    }
                  }
                  if ( processor instanceof ConfigurableProcessor && configURI != null ) {
                    if ( !configURI.startsWith("/") ) {
                      configURI = applicationUri.toString() + configURI;
                    }
                    URI configurationUri = new URIValue(configURI);
                    if ( processorDescriptor.getConfiguration() == null || !processorDescriptor.getConfiguration().equals(configurationUri) ) {
                      logger.log(Level.FINE, "Configuring processor with config-URI=" + configURI);
                      processorDescriptor.setConfiguration(configurationUri);
                      StreamableValue config = (StreamableValue)Projector.getRepository().getResource(configurationUri, Projector.getCredentials());
                      ((ConfigurableProcessor)processor).configure(config);
                      // listen for configuration changes
                      Subscriber subscriber = new ConfigurationListener();
                      Projector.getRepository().subscribe("Update", configurationUri, 0, subscriber, Projector.getCredentials());
                      configurationListeners.put(configurationUri, subscriber);
                      configuredProcessors.put(configurationUri, processor);
                      modified = true;
                    }
                    }
                    if ( added ) {
                        logger.log(Level.FINE, "Adding processor with URI=" + uri);
                      addedProcessors.add(uri);
                    }
                    if ( modified ) {
                        logger.log(Level.FINE, "Updating processor with URI=" + uri);
                      processorMap.put(uri, processor);
                      processorDescriptors.put(uri, processorDescriptor);
                    }
                } catch (Exception e) {
                    logger.log(Level.SEVERE, "Processor " + clazz + " could not be created or configured!", e);
                }
            }
        }

      List getAddedProcessors() {
        return addedProcessors;
      }

      List getRemovedProcessors() {
        return removedProcessors;
      }
    }

    class ConfigurationListener implements Subscriber {
      public void notify(String uri, Map information) {
        URI processorUri = new URIValue(uri);
        Processor processor = (Processor)configuredProcessors.get(processorUri);
        logger.log(Level.FINE, "Reloading processor with configuration URI='"+uri+"'");
        try {
          StreamableValue config = (StreamableValue)Projector.getRepository().getResource(processorUri, Projector.getCredentials());
          ((ConfigurableProcessor)processor).configure(config);
        } catch ( IOException e ) {
          logger.log(Level.SEVERE, "Configuration resource with URI='"+uri+"' could not be loaded!", e);
        } catch ( ConfigurationException e ) {
          logger.log(Level.SEVERE, "Processor with configuration URI='" + uri + "' could not be reloaded! Configuration resource might be invalid!", e);
        }
      }
    }
   
    class ConfiguredProcessor {
        private String configUri;
        private URI processorUri;

        public ConfiguredProcessor(String configUri, URI processorUri) {
            this.configUri = configUri;
            this.processorUri = processorUri;
        }

        public String getConfigUri() {
            return configUri;
        }

        public URI getProcessorUri() {
            return processorUri;
        }
    }
}
TOP

Related Classes of org.apache.slide.projector.engine.ProcessorManager

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.