1 package org.apache.slide.projector.application; 2 3 import java.io.IOException ; 4 import java.io.InputStream ; 5 import java.util.ArrayList ; 6 import java.util.Collection ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 import java.util.logging.Level ; 12 import java.util.logging.Logger ; 13 14 import javax.xml.parsers.ParserConfigurationException ; 15 16 import org.apache.slide.projector.Context; 17 import org.apache.slide.projector.Projector; 18 import org.apache.slide.projector.SystemContext; 19 import org.apache.slide.projector.URI; 20 import org.apache.slide.projector.descriptor.ValueFactory; 21 import org.apache.slide.projector.descriptor.ValueFactoryManager; 22 import org.apache.slide.projector.engine.ProcessorManager; 23 import org.apache.slide.projector.engine.ProjectorClassLoader; 24 import org.apache.slide.projector.engine.Scheduler; 25 import org.apache.slide.projector.i18n.MessageManager; 26 import org.apache.slide.projector.value.ArrayValue; 27 import org.apache.slide.projector.value.StreamableValue; 28 import org.apache.slide.projector.value.URIValue; 29 import org.apache.slide.projector.value.Value; 30 import org.apache.webdav.lib.Subscriber; 31 import org.xml.sax.InputSource ; 32 import org.xml.sax.SAXException ; 33 import org.xml.sax.helpers.AttributesImpl ; 34 35 import de.zeigermann.xml.simpleImporter.DefaultSimpleImportHandler; 36 import de.zeigermann.xml.simpleImporter.SimpleImporter; 37 import de.zeigermann.xml.simpleImporter.SimplePath; 38 39 public class ApplicationManager { 40 private final static Logger logger = Logger.getLogger(ApplicationManager.class.getName()); 41 42 private final static String APPLICATION_CONFIG = "application.xml"; 43 private final static Context context = new SystemContext(); 44 private final static String CLASSES_DIR = "classes/"; 45 46 private static ApplicationManager applicationManager; 47 private List applicationListeners = new ArrayList (); 48 private Map installedApplications = new HashMap (); private ProjectorClassLoader factoryClassLoader = new ProjectorClassLoader(this.getClass().getClassLoader(), new URIValue(Projector.getProjectorDir()+CLASSES_DIR)); 51 52 private ApplicationManager() { 53 logger.log(Level.INFO, "Starting application manager"); 54 Projector.getRepository().subscribe("Update/newmember", new URIValue(Projector.getApplicationsDir()), 1, 55 new Subscriber() { 56 public void notify(String uri, Map information) { 57 logger.log(Level.FINE, "Package manager received add event"); 58 applicationManager.installApplications(); 59 } 60 }, context.getCredentials()); 61 Projector.getRepository().subscribe("Delete", new URIValue(Projector.getApplicationsDir()), 1, 62 new Subscriber() { 63 public void notify(String uri, Map information) { 64 logger.log(Level.FINE, "Package manager received delete event"); 65 applicationManager.installApplications(); 66 } 67 }, context.getCredentials()); 68 applicationListeners.add(ProcessorManager.getInstance()); 69 applicationListeners.add(MessageManager.getInstance()); 70 applicationListeners.add(Scheduler.getInstance()); 71 installApplications(); 72 } 73 74 private synchronized void installApplications() { 75 Value[] applicationUris; 76 List applicationsToInstall = new ArrayList (); 77 List applicationsToRemove = new ArrayList (); 78 try { 79 List removedApplications = new ArrayList (); 80 removedApplications.addAll(installedApplications.keySet()); 81 applicationUris = ((ArrayValue)Projector.getRepository().getChildren(new URIValue(Projector.getApplicationsDir()), context.getCredentials())).getArray(); 82 for ( int i = 0; i < applicationUris.length; i++ ) { 83 String applicationUri = applicationUris[i].toString(); 84 if ( !applicationUri.endsWith("/") ) { 85 applicationUri = applicationUri + "/"; 86 } 87 92 if ( !installedApplications.containsKey(applicationUri) ) { 93 Application installedApplication = parseApplication(new URIValue(applicationUri)); 94 if ( installedApplication != null ) { 95 applicationsToInstall.add(installedApplication); 96 } 97 } else { 98 logger.log(Level.FINE, "Application '"+applicationUri+"' already installed"); 99 removedApplications.remove(applicationUri); 100 } 101 } 102 for ( Iterator i = removedApplications.iterator(); i.hasNext(); ) { 103 Application removedApplication = (Application)installedApplications.get((URI)i.next()); 104 applicationsToRemove.add(removedApplication); 105 } 106 List sortedApplications = sortApplications(applicationsToInstall); 108 for ( Iterator i = sortedApplications.iterator(); i.hasNext(); ) { 109 Application application = (Application)i.next(); 110 Projector.getRepository().subscribe("Update", application.getUri(), 0, 111 new Subscriber() { 112 public void notify(String uri, Map information) { 113 applicationManager.updateApplication(uri); 114 } 115 }, context.getCredentials()); 116 install(Application.MESSAGES, application); 117 install(Application.PROCESSORS, application); 118 } 119 Scheduler.getInstance().install(new URIValue(Projector.getWorkDir() + Scheduler.JOBS), true); 120 for ( Iterator i = sortedApplications.iterator(); i.hasNext(); ) { 121 Application application = (Application)i.next(); 122 install(Application.JOBS, application); 123 } 124 Scheduler.getInstance().saveJobs(); 125 } catch (IOException e) { 126 logger.log(Level.SEVERE, "Could not determine installed applications!", e); 127 } 128 } 129 130 public static ApplicationManager getInstance() { 131 if ( applicationManager == null ) { 132 applicationManager = new ApplicationManager(); 133 } 134 return applicationManager; 135 } 136 137 private List sortApplications(List applicationsToInstall) { 138 List sortedApplications = new ArrayList (); 139 for ( Iterator i = applicationsToInstall.iterator(); i.hasNext(); ) { 140 Application application = (Application)i.next(); 141 if ( !sortedApplications.contains(application) ) { 142 logger.log(Level.FINE, "Try to install '"+application.getName()+"'"); 143 addRequiredApplicationsFirst(sortedApplications, applicationsToInstall, application); 144 } 145 } 146 return sortedApplications; 147 } 148 149 private void addRequiredApplicationsFirst(List sortedApplications, List applicationsToInstall, Application application) { 150 logger.log(Level.FINE, "Checking for dependencies..."); 152 for ( Iterator i = application.getDependencies().iterator(); i.hasNext(); ) { 153 Dependency dependency = (Dependency)i.next(); 154 logger.log(Level.FINE, "Dependency on application '"+dependency.getRequiredApplication()+"' found!"); 155 Application requiredApplication = getApplicationByName(applicationsToInstall, dependency.getRequiredApplication()); 156 if ( requiredApplication == null ) { 157 requiredApplication = getApplicationByName(installedApplications.entrySet(), dependency.getRequiredApplication()); 159 if ( requiredApplication == null ) { 160 logger.log(Level.SEVERE, "Required application '"+dependency.getRequiredApplication()+"' not found!"); 162 } 163 } else { 164 logger.log(Level.FINE, "Required application '"+requiredApplication.getName()+"' not installed but available, so install it first"); 165 addRequiredApplicationsFirst(sortedApplications, applicationsToInstall, requiredApplication); 166 } 167 } 168 if ( !sortedApplications.contains(application) ) { 169 logger.log(Level.FINE, "Adding '"+application.getName()+"' to installation process"); 170 sortedApplications.add(application); 171 } 172 } 173 174 private Application getApplicationByName(Collection applications, String name) { 175 for ( Iterator i = applications.iterator(); i.hasNext(); ) { 176 Application application = (Application)i.next(); 177 if ( application.getName().equals(name)) { 178 return application; 179 } 180 } 181 return null; 182 } 183 184 private Application parseApplication(URI applicationUri) { 185 try { 186 SimpleImporter importer = new SimpleImporter(); 187 URI applicationDefinition = new URIValue(applicationUri.toString()+APPLICATION_CONFIG); 188 StreamableValue applicationDefinitionResouce = ((StreamableValue)Projector.getRepository().getResource(applicationDefinition, context.getCredentials())); 189 if ( applicationDefinitionResouce != null ) { 190 InputStream configuration = applicationDefinitionResouce.getInputStream(); 191 ConfigurationHandler handler = new ConfigurationHandler(applicationUri); 192 importer.addSimpleImportHandler(handler); 193 importer.parse(new InputSource (configuration)); 194 return handler.getApplication(); 195 } else { 196 logger.log(Level.SEVERE, "Application definition (application.xml) not found in directory '"+applicationUri+"'. Application will not be installed!"); 197 } 198 } catch (ParserConfigurationException e) { 199 logger.log(Level.SEVERE, "Exception while parsing application configuration. Skipping installation...", e); 200 } catch (SAXException e) { 201 logger.log(Level.SEVERE, "Exception while parsing application configuration. Skipping installation...", e); 202 } catch (IOException e) { 203 logger.log(Level.SEVERE, "Could not get application information. Skipping installation...", e); 204 } 205 return null; 206 } 207 208 private Application getApplication(List applications, URI applicationUri) { 209 for ( Iterator i = applications.iterator(); i.hasNext(); ) { 210 Application application = (Application)i.next(); 211 if ( application.getUri().equals(applicationUri) ) return application; 212 } 213 return null; 214 } 215 216 private synchronized void updateApplication(String uri) { 217 URI applicationUri = new URIValue(uri); 218 logger.log(Level.FINE, "Updating application '"+applicationUri+"'"); 219 Application installedApplication = (Application)installedApplications.get(applicationUri); 221 Application updatedApplication = parseApplication(applicationUri); 222 for ( Iterator i = installedApplication.getContent().entrySet().iterator(); i.hasNext(); ) { 223 Map.Entry entry = (Map.Entry )i.next(); 224 List removed = new ArrayList (); 225 removed.addAll((List )entry.getValue()); 226 List updated = updatedApplication.getContent((String )entry.getKey()); 227 if ( updated != null ) { 228 removed.removeAll(updated); 229 } 230 for ( Iterator j = removed.iterator(); j.hasNext(); ) { 231 for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) { 232 ((ApplicationListener)k.next()).uninstall((String )entry.getKey(), updatedApplication.getUri(), (URI)j.next()); 233 } 234 } 235 } 236 for ( Iterator i = updatedApplication.getContent().entrySet().iterator(); i.hasNext(); ) { 237 Map.Entry entry = (Map.Entry )i.next(); 238 List added = new ArrayList (); 239 added.addAll((List )entry.getValue()); 240 List installed = installedApplication.getContent((String )entry.getKey()); 241 if ( installed != null ) { 242 added.removeAll(installed); 243 } 244 for ( Iterator j = added.iterator(); j.hasNext(); ) { 245 for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) { 246 ((ApplicationListener)k.next()).install((String )entry.getKey(), updatedApplication.getUri(), (URI)j.next()); 247 } 248 } 249 } 250 } 251 252 private void install(String type, Application application) { 253 logger.log(Level.FINE, "Installing "+type+" of application '"+application.getUri()+"'"); 254 List contents = (List )application.getContent().get(type); 255 if ( contents != null ) { 256 for ( Iterator j = contents.iterator(); j.hasNext(); ) { 257 URI uri = (URI)j.next(); 258 for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) { 259 ((ApplicationListener)k.next()).install(type, application.getUri(), uri); 260 } 261 } 262 } 263 installedApplications.put(application.getUri(), application); 264 } 265 266 private void uninstall(String type, Application application) { 267 logger.log(Level.FINE, "Uninstall "+type+" of application '"+application.getUri()+"'"); 268 for ( Iterator i = application.getContent().entrySet().iterator(); i.hasNext(); ) { 269 Map.Entry entry = (Map.Entry )i.next(); 270 for ( Iterator j = ((List )entry.getValue()).iterator(); j.hasNext(); ) { 271 URI uri = (URI)j.next(); 272 for ( Iterator k = applicationListeners.iterator(); k.hasNext(); ) { 273 ((ApplicationListener)k.next()).uninstall((String )entry.getKey(), application.getUri(), uri); 274 } 275 } 276 } 277 installedApplications.remove(application.getUri()); 279 } 280 281 private final class ConfigurationHandler extends DefaultSimpleImportHandler { 282 private Application application; 283 private URI applicationUri; 284 285 private ConfigurationHandler(URI applicationUri) { 286 this.applicationUri = applicationUri; 287 } 288 289 private Application getApplication() { 290 return application; 291 } 292 293 public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) { 294 if (path.matches("application")) { 295 application = new Application(applicationUri); 296 } else if ( path.matches("application/name") ) { 297 application.setName(leadingCDdata); 298 } else if ( path.matches("application/display-name") ) { 299 application.setDisplayName(leadingCDdata); 300 } else if ( path.matches("application/vendor") ) { 301 application.setVendor(leadingCDdata); 302 } else if ( path.matches("application/description") ) { 303 application.setDescription(leadingCDdata); 304 } else if ( path.matches("application/version") ) { 305 application.setVersion(leadingCDdata); 306 } else if ( path.matches("application/dependencies/requires") ) { 307 Dependency dependency = new Dependency(attributes.getValue("application"), attributes.getValue("version")); 308 application.addDependency(dependency); 309 } else if ( path.matches("application/resource-types/resource-type") ) { 310 String resourceTypeName = attributes.getValue("name"); 311 String clazz = attributes.getValue("class"); 312 try { 313 ValueFactory descriptorFactory = (ValueFactory)factoryClassLoader.loadClass(clazz).getConstructor(new Class [0]).newInstance(new Object [0]); 314 ValueFactoryManager.getInstance().registerDescriptorFactory(descriptorFactory); 315 logger.log(Level.FINE, "Successfully registered descriptor factory " + clazz); 316 } catch (Exception e) { 317 logger.log(Level.SEVERE, "Descriptor factory " + clazz + " could not loaded!", e); 318 } 319 } else if ( path.matches("application/content/processors") ) { 320 String uri = attributes.getValue("uri"); 321 application.addContent(Application.PROCESSORS, new URIValue(applicationUri+attributes.getValue("uri"))); 322 } else if ( path.matches("application/content/messages") ) { 323 application.addContent(Application.MESSAGES, new URIValue(applicationUri+attributes.getValue("uri"))); 324 } else if ( path.matches("application/content/jobs") ) { 325 application.addContent(Application.JOBS, new URIValue(applicationUri+attributes.getValue("uri"))); 326 } 327 } 328 } 329 } | Popular Tags |