Package net.sourceforge.javautil.web.server.application.impl

Source Code of net.sourceforge.javautil.web.server.application.impl.WebApplicationAbstract$DetachedWebXml

package net.sourceforge.javautil.web.server.application.impl;

import java.io.IOException;
import java.net.URL;
import java.security.Principal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sourceforge.javautil.classloader.impl.ClassContext;
import net.sourceforge.javautil.classloader.impl.StandardClassLoaderHeiarchy;
import net.sourceforge.javautil.classloader.resolver.IClassDependencyPool;
import net.sourceforge.javautil.classloader.resolver.ClassPackageContext;
import net.sourceforge.javautil.classloader.resolver.IClassPackageDependencyReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackageDescriptor;
import net.sourceforge.javautil.classloader.resolver.IClassDependencyPool.PoolScope;
import net.sourceforge.javautil.classloader.resolver.impl.ClassDependencyPoolImpl;
import net.sourceforge.javautil.classloader.resolver.impl.maven.ProjectObjectModel;
import net.sourceforge.javautil.classloader.source.ClassSource;
import net.sourceforge.javautil.classloader.source.ClassSourceScanner;
import net.sourceforge.javautil.classloader.source.CompositeClassSource;
import net.sourceforge.javautil.classloader.source.ClassSourceScanner.ClassSourceMatch;
import net.sourceforge.javautil.classloader.source.ClassSourceVisitorContext.Type;
import net.sourceforge.javautil.classloader.util.ClassPackageUtil;
import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.io.IModifiableInputSource;
import net.sourceforge.javautil.common.io.VirtualArtifactNotFoundException;
import net.sourceforge.javautil.common.io.VirtualArtifactSystem;
import net.sourceforge.javautil.common.io.IVirtualDirectory;
import net.sourceforge.javautil.common.io.impl.Directory;
import net.sourceforge.javautil.common.io.impl.DirectoryRoot;
import net.sourceforge.javautil.common.proxy.DetachedProxy;
import net.sourceforge.javautil.common.proxy.IDetachedProxySource;
import net.sourceforge.javautil.common.proxy.RecursiveInterface;
import net.sourceforge.javautil.common.reflection.cache.ClassCache;
import net.sourceforge.javautil.common.reflection.cache.ClassDescriptor;
import net.sourceforge.javautil.common.xml.XMLDocument;
import net.sourceforge.javautil.common.xml.annotation.XmlTag;
import net.sourceforge.javautil.web.server.application.IWebApplication;
import net.sourceforge.javautil.web.server.application.WebApplicationAuthenticator;
import net.sourceforge.javautil.web.server.application.WebApplicationAuxilaryDescriptorLocation;
import net.sourceforge.javautil.web.server.application.WebApplicationDeploymentContext;
import net.sourceforge.javautil.web.server.application.IWebApplicationResourceResolver;
import net.sourceforge.javautil.web.server.application.ext.IWebApplicationExtension;
import net.sourceforge.javautil.web.server.application.ext.WebApplicationExtensionAbstract;
import net.sourceforge.javautil.web.server.deployer.WebApplicationServerDescriptor;
import net.sourceforge.javautil.web.server.descriptor.IWebXml;
import net.sourceforge.javautil.web.server.descriptor.impl.WebXml;

/**
* This provides a base for most standard {@link IWebApplication}
* implementations, providing common functionality.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: WebApplicationAbstract.java 2747 2011-02-05 04:30:12Z ponderator $
*/
public abstract class WebApplicationAbstract implements IWebApplication {
 
  protected final String name;
  protected final String path;
  protected final Logger log = LoggerFactory.getLogger(getClass().getName());
 
  protected Map<String, String> authenticators = new LinkedHashMap<String, String>();
  protected Map<String, ExtensionDefinition> extensions = new LinkedHashMap<String, ExtensionDefinition>();
 
  protected List<WebApplicationAuthenticator> loadedAuthenticators = new ArrayList<WebApplicationAuthenticator>();
  protected List<IWebApplicationExtension> loadedExtensions = new ArrayList<IWebApplicationExtension>();
 
  protected List<Object> auxiliaryDescriptors = new ArrayList<Object>();
 
  protected WebXml webXml;
  protected IWebXml readOnlyWebXml;
 
  protected VirtualArtifactSystem vasRoot;
  protected IWebApplicationResourceResolver resolver;
 
  protected ClassLoader parentClassLoader;
  protected ClassContext classContext;
  protected IVirtualDirectory root;
 
  protected boolean reloadable = true;
 
  protected WebApplicationServerDescriptor descriptor;
 
  public WebApplicationAbstract(String name, String path, IVirtualDirectory root) {
    this.name = name;
    this.path = path;
   
    this.vasRoot = VirtualArtifactSystem.get("net.sf.javautil.web.server.application." + name, true);
    this.resolver = new VirtualDirectoryResolver(vasRoot);
   
    this.root = root;
    this.readOnlyWebXml = DetachedProxy.create(getClass().getClassLoader(),
        new Class[] { IWebXml.class }, IWebXml.class, new DetachedWebXml(), new RecursiveInterface());
   
  }
 
  public ClassLoader getParentClassLoader() { return parentClassLoader; }
  public void setParentClassLoader(ClassLoader parentClassLoader) { this.parentClassLoader = parentClassLoader; }

  public boolean isReloadable() { return reloadable; }
  public void setReloadable(boolean reloadable) { this.reloadable = reloadable; }

  public void addExtension (String name, String extensionClassName, Map<String, Object> settings) {
    this.extensions.put(name, new ExtensionDefinition(name, extensionClassName, settings));
  }
 
  public void addAuthenticator (String name, String authenticatorClassName) {
    this.authenticators.put(name, authenticatorClassName);
  }

  public IVirtualDirectory getRoot() { return root; }

  public ClassContext getClassLoader() { return this.classContext; }
 
  public boolean hasBeenModifiedSince(long timestamp) {
    return this.classContext != null && this.classContext.getAllSources().getLastModifiedClass() > timestamp;
  }

  public IWebXml getWebXml() { return this.readOnlyWebXml; }
 
  public List<WebApplicationAuthenticator> getAuthenticators() {
    return new ArrayList<WebApplicationAuthenticator>(this.loadedAuthenticators);
  }

  public List<IWebApplicationExtension> getExtensions() {
    return new ArrayList<IWebApplicationExtension>(this.loadedExtensions);
  }

  public String getContextPath() { return this.path; }

  public String getName() { return name; }

  public IWebApplicationResourceResolver getResourceResolver() { return this.resolver; }
 
  public String getWebXmlAsXml() {
    return webXml == null ? null : webXml.toXML();
  }

  public void postUndeployCleanup(WebApplicationDeploymentContext ctx, boolean reload) {
    ctx.getHost().preCleanup(this);
   
    for (IWebApplicationExtension extension : this.loadedExtensions) {
      extension.cleanup(ctx);
    }
   
    this.webXml = null;
    this.loadedAuthenticators.clear();
    this.loadedExtensions.clear();
    if (this.classContext != null && !reload) {
      this.classContext.cleanup();
      this.classContext = null;
    }
   
    if (this.root instanceof DirectoryRoot && !reload) {
      VirtualArtifactSystem vas = VirtualArtifactSystem.get("net.sf.javautil.web.server." + ctx.getHost().getName() + "." + getName(), false);
      if (vas != null) vas.unlink(this.root.getPath());
    }
  }

  public void preDeploySetup(WebApplicationDeploymentContext ctx, boolean reload) {
    if (this.resolver == null)
      throw new IllegalStateException("Cannot call predeploy setup before initializing the resolver");
   
    vasRoot.link(this.root);
   
    this.classContext = new WebApplicationClassLoader(ctx);
    this.classContext.setPool(ClassPackageUtil.createStandardDependencyPool("Web Application Pool: " + this.getName(), true, PoolScope.Root));
    this.classContext.getAllSources().refresh();
   
    for (String name : this.authenticators.keySet()) {
      ClassDescriptor<? extends WebApplicationAuthenticator> cd = ClassCache.getFor(ReflectionUtil.getClass(this.authenticators.get(name), this.classContext));
      this.loadedAuthenticators.add(cd.newInstance());
    }
   
    this.descriptor = this.getAuxilaryDescriptor(WebApplicationServerDescriptor.class);
    if (this.descriptor != null) {
      this.setReloadable(this.descriptor.isAutoRestart());
    }
   
    this.initializeWebXml();
    IClassDependencyPool pool = this.classContext.getPool();
   
    this.loadExtension(ctx, pool, new MavenExtension(name, this));
   
    for (String name : this.extensions.keySet()) {
      ClassDescriptor cd = ClassCache.getFor(ReflectionUtil.getClass(this.extensions.get(name).className, this.classContext));

      if (this.isExtensionLoaded(cd.getDescribedClass())) continue;
     
      IWebApplicationExtension extension = (IWebApplicationExtension) cd.newInstance(this);
     
      if (!extension.shouldLoad(webXml)) continue;
     
      this.loadedExtensions.add(extension);
      if (this.extensions.get(name).settings != null) {
        cd.deserializeProperties(extension, this.extensions.get(name).settings);
      }
     
      pool = this.loadExtension(ctx, pool, extension);
    }
   
    ctx.getHost().postSetup(this, webXml);
  }
 
  /**
   * @param ctx The context in which this application is being deployed
   * @param pool The pool for
   */
  protected IClassDependencyPool loadExtension (WebApplicationDeploymentContext ctx, IClassDependencyPool pool, IWebApplicationExtension extension) {
    log.info("Loading extension: " + extension.getName());
   
    extension.setup(webXml, ctx);
   
    List<? extends IClassPackageDependencyReference> wdd = extension.getClassPackageDependencies();
    if (wdd != null && wdd.size() > 0) {
      pool = pool.createChild("Web Application Dependency: " + extension.getName(), PoolScope.Component);
      ClassPackageUtil.append(pool, ClassPackageContext.getPackageResolver(),
        extension.isArePrimaryDependencies(), extension.getDescriptor(),
        wdd.toArray(new IClassPackageDependencyReference[wdd.size()])
      );
    }
   
    CompositeClassSource ccs = extension.getNonClassPackageDependencies();
    if (ccs != null) {
      this.classContext.getNonPackageSources().add(ccs);
      this.loadDynamicExtensions(ctx, pool, new CompositeClassSource(ccs, pool.getCompositeClassSource()));
    } else if (wdd != null && wdd.size() > 0) {
      this.loadDynamicExtensions(ctx, pool, pool.getCompositeClassSource());
    }
   
    return pool;
  }
 
  /**
   * @param ctx The context in which we are deploying
   * @param pool The current pool for dependency resolution
   * @param source The source to load dynamic extensions for
   */
  public void loadDynamicExtensions (WebApplicationDeploymentContext ctx, IClassDependencyPool pool, ClassSource source) {
    for (IWebApplicationExtension extension : this.findNewExtensions(source)) {
      this.loadExtension(ctx, pool, extension);
    }
  }
 
  /**
   * @param source The source to search for dynamic extensions
   * @return A list, possibly empty, of extensions found in the source
   */
  public List<IWebApplicationExtension> findNewExtensions (ClassSource source) {
    List<IWebApplicationExtension> extensions = new ArrayList<IWebApplicationExtension>();
    for (ClassSourceMatch match : source.accept(new ClassSourceScanner("webserver.properties").addSuffixes("WebExtension")).getMatches()) {
      if (match.getType() == Type.Resource) continue;
      try {
        ClassDescriptor eclass = ClassCache.getFor( classContext.loadClass(match.getName()) );
        if (!this.isExtensionLoaded(eclass.getDescribedClass())) {
         
          boolean load = true;
          IWebApplicationExtension replace = null;
          for (IWebApplicationExtension ext : extensions) {
            if (eclass.getDescribedClass().isAssignableFrom(ext.getClass())) { load = false; break; }
            if (ext.getClass().isAssignableFrom(eclass.getDescribedClass())) {
              replace = ext; break;
            }
          }
          if (!load) continue;
          if (replace != null) { extensions.remove(replace); }
         
          IWebApplicationExtension extension = (IWebApplicationExtension) eclass.newInstance(this);
          extensions.add(extension);
         
          if (this.descriptor != null && this.descriptor.getDescriptorFor(extension) != null) {
            if (this.descriptor.getDescriptorFor(extension).getSettings() != null)
              eclass.deserializeProperties(extension, this.descriptor.getDescriptorFor(extension).getSettings());
          }
        }
      } catch (ClassNotFoundException e) {
        ThrowableManagerRegistry.caught(e);
      }
    }
    return extensions;
  }
 
  /**
   * @param type The type to check for
   * @return True if an extension that is of the type or a sub type is already loaded, otherwise false
   */
  public boolean isExtensionLoaded (Class<? extends IWebApplicationExtension> type) {
    for (IWebApplicationExtension extension : this.loadedExtensions) {
      if (type.isAssignableFrom(extension.getClass())) return true;
    }
    return false;
  }
 
  /**
   * If a descriptor has already been retreived it can be manually
   * added here for later retrieval.
   *
   * @param descriptor The descriptor to add
   */
  public void addAuxilaryDescriptor (Object descriptor) {
    this.auxiliaryDescriptors.add(descriptor);
  }

  public <T> T getAuxilaryDescriptor(Class<T> type) {
    String path = null;
    WebApplicationAuxilaryDescriptorLocation waadl = type.getAnnotation(WebApplicationAuxilaryDescriptorLocation.class);
    if (waadl != null) {
      path = waadl.relativeLocation();
    } else {
      XmlTag tag = type.getAnnotation(XmlTag.class);
      if (tag != null && !"".equals(tag.name())) {
        path = "WEB-INF/" + tag.name() + ".xml";
      } else {
        path = "WEB-INF/" + type.getSimpleName() + ".xml";
      }
    }
    return this.getAuxilaryDescriptor(path, type);
  }

  public <T> T getAuxilaryDescriptor(String path, Class<T> type) {
    T descriptor = this.findAuxiliaryDescriptor(type);
    if (descriptor == null) {
      URL url = this.getResourceResolver().getResource(path);
      if (url != null)
        descriptor = XMLDocument.read(url, type);
     
      if (descriptor != null)
        this.auxiliaryDescriptors.add(descriptor);
    }
    return descriptor;
  }

  public void setup(ServletContext ctx) {}

  public void cleanup(ServletContext ctx) {}

  public void log(String msg) { log.info(msg); }

  public void log(String msg, Throwable t) {
    log.error(msg + ": " + t.getMessage());
    t.printStackTrace();
  }
 
  public String toString () { return getClass().getSimpleName() + "[ " + this.name + ", path: " + this.path + " ]"; }
 
  /**
   * @param <T> The type of descriptor
   * @param type The descriptor class
   * @return The instance that is of the type or a sub type of the type specified
   */
  protected <T> T findAuxiliaryDescriptor (Class<T> type) {
    for (Object ad : this.auxiliaryDescriptors) {
      if (type.isAssignableFrom(ad.getClass())) return (T) ad;
    }
    return null;
  }
 
  /**
   * Initialize the web.xml
   */
  protected void initializeWebXml () {
    if (this.webXml == null) {
      URL webXmlURL = this.resolver.getResource("WEB-INF/web.xml");
      this.webXml = webXmlURL == null ? new WebXml() : WebXml.getInstance(webXmlURL);
    }
  }
 
  /**
   * This will allow access to the web.xml help internally for the
   * {@link DetachedProxy} making the web.xml read-only.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: WebApplicationAbstract.java 2747 2011-02-05 04:30:12Z ponderator $
   */
  private class DetachedWebXml implements IDetachedProxySource {
   
    public <T> T getInstance(Class<T> type) {
      return type == IWebXml.class ? (T) webXml : null;
    }
   
  }
 
  /**
   * The composite information about an extension that should be loaded and executed
   * at predeployment.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: WebApplicationAbstract.java 2747 2011-02-05 04:30:12Z ponderator $
   */
  private class ExtensionDefinition {
   
    protected String name;
    protected String className;
    protected Map<String, Object> settings;
   
    public ExtensionDefinition(String name, String className, Map<String, Object> settings) {
      this.name = name;
      this.className = className;
      this.settings = settings;
    }
   
  }
 
  /**
   * This will cause the standard WEB-INF/pom.xml to be recognized for class loaders.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: WebApplicationAbstract.java 2747 2011-02-05 04:30:12Z ponderator $
   */
  public static class MavenExtension extends WebApplicationExtensionAbstract {
   
    protected ProjectObjectModel pom;

    public MavenExtension(String name, IWebApplication application) {
      super(name, application);
    }

    @Override public boolean isArePrimaryDependencies() { return true; }

    @Override public List<? extends IClassPackageDependencyReference> getClassPackageDependencies() {
      if (this.getDescriptor() != null) {
        return this.getDescriptor().getDependencies(net.sourceforge.javautil.classloader.resolver.IClassDependency.Scope.Runtime);
      }
      return super.getClassPackageDependencies();
    }

    @Override public ProjectObjectModel getDescriptor() {
      if (this.pom == null) {
        URL pomURL = this.application.getResourceResolver().getResource("WEB-INF/pom.xml");
        if (pomURL != null) {
          IModifiableInputSource input = new IModifiableInputSource.URLInputSource(pomURL);
          pom = ProjectObjectModel.parse(ClassPackageContext.getPackageResolver(), input);
        }
      }
      return pom;
    }

  }

}
TOP

Related Classes of net.sourceforge.javautil.web.server.application.impl.WebApplicationAbstract$DetachedWebXml

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.