1 package org.apache.slide.projector.engine; 2 3 import java.io.IOException ; 4 import java.io.InputStream ; 5 import java.util.ArrayList ; 6 import java.util.HashMap ; 7 import java.util.Iterator ; 8 import java.util.List ; 9 import java.util.Map ; 10 import java.util.logging.Level ; 11 import java.util.logging.Logger ; 12 13 import org.apache.slide.projector.ConfigurableProcessor; 14 import org.apache.slide.projector.ConfigurationException; 15 import org.apache.slide.projector.Context; 16 import org.apache.slide.projector.EnvironmentConsumer; 17 import org.apache.slide.projector.ProcessException; 18 import org.apache.slide.projector.Processor; 19 import org.apache.slide.projector.Projector; 20 import org.apache.slide.projector.Result; 21 import org.apache.slide.projector.URI; 22 import org.apache.slide.projector.application.Application; 23 import org.apache.slide.projector.application.ApplicationListener; 24 import org.apache.slide.projector.descriptor.ParameterDescriptor; 25 import org.apache.slide.projector.descriptor.ProcessorDescriptor; 26 import org.apache.slide.projector.descriptor.ResultDescriptor; 27 import org.apache.slide.projector.descriptor.ValidationException; 28 import org.apache.slide.projector.i18n.DefaultMessage; 29 import org.apache.slide.projector.i18n.ErrorMessage; 30 import org.apache.slide.projector.processor.SimpleProcessor; 31 import org.apache.slide.projector.processor.process.Process; 32 import org.apache.slide.projector.value.AnyValue; 33 import org.apache.slide.projector.value.NullValue; 34 import org.apache.slide.projector.value.StreamableValue; 35 import org.apache.slide.projector.value.URIValue; 36 import org.apache.slide.projector.value.Value; 37 import org.apache.webdav.lib.Subscriber; 38 import org.xml.sax.InputSource ; 39 import org.xml.sax.helpers.AttributesImpl ; 40 41 import de.zeigermann.xml.simpleImporter.DefaultSimpleImportHandler; 42 import de.zeigermann.xml.simpleImporter.SimpleImporter; 43 import de.zeigermann.xml.simpleImporter.SimplePath; 44 45 52 public class ProcessorManager implements ApplicationListener, Subscriber { 53 public final static URI BINARY = new URIValue("image"); 54 public final static URI LOCALE_RESOLVER = new URIValue("localeResolver"); 55 public final static URI URL = new URIValue("url"); 56 public final static URI THREAD = new URIValue("thread"); 57 58 private final static String CLASSES_DIR = "classes/"; 59 60 private final static Logger logger = Logger.getLogger(ProcessorManager.class.getName()); 61 private final static String PROCESSOR_CONFIG = "processors.xml"; 62 private final static URI SMALL_DEFAULT_ICON = new URIValue("/files/contelligent/images/process.jpg"); 63 private final static URI LARGE_DEFAULT_ICON = new URIValue("/files/contelligent/images/process.jpg"); 64 65 private static ProcessorManager processorManager = new ProcessorManager(); 66 67 private Map configurationToApplication = new HashMap (); private Map installedProcessors = new HashMap (); 69 private Map processorMap = new HashMap (256); private Map configuredProcessors = new HashMap (128); 71 private Map configurationListeners = new HashMap (128); 72 private Map processorDescriptors = new HashMap (256); private ProjectorClassLoader processorClassLoader = new ProjectorClassLoader(this.getClass().getClassLoader(), new URIValue(Projector.getProjectorDir()+CLASSES_DIR)); 74 75 private ProcessorManager() { 76 } 77 78 public void install(String type, URI applicationUri, URI configurationUri) { 79 if ( type == Application.PROCESSORS ) { 80 install(applicationUri, configurationUri); 81 configurationToApplication.put(configurationUri, applicationUri); 82 } 83 } 84 85 public void uninstall(String type, URI applicationUri, URI configurationUri) { 86 if ( type == Application.PROCESSORS ) { 87 uninstall(applicationUri, configurationUri); 88 configurationToApplication.remove(configurationUri); 89 } 90 } 91 92 public void update(String type, URI applcationUri, URI configurationUri) { 93 if ( type == Application.PROCESSORS ) { 94 update(applcationUri, configurationUri); 95 } 96 } 97 98 private void install(URI applicationUri, URI configurationUri) { 99 logger.log(Level.FINE, "Installing processors '"+configurationUri+"'"); 100 try { 101 InputStream configuration = ((StreamableValue)Projector.getRepository().getResource(configurationUri, Projector.getCredentials())).getInputStream(); 102 SimpleImporter importer = new SimpleImporter(); 103 List alreadyInstalledProcessors = (List )installedProcessors.get(configurationUri); 104 if ( alreadyInstalledProcessors == null ) alreadyInstalledProcessors = new ArrayList (); 105 ConfigurationHandler handler = new ConfigurationHandler(applicationUri, alreadyInstalledProcessors); 106 importer.addSimpleImportHandler(handler); 107 importer.parse(new InputSource (configuration)); 108 List removedProcessors = new ArrayList (); 109 alreadyInstalledProcessors.addAll(handler.getAddedProcessors()); 110 for ( Iterator i = handler.getRemovedProcessors().iterator(); i.hasNext(); ) { 111 URI removedProcessorUri = (URI)i.next(); 112 uninstallProcessor(removedProcessorUri); 113 alreadyInstalledProcessors.remove(removedProcessorUri); 114 } 115 installedProcessors.put(configurationUri, alreadyInstalledProcessors); 116 Projector.getRepository().subscribe("Update", configurationUri, 0, this, Projector.getCredentials()); 117 } catch (Exception exception) { 118 logger.log(Level.SEVERE, "Error while parsing configuration", exception); 119 } 120 } 121 122 public void uninstall(URI applicationUri, URI configurationUri) { 123 logger.log(Level.FINE, "Uninstalling processors '"+configurationUri+"'"); 124 List processors = (List )installedProcessors.get(configurationUri); 125 for ( Iterator j = processors.iterator(); j.hasNext(); ) { 126 URI processorUri = (URI)j.next(); 127 uninstallProcessor(processorUri); 128 } 129 installedProcessors.remove(configurationUri); 130 Projector.getRepository().unsubscribe(configurationUri, this, Projector.getCredentials()); 131 } 132 133 private void uninstallProcessor(URI processorUri) { 134 processorMap.remove(processorUri); 135 ProcessorDescriptor processorDescriptor = getProcessorDescriptor(processorUri); 136 URI processorConfiguration = processorDescriptor.getConfiguration(); 137 if ( processorConfiguration != null ) { 138 configuredProcessors.remove(processorConfiguration); 139 Subscriber subscriber = (Subscriber)configurationListeners.get(processorConfiguration); 140 Projector.getRepository().unsubscribe(processorConfiguration, subscriber, Projector.getCredentials()); 141 configurationListeners.remove(processorConfiguration); 142 } 143 processorDescriptors.remove(processorUri); 144 logger.log(Level.FINE, "Removing processor: "+processorUri); 145 } 146 147 private void update(URI applicationUri, URI configurationUri) { 148 Projector.getRepository().unsubscribe(configurationUri, this, Projector.getCredentials()); 149 install(applicationUri, configurationUri); 150 } 151 152 public static ProcessorManager getInstance() { 153 return processorManager; 154 } 155 156 public void notify(String uri, Map information) { 157 URI configurationUri = new URIValue(uri); 158 update((URI)configurationToApplication.get(configurationUri), configurationUri); 159 } 160 161 public Processor getProcessor(URI uri) throws ProcessException { 162 if ( processorMap.containsKey(uri) ) { 163 return (Processor)processorMap.get(uri); 164 } 165 logger.log(Level.SEVERE, "Requested processor with URI=" + uri+ " not found!"); 166 throw new ProcessException(new ErrorMessage("processorNotFound", new Object [] {uri.toString()})); 167 } 168 169 public URI getURI(Processor processor) throws ProcessException { 170 for ( Iterator i = processorMap.entrySet().iterator(); i.hasNext(); ) { 171 Map.Entry entry = (Map.Entry )i.next(); 172 if ( entry.getValue() == processor ) { 173 return ((URI)entry.getKey()); 174 } 175 } 176 logger.log(Level.SEVERE, "Requested URI for processor=" + processor + " not found!"); 177 throw new ProcessException(new ErrorMessage("processorNotFound", new Object [] {processor.toString()})); 178 } 179 180 public Result process(URI processorUri, Map parameters, Context context) throws Exception { 181 Processor processor = getProcessor(processorUri); 182 return process(processor, parameters, context); 183 } 184 185 public static Result process(Processor processor, Map parameters, Context context) throws Exception { 186 ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors(); 187 prepareValues(parameterDescriptors, parameters, context); 188 return processor.process(parameters, context); 189 } 190 191 public Value process(URI simpleProcessorUri, Object input, Context context) throws Exception { 192 return process(simpleProcessorUri, input, null, context); 193 } 194 195 public Value process(URI simpleProcessorUri, Object input, String resultKey, Context context) throws Exception { 196 Processor processor = getProcessor(simpleProcessorUri); 197 ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors(); 198 if ( parameterDescriptors.length > 1 && countRequiredParameters(parameterDescriptors) > 1 ) { 199 throw new ProcessException(new ErrorMessage("valueProcessorNeedsTooManyParametersException")); 200 } 201 if ( resultKey == null ) { 202 ResultDescriptor resultDescriptor = processor.getResultDescriptor(); 203 if ( resultDescriptor.getResultEntryDescriptors().length == 0 ) { 204 throw new ProcessException(new ErrorMessage("parameterProcessingException", new String [] { simpleProcessorUri.toString() })); 205 } else { 206 resultKey = resultDescriptor.getResultEntryDescriptors()[0].getName(); 207 } 208 } 209 if ( input == null && parameterDescriptors.length == 1 && parameterDescriptors[0].isRequired()) { 210 throw new ProcessException(new ErrorMessage("requiredParameterMissing", new String []{parameterDescriptors[0].getName()})); 211 } else if ( input == null && parameterDescriptors.length > 1 ) { 212 ParameterDescriptor requiredParameter = getRequiredParameter(parameterDescriptors); 213 if ( requiredParameter != null ) throw new ProcessException(new ErrorMessage("requiredParameterMissing", new String []{ requiredParameter.getName()})); 214 } else { 215 try { 216 if ( processor instanceof EnvironmentConsumer ) { 218 Process.checkRequirements((EnvironmentConsumer)processor, context); 219 } 220 if ( processor instanceof SimpleProcessor ) { 221 Value preparedValue = prepareValue(parameterDescriptors[0], input, context); 222 input = ((SimpleProcessor)processor).process(preparedValue, context); 223 } else { 224 Map parameters = new HashMap (); 225 if ( parameterDescriptors.length == 1 ) { 226 parameters.put(parameterDescriptors[0].getName(), prepareValue(parameterDescriptors[0], input, context)); 227 } else { 228 for ( int i = 0; i < parameterDescriptors.length; i++ ) { 229 if ( parameterDescriptors[i].isRequired() ) { 230 parameters.put(parameterDescriptors[i].getName(), prepareValue(parameterDescriptors[i], input, context)); 231 } else { 232 parameters.put(parameterDescriptors[i].getName(), parameterDescriptors[i].getDefaultValue()); 233 } 234 } 235 236 } 237 Result processorResult = processor.process(parameters, context); 238 input = processorResult.getResultEntries().get(resultKey); 239 } 240 } catch ( Exception exception ) { 241 throw new ProcessException(new ErrorMessage("parameterProcessingException", new String [] { simpleProcessorUri.toString(), exception.getMessage() }), exception); 242 } 243 } 244 return (Value)input; 245 } 246 247 public static void prepareValues(ParameterDescriptor[] parameterDescriptors, Map parameters, Context context) throws Exception { 248 for ( int i = 0; i < parameterDescriptors.length; i++ ) { 249 String parameterName = parameterDescriptors[i].getName(); 250 Object parameterValue = parameters.get(parameterName); 251 Value preparedValue = prepareValue(parameterDescriptors[i], parameterValue, context); 252 parameters.put(parameterName, preparedValue); 253 } 254 } 255 256 public static Value prepareValue(ParameterDescriptor parameterDescriptor, Object value, Context context) throws Exception { 257 Value preparedValue; 258 if ( value instanceof AnyValue ) { 259 value = ((AnyValue)value).load(context); 260 } 261 if ( value == null || value instanceof NullValue ) { 262 if ( parameterDescriptor.isRequired() ) { 263 throw new ValidationException(new ErrorMessage("requiredParameterMissing", new String [] { parameterDescriptor.getName() })); 264 } else { 265 preparedValue = parameterDescriptor.getDefaultValue(); 266 } 267 } else { 268 preparedValue = parameterDescriptor.getValueDescriptor().valueOf(value, context); 269 parameterDescriptor.getValueDescriptor().validate(preparedValue, context); 270 } 271 return preparedValue; 272 } 273 274 public ProcessorDescriptor getProcessorDescriptor(URI uri) { 275 return (ProcessorDescriptor)processorDescriptors.get(uri); 276 } 277 278 public ProcessorDescriptor getProcessorDescriptor(Processor processor) { 279 for ( Iterator i = processorDescriptors.values().iterator(); i.hasNext(); ) { 280 ProcessorDescriptor processorDescriptor = (ProcessorDescriptor)i.next(); 281 if ( processorDescriptor.getProcessor() == processor ) return processorDescriptor; 282 } 283 return null; 284 } 285 286 private void registerProcessor(URI uri, Processor processor) { 287 } 288 289 private static int countRequiredParameters(ParameterDescriptor[] descriptors) { 290 int count = 0; 291 for ( int i = 0; i < descriptors.length; i++ ) { 292 if ( descriptors[i].isRequired() ) { 293 count++; 294 } 295 } 296 return count; 297 } 298 299 private static ParameterDescriptor getRequiredParameter(ParameterDescriptor[] descriptors) { 300 for ( int i = 0; i < descriptors.length; i++ ) { 301 if ( descriptors[i].isRequired() ) { 302 return descriptors[i]; 303 } 304 } 305 return null; 306 } 307 308 public class ConfigurationHandler extends DefaultSimpleImportHandler { 309 URI applicationUri; 310 List addedProcessors = new ArrayList (); 311 List removedProcessors = new ArrayList (); 312 313 public ConfigurationHandler(URI applicationUri, List installedProcessors) { 314 this.applicationUri = applicationUri; 315 removedProcessors.addAll(installedProcessors); 316 } 317 318 public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) { 319 if (path.matches("processor")) { 320 boolean modified = false, added = false; 321 URI uri = new URIValue(attributes.getValue("uri")); 322 removedProcessors.remove(uri); 323 String configURI = attributes.getValue("config-uri"); 324 String processorName = attributes.getValue("name"); 325 String descriptionKey = attributes.getValue("description"); 326 String smallIcon = attributes.getValue("small-icon"); 327 String largeIcon = attributes.getValue("large-icon"); 328 String clazz = attributes.getValue("class"); 329 String bookmark = attributes.getValue("bookmark"); 330 Processor processor = (Processor)processorMap.get(uri); 331 ProcessorDescriptor processorDescriptor = (ProcessorDescriptor)processorDescriptors.get(uri); 332 try { 333 if ( processor == null ) { 334 processor = (Processor)processorClassLoader.loadClass(clazz).getConstructor(new Class [0]).newInstance(new Object [0]); 335 added = true; 336 modified = true; 337 } 338 if ( processorDescriptor == null ) { 339 processorDescriptor = new ProcessorDescriptor(uri); 340 modified = true; 341 } 342 if ( processorName == null ) processorName = uri.toString(); 343 if ( processorDescriptor.getName() == null || !processorDescriptor.getName().equals(processorName) ) { 344 processorDescriptor.setName(processorName); 345 modified = true; 346 } 347 if ( descriptionKey == null ) { 348 descriptionKey = "processorManager/noProcessorDescriptionAvailable"; 349 } 350 DefaultMessage description = null; 351 if ( processorDescriptor.getDescription() == null || !processorDescriptor.getDescription().getId().equals(descriptionKey) ) { 352 description = new DefaultMessage(descriptionKey); 353 processorDescriptor.setDescription(description); 354 modified = true; 355 } 356 if ( processorDescriptor.getProcessor() != processor ) { 357 processorDescriptor.setProcessor(processor); 358 modified = true; 359 } 360 URI smallIconUri = SMALL_DEFAULT_ICON, largeIconUri = LARGE_DEFAULT_ICON; 361 if ( smallIcon != null ) smallIconUri = new URIValue(smallIcon); 362 if ( largeIcon != null ) largeIconUri = new URIValue(largeIcon); 363 if ( processorDescriptor.getSmallIcon() == null || !processorDescriptor.getSmallIcon().equals(smallIconUri) ) { 364 processorDescriptor.setSmallIcon(smallIconUri); 365 modified = true; 366 } 367 if ( processorDescriptor.getLargeIcon() == null || !processorDescriptor.getLargeIcon().equals(largeIconUri) ) { 368 processorDescriptor.setLargeIcon(largeIconUri); 369 modified = true; 370 } 371 if ( bookmark != null ) { 372 boolean isBookmark = Boolean.valueOf(bookmark).booleanValue(); 373 if ( processorDescriptor.isBookmark() != isBookmark ) { 374 processorDescriptor.setBookmark(isBookmark); 375 modified = true; 376 } 377 } 378 if ( processor instanceof ConfigurableProcessor && configURI != null ) { 379 if ( !configURI.startsWith("/") ) { 380 configURI = applicationUri.toString() + configURI; 381 } 382 URI configurationUri = new URIValue(configURI); 383 if ( processorDescriptor.getConfiguration() == null || !processorDescriptor.getConfiguration().equals(configurationUri) ) { 384 logger.log(Level.FINE, "Configuring processor with config-URI=" + configURI); 385 processorDescriptor.setConfiguration(configurationUri); 386 StreamableValue config = (StreamableValue)Projector.getRepository().getResource(configurationUri, Projector.getCredentials()); 387 ((ConfigurableProcessor)processor).configure(config); 388 Subscriber subscriber = new ConfigurationListener(); 390 Projector.getRepository().subscribe("Update", configurationUri, 0, subscriber, Projector.getCredentials()); 391 configurationListeners.put(configurationUri, subscriber); 392 configuredProcessors.put(configurationUri, processor); 393 modified = true; 394 } 395 } 396 if ( added ) { 397 logger.log(Level.FINE, "Adding processor with URI=" + uri); 398 addedProcessors.add(uri); 399 } 400 if ( modified ) { 401 logger.log(Level.FINE, "Updating processor with URI=" + uri); 402 processorMap.put(uri, processor); 403 processorDescriptors.put(uri, processorDescriptor); 404 } 405 } catch (Exception e) { 406 logger.log(Level.SEVERE, "Processor " + clazz + " could not be created or configured!", e); 407 } 408 } 409 } 410 411 List getAddedProcessors() { 412 return addedProcessors; 413 } 414 415 List getRemovedProcessors() { 416 return removedProcessors; 417 } 418 } 419 420 class ConfigurationListener implements Subscriber { 421 public void notify(String uri, Map information) { 422 URI processorUri = new URIValue(uri); 423 Processor processor = (Processor)configuredProcessors.get(processorUri); 424 logger.log(Level.FINE, "Reloading processor with configuration URI='"+uri+"'"); 425 try { 426 StreamableValue config = (StreamableValue)Projector.getRepository().getResource(processorUri, Projector.getCredentials()); 427 ((ConfigurableProcessor)processor).configure(config); 428 } catch ( IOException e ) { 429 logger.log(Level.SEVERE, "Configuration resource with URI='"+uri+"' could not be loaded!", e); 430 } catch ( ConfigurationException e ) { 431 logger.log(Level.SEVERE, "Processor with configuration URI='" + uri + "' could not be reloaded! Configuration resource might be invalid!", e); 432 } 433 } 434 } 435 436 class ConfiguredProcessor { 437 private String configUri; 438 private URI processorUri; 439 440 public ConfiguredProcessor(String configUri, URI processorUri) { 441 this.configUri = configUri; 442 this.processorUri = processorUri; 443 } 444 445 public String getConfigUri() { 446 return configUri; 447 } 448 449 public URI getProcessorUri() { 450 return processorUri; 451 } 452 } 453 } | Popular Tags |