ALCWebFilter.java :  » REST » alc-rest » org » allcolor » alc » webapp » Java Open Source

Java Open Source » REST » alc rest 
alc rest » org » allcolor » alc » webapp » ALCWebFilter.java
/**
 * ALC-Rest. Copyright
 * (C) 2009 Quentin Anciaux
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.allcolor.alc.webapp;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.UUID;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.allcolor.alc.config.ConfigMerger;
import org.allcolor.alc.config.ConfigMergerImpl;
import org.allcolor.alc.filesystem.Directory;
import org.allcolor.alc.filesystem.File;
import org.allcolor.alc.filesystem.FileSystem;
import org.allcolor.alc.filesystem.FileSystemElement;
import org.allcolor.alc.filesystem.FileSystemType;
import org.allcolor.alc.filesystem.classloader.FileSystemClassLoader;
import org.allcolor.alc.reflect.Dynamic;
import org.allcolor.alc.utils.io.ReaderUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
 * DOCUMENT ME!
 * 
 * @author Quentin Anciaux
 * @version $Revision$
 */
public class ALCWebFilter implements Filter {
  // ~ Static fields/initializers
  // -----------------------------------------------

  private static final Logger LOG = Logger.getLogger(ALCWebFilter.class);
  
  /**
   * DOCUMENT ME!
   * 
   * @author Quentin Anciaux
   * @version $Revision$
   */
  public static class ALCManifest {
    // ~ Instance fields
    // --------------------------------------------------------

    /**
     * DOCUMENT ME!
     */
    private final List<ALCManifest> dependencies = new ArrayList<ALCManifest>();

    /** DOCUMENT ME! */
    private final FileSystemElement file;

    private List<ALCManifest> fullDependencies = null;

    /** DOCUMENT ME! */
    private final YPackage main;

    // ~ Constructors
    // -----------------------------------------------------------

    private final Manifest manifest;

    /**
     * @param file
     * @param fullDependencies
     * @param manifest
     * @param main
     */
    public ALCManifest(final FileSystemElement file,
        final Manifest manifest, final YPackage main) {
      super();
      this.file = file;
      this.manifest = manifest;
      this.main = main;
    }

    /**
     * DOCUMENT ME!
     * 
     * @param p
     *            DOCUMENT ME!
     */
    private void addDependency(final ALCManifest p) {
      this.dependencies.add(p);
    } // end addDependency()

    private List<ALCManifest> constructDependenciesList(
        final ALCManifest manifest) {
      final List<ALCManifest> list = new ArrayList<ALCManifest>();
      this.constructDependenciesList(manifest, list);
      return list;
    }

    private void constructDependenciesList(final ALCManifest manifest,
        final List<ALCManifest> list) {
      for (final ALCManifest mf : manifest.getPartialDependenciesList()) {
        if (!ALCWebFilter.containsALCManifest(list, mf, false)) {
          list.add(mf);
          this.constructDependenciesList(mf, list);
        }
      }
    }

    public List<ALCManifest> getDependenciesList() {
      if (this.fullDependencies == null) {
        this.fullDependencies = Collections.unmodifiableList(this
            .constructDependenciesList(this));
      }
      return this.fullDependencies;
    }

    public FileSystemElement getJarFile() {
      return this.file;
    }

    // ~ Methods
    // ----------------------------------------------------------------

    public Manifest getManifest() {
      return this.manifest;
    }

    public YPackage getPackage() {
      return this.main;
    }

    private List<ALCManifest> getPartialDependenciesList() {
      return Collections.unmodifiableList(this.dependencies);
    }
  } // end DepXml

  // ~ Instance fields
  // ----------------------------------------------------------

  /**
   * @author Quentin Anciaux
   * @version $Revision$
   */
  private static interface MainFilter {
    // ~ Methods
    // ----------------------------------------------------------------

    // ~ Methods
    // ------------------------------------------------------------
    /**
     * DOCUMENT ME!
     */
    public abstract void destroy();

    /**
     * DOCUMENT ME!
     * 
     * @param request
     *            DOCUMENT ME!
     * @param response
     *            DOCUMENT ME!
     */
    public abstract void doFilter(final Object request,
        final Object response);

    /**
     * DOCUMENT ME!
     * 
     * @param unionWebappFS
     *            DOCUMENT ME!
     * @param contextName
     *            DOCUMENT ME!
     * 
     * @throws ServletException
     *             DOCUMENT ME!
     */
    public abstract void init(final FileSystem unionWebappFS,
        final String contextName) throws ServletException;
  } // end MainFilter

  /**
   * DOCUMENT ME!
   * 
   * @author Quentin Anciaux
   * @version $Revision$
   */
  public static class YPackage {
    // ~ Instance fields
    // --------------------------------------------------------

    private final String depends;

    private final String description;

    private final String license;

    private final String licenseText;

    /** DOCUMENT ME! */
    private final String packageName;

    private final String title;

    private final String vendor;

    /** DOCUMENT ME! */
    private final String version;

    // ~ Constructors
    // -----------------------------------------------------------

    /**
     * @param packageName
     * @param versionMajor
     * @param versionMinor
     * @param versionPatch
     * @param description
     * @param license
     * @param licenseText
     * @param vendor
     * @param title
     */
    private YPackage(final String packageName, final String version,
        final String depends, final String description,
        final String license, final String licenseText,
        final String vendor, final String title) {
      super();
      this.packageName = packageName;
      this.version = version;
      this.depends = depends;
      this.description = description;
      this.license = license;
      this.licenseText = licenseText;
      this.vendor = vendor;
      this.title = title;
    }

    public String getDepends() {
      return this.depends;
    }

    // ~ Methods
    // ----------------------------------------------------------------

    public String getDescription() {
      return this.description;
    }

    public String getLicense() {
      return this.license;
    }

    public String getLicenseText() {
      return this.licenseText;
    }

    public String getPackageName() {
      return this.packageName;
    }

    public String getTitle() {
      return this.title;
    }

    public String getVendor() {
      return this.vendor;
    }

    public String getVersion() {
      return this.version;
    }

    /**
     * DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     */
    @Override
    public String toString() {
      return this.packageName + " - version: " + this.version;
    } // end toString()
  } // end YPackage

  /** DOCUMENT ME! */
  private static FileSystemClassLoader fsClassLoader = null;

  private static ALCWebFilter handle = null;

  /**
   * DOCUMENT ME!
   * 
   * @param list
   *            DOCUMENT ME!
   * @param dx
   *            DOCUMENT ME!
   * @param noVersionCheck
   *            DOCUMENT ME!
   * 
   * @return DOCUMENT ME!
   */
  private static boolean containsALCManifest(final List<ALCManifest> list,
      final ALCManifest dx, final boolean noVersionCheck) {
    for (final ALCManifest dxm : list) {
      if ((noVersionCheck && dxm.main.packageName
          .equals(dx.main.packageName))
          || ((dxm.main.version.equals(dx.main.version)) && dxm.main.packageName
              .equals(dx.main.packageName))) {
        return true;
      } // end if
    } // end for
    return false;
  } // end contains()

  // ~ Methods
  // ------------------------------------------------------------------

  /**
   * DOCUMENT ME!
   * 
   * @return DOCUMENT ME!
   */
  public static final FileSystemClassLoader getFsClassLoader() {
    return ALCWebFilter.fsClassLoader;
  } // end getFsClassLoader()

  public static ALCWebFilter getHandle() {
    return ALCWebFilter.handle;
  }

  /** DOCUMENT ME! */
  private volatile boolean init = false;

  /** DOCUMENT ME! */
  private volatile Thread initThread = null;

  private List<ALCManifest> lALCManifest = new ArrayList<ALCManifest>(0);

  private List<ALCManifest> lBundlesALCManifest = new ArrayList<ALCManifest>(
      0);

  /** DOCUMENT ME! */
  private final List<FileSystem> listMountedFs = new ArrayList<FileSystem>();

  /** DOCUMENT ME! */
  private MainFilter mainFilter = null;
  
  private volatile long lastLoadLog4j = -1;
  
  private ServletContext context = null;

  /**
   * DOCUMENT ME!
   * 
   * @param config
   *            DOCUMENT ME!
   * 
   * @throws ServletException
   *             DOCUMENT ME!
   */
  private void _init(final FilterConfig config) throws ServletException {
    if (this.init) {
      return;
    } // end if
    ALCWebFilter.handle = this;
    try {
      try {
        URL url = config.getServletContext().getResource ("/WEB-INF/classes/log4j.properties");
        URLConnection uc = url.openConnection();
        lastLoadLog4j = uc.getLastModified();
        try{uc.getInputStream().close();}catch(Exception ignore){}
        PropertyConfigurator.configure (url);
      } // end try
      catch (final Exception e) {
      } // end catch
      this.registerConfigMergers();
      final String contextName = this.getContextName(context);
      final StringBuilder bufferUnionAlrFs = new StringBuilder();
      final StringBuilder bufferUnionFs = new StringBuilder();
      final StringBuilder bufferUnionLibsFs = new StringBuilder();
      final FileSystem contextfs = FileSystem.mount(contextName
          + "_CONTEXT", FileSystemType.SERVLETCONTEXT, context);
      this.listMountedFs.add(contextfs);
      LOG.info("Mounted servlet context filesystem "
          + contextfs.getLabel());

      // mount union alr files
      try {
        this.lBundlesALCManifest = this.getPackageToDeploy(contextfs
            .directory("/WEB-INF/bundle-archives/"), context);
      }
      catch (Exception ignore){}

      LOG.info("lBundlesALCManifest : "+lBundlesALCManifest.size());
      for (final ALCManifest bundle : this.lBundlesALCManifest) {
        LOG.info("mounting : "+bundle.getJarFile().getPath());
        final FileSystem zipfs = FileSystem.mount(contextName + "_ALR_"
            + bundle.getJarFile().getName(), FileSystemType.ZIP,
            bundle.getJarFile());
        LOG.info("mounted : "+bundle.getJarFile().getPath());
        bufferUnionAlrFs.append(zipfs.getLabel());
        bufferUnionAlrFs.append(":");
        this.listMountedFs.add(zipfs);
      }
      bufferUnionAlrFs.append(contextfs.getLabel());
      bufferUnionAlrFs.append(":");

      LOG.info("Mounting unionALRFS filesystem "
          + bufferUnionAlrFs.toString());
      final FileSystem unionALRFS = FileSystem.mount(contextName,
          FileSystemType.UNION, bufferUnionAlrFs.toString());
      LOG.info("Mounted unionALRFS filesystem "
          + unionALRFS.getLabel() + " - "
          + bufferUnionAlrFs.toString());

      final FileSystem memoryfs = FileSystem.mount(unionALRFS.getLabel()
          + "_MEMORY", FileSystemType.MEMORY, null);
      this.listMountedFs.add(memoryfs);
      LOG.info("Mounted MEMORY filesystem " + memoryfs.getLabel());
      bufferUnionFs.append(unionALRFS.getLabel());
      bufferUnionFs.append(":");
      bufferUnionFs.append(memoryfs.getLabel());

      final Directory archives = unionALRFS
          .directory("/WEB-INF/archives/");
      this.lALCManifest = this.getPackageToDeploy(archives, context);

      for (int i = this.lALCManifest.size() - 1; i >= 0; i--) {
        final FileSystemElement file = this.lALCManifest.get(i)
            .getJarFile();
        FileSystem zipfs = null;

        try {
          zipfs = file.isFile() ? FileSystem.mount(unionALRFS
              .getLabel()
              + "_" + file.getName(), FileSystemType.ZIP, file)
              : FileSystem.mount(unionALRFS.getLabel() + "_"
                  + file.getName(), FileSystemType.CHROOT,
                  file);
        } // end try
        catch (final Exception ignore) {
          zipfs = FileSystem.getFileSystem(unionALRFS.getLabel()
              + "_" + file.getName());

          if (zipfs != null) {
            zipfs.umount();
            zipfs = file.isFile() ? FileSystem.mount(unionALRFS
                .getLabel()
                + "_" + file.getName(), FileSystemType.ZIP,
                file) : FileSystem.mount(unionALRFS.getLabel()
                + "_" + file.getName(), FileSystemType.CHROOT,
                file);
          } // end if
          else {
            continue;
          } // end else
        } // end catch

        this.listMountedFs.add(zipfs);

        try {
          FileSystem libs = null;

          try {
            libs = FileSystem.mount(unionALRFS.getLabel() + "_"
                + file.getName() + "_libs",
                FileSystemType.CHROOT, unionALRFS.getLabel()
                    + "_" + file.getName() + ":/lib/");
          } // end try
          catch (final Exception ignore) {
            libs = FileSystem.getFileSystem(unionALRFS.getLabel()
                + "_" + file.getName() + "_libs");

            if (libs != null) {
              libs.umount();
              libs = FileSystem.mount(unionALRFS.getLabel() + "_"
                  + file.getName() + "_libs",
                  FileSystemType.CHROOT, unionALRFS
                      .getLabel()
                      + "_"
                      + file.getName()
                      + ":/lib/");
            } // end if
          } // end catch

          if (libs != null) {
            this.listMountedFs.add(libs);
            LOG.info("Mounted libs filesystem "
                + unionALRFS.getLabel() + "_" + file.getName()
                + ":/lib/");

            if (bufferUnionLibsFs.length() > 0) {
              bufferUnionLibsFs.append(":");
            } // end if

            bufferUnionLibsFs.append(unionALRFS.getLabel());
            bufferUnionLibsFs.append("_");
            bufferUnionLibsFs.append(file.getName());
            bufferUnionLibsFs.append("_libs");

            for (final File lib : libs.getRoot().getFiles()) {
              if (lib.getName().endsWith(".jar")) {
                FileSystem fs = null;

                try {
                  fs = FileSystem.mount(unionALRFS.getLabel()
                      + "_" + file.getName() + "_lib_"
                      + lib.getName(),
                      FileSystemType.ZIP, lib);
                } // end try
                catch (final Exception ignore) {
                  fs = FileSystem.getFileSystem(unionALRFS
                      .getLabel()
                      + "_"
                      + file.getName()
                      + "_lib_"
                      + lib.getName());

                  if (fs != null) {
                    fs.umount();
                    fs = FileSystem.mount(unionALRFS
                        .getLabel()
                        + "_"
                        + file.getName()
                        + "_lib_" + lib.getName(),
                        FileSystemType.ZIP, lib);
                  } // end if
                } // end catch

                if (fs != null) {
                  this.listMountedFs.add(fs);
                  if (bufferUnionLibsFs.length() > 0) {
                    bufferUnionLibsFs.append(":");
                  } // end if

                  bufferUnionLibsFs.append(fs.getLabel());
                  LOG.info("Mounted lib filesystem "
                      + fs.getLabel());
                } // end if

              } // end if
            } // end for
          } // end if
        } // end try
        catch (final IOException ignore) {
          ;
        } // end catch

        try {
          FileSystem fs = null;

          try {
            fs = FileSystem.mount(unionALRFS.getLabel() + "_"
                + file.getName() + "_webapp",
                FileSystemType.CHROOT, unionALRFS.getLabel()
                    + "_" + file.getName() + ":/content/");
          } // end try
          catch (final Exception ignore) {
            fs = FileSystem.getFileSystem(unionALRFS.getLabel()
                + "_" + file.getName() + "_webapp");

            if (fs != null) {
              fs.umount();
              fs = FileSystem.mount(unionALRFS.getLabel() + "_"
                  + file.getName() + "_webapp",
                  FileSystemType.CHROOT, unionALRFS
                      .getLabel()
                      + "_"
                      + file.getName()
                      + ":/content/");
            } // end if
          } // end catch

          if (fs != null) {
            this.listMountedFs.add(fs);
            LOG.info("Mounted content filesystem "
                + fs.getLabel() + "_" + file.getName()
                + ":/content/");
          } // end if

          bufferUnionFs.append(":");
          bufferUnionFs.append(unionALRFS.getLabel());
          bufferUnionFs.append("_");
          bufferUnionFs.append(file.getName());
          bufferUnionFs.append("_webapp");
        } // end try
        catch (final IOException ignore) {
          ;
        } // end catch
      } // end for

      for (int i = 0; i < this.lALCManifest.size(); i++) {
        final FileSystemElement file = this.lALCManifest.get(i)
            .getJarFile();
        try {
          FileSystem fs = null;

          try {
            fs = FileSystem.mount(unionALRFS.getLabel() + "_"
                + file.getName() + "_config",
                FileSystemType.CHROOT, unionALRFS.getLabel()
                    + "_" + file.getName() + ":/config/");
          } // end try
          catch (final Exception ignore) {
            fs = FileSystem.getFileSystem(unionALRFS.getLabel()
                + "_" + file.getName() + "_config");

            if (fs != null) {
              fs.umount();
              fs = FileSystem.mount(unionALRFS.getLabel() + "_"
                  + file.getName() + "_config",
                  FileSystemType.CHROOT, unionALRFS
                      .getLabel()
                      + "_"
                      + file.getName()
                      + ":/config/");
            } // end if
          } // end catch

          if (fs != null) {
            this.listMountedFs.add(fs);

            for (final File f : fs.getRoot().getFiles()) {
              try {
                ConfigMergerImpl.getInstance().mergeConfig(f,
                    memoryfs, file.getName());
              } // end try
              catch (final Exception e) {
                e.printStackTrace();
              } // end catch
            } // end for

            LOG.info("Mounted config filesystem "
                + fs.getLabel() + "_" + file.getName()
                + ":/config/");
          } // end if
        } // end try
        catch (final IOException ignore) {
          ;
        } // end catch
      } // end for

      FileSystem unionWebappFS = null;

      try {
        unionWebappFS = FileSystem.mount(unionALRFS.getLabel()
            + "_UNION_webapp", FileSystemType.UNION, bufferUnionFs
            .toString());
      } // end try
      catch (final Exception ignore) {
        unionWebappFS = FileSystem.getFileSystem(unionALRFS.getLabel()
            + "_UNION_webapp");

        if (unionWebappFS != null) {
          unionWebappFS.umount();
          unionWebappFS = FileSystem.mount(unionALRFS.getLabel()
              + "_UNION_webapp", FileSystemType.UNION,
              bufferUnionFs.toString());
        } // end if
      } // end catch

      if (unionWebappFS != null) {
        this.listMountedFs.add(unionWebappFS);
      } // end if

      LOG.info("Mounted lib unionWebappFS "
              + bufferUnionFs.toString());

      FileSystem unionLibsFS = null;

      try {
        unionLibsFS = FileSystem.mount(unionALRFS.getLabel()
            + "_UNION_libs", FileSystemType.UNION,
            bufferUnionLibsFs.toString());
      } // end try
      catch (final Exception ignore) {
        unionLibsFS = FileSystem.getFileSystem(unionALRFS.getLabel()
            + "_UNION_libs");

        if (unionLibsFS != null) {
          unionLibsFS.umount();
          unionLibsFS = FileSystem.mount(unionALRFS.getLabel()
              + "_UNION_libs", FileSystemType.UNION,
              bufferUnionLibsFs.toString());
        } // end if
      } // end catch

      if (unionLibsFS != null) {
        this.listMountedFs.add(unionLibsFS);
      } // end if

      LOG.info("Mounted lib unionLibsFS "
          + bufferUnionLibsFs.toString());
      ALCWebFilter.fsClassLoader = new FileSystemClassLoader(unionLibsFS
          .getLabel(), bufferUnionLibsFs.toString(), null, this
          .getClass().getClassLoader());
      LOG.info("Classloader initialized : "
          + ALCWebFilter.fsClassLoader);

      try {
        this.mainFilter = Dynamic._.Proxy(ALCWebFilter.fsClassLoader
            .loadClass("org.allcolor.ywt.filter.CMainFilter")
            .newInstance(), MainFilter.class);
        this.mainFilter.init(unionWebappFS, unionALRFS.getLabel());
        LOG.info("MainFilter initialized : " + this.mainFilter);
      } // end try
      catch (final IllegalAccessException e) {
        throw e;
      } // end catch
      catch (final InstantiationException e) {
        throw e;
      } // end catch
      catch (final ClassNotFoundException e) {
        throw e;
      } // end catch
    } // end try
    catch (final Exception e) {
      throw new ServletException(e);
    } // end catch
  } // end _init()

  /**
   * DOCUMENT ME!
   */
  public void destroy() {
    if ((this.initThread != null) && this.initThread.isAlive()) {
      try {
        Thread.class.getMethod("stop", (Class<?>[]) null).invoke(
            this.initThread, (Object[]) null);
      } // end try
      catch (final Exception ignore) {
        ;
      } // end catch
    } // end if

    this.initThread = null;
    ALCWebFilter.fsClassLoader = null;

    if (this.mainFilter != null) {
      this.mainFilter.destroy();
      this.mainFilter = null;
    } // end if

    for (final FileSystem fs : this.listMountedFs) {
      try {
        fs.umount();
      } // end try
      catch (final Throwable ignore) {
        final Throwable t = ignore;

        if (t.getClass() == ThreadDeath.class) {
          throw (ThreadDeath) t;
        } // end if

        Throwable cause = ignore.getCause();

        while (cause != null) {
          if (cause.getClass() == ThreadDeath.class) {
            throw (ThreadDeath) cause;
          } // end if

          cause = cause.getCause();
        } // end while
      } // end catch
    } // end for

    this.listMountedFs.clear();
    this.lALCManifest.clear();
    this.context = null;
    ALCWebFilter.handle = null;
    this.init = false;
  } // end destroy()

  /**
   * DOCUMENT ME!
   * 
   * @param arg0
   *            DOCUMENT ME!
   * @param arg1
   *            DOCUMENT ME!
   * @param arg2
   *            DOCUMENT ME!
   * 
   * @throws IOException
   *             DOCUMENT ME!
   * @throws ServletException
   *             DOCUMENT ME!
   */
  public void doFilter(final ServletRequest arg0, final ServletResponse arg1,
      final FilterChain arg2) throws IOException, ServletException {
    if (!this.init) {
      final HttpServletResponse response = Dynamic._.Cast(arg1);
      response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
          "Mainfilter not initialized.");

      return;
    } // end if

    if (this.mainFilter != null) {
      try {
        URL url = this.context.getResource ("/WEB-INF/classes/log4j.properties");
        URLConnection uc = url.openConnection();
        if (uc.getLastModified() != lastLoadLog4j) {
          lastLoadLog4j = uc.getLastModified();
          try{uc.getInputStream().close();}catch(Exception ignore){}
          PropertyConfigurator.configure (url);
        } else {
          try{uc.getInputStream().close();}catch(Exception ignore){}
        }
      } // end try
      catch (final Exception e) {
      } // end catch
      
      
      this.mainFilter.doFilter(arg0, arg1);
    } // end if
    else {
      final HttpServletResponse response = Dynamic._.Cast(arg1);
      response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
          "Mainfilter bad setup.");
    } // end else
  } // end doFilter()

  /**
   * 
   * @param toCheck
   * @param pck
   * @param pckVersion
   * @return
   */
  private ALCManifest findDependency(final List<ALCManifest> toCheck,
      final String pck, final String pckVersion, final String operator)
      throws ServletException {
    ALCManifest toRet = null;

    if ("<".equals(operator) || "!!<".equals(operator)) {
      for (final ALCManifest dx : toCheck) {
        if (dx.main.packageName.equals(pck)) {
          if (dx.main.version.compareTo(pckVersion) >= 0) {
            continue;
          } // end if
          toRet = dx;
          break;
        } // end if
      } // end for
    } else if ("<=".equals(operator) || "!!<=".equals(operator)) {
      for (final ALCManifest dx : toCheck) {
        if (dx.main.packageName.equals(pck)) {
          if (dx.main.version.compareTo(pckVersion) > 0) {
            continue;
          } // end if
          toRet = dx;
          break;
        } // end if
      } // end for
    } else if ("==".equals(operator) || "!!==".equals(operator)) {
      for (final ALCManifest dx : toCheck) {
        if (dx.main.packageName.equals(pck)) {
          if (dx.main.version.compareTo(pckVersion) != 0) {
            continue;
          } // end if
          toRet = dx;
          break;
        } // end if
      } // end for
    } else if (">=".equals(operator) || "!!>=".equals(operator)) {
      for (final ALCManifest dx : toCheck) {
        if (dx.main.packageName.equals(pck)) {
          if (dx.main.version.compareTo(pckVersion) < 0) {
            continue;
          } // end if
          toRet = dx;
          break;
        } // end if
      } // end for
    } else if (">".equals(operator) || "!!>".equals(operator)) {
      for (final ALCManifest dx : toCheck) {
        if (dx.main.packageName.equals(pck)) {
          if (dx.main.version.compareTo(pckVersion) <= 0) {
            continue;
          } // end if
          toRet = dx;
          break;
        } // end if
      } // end for
    }
    if ((operator != null) && operator.startsWith("!!")) {
      if (toRet != null) {
        throw new ServletException("Conflict found !! " + pck + " "
            + toRet.main.version + " " + operator + " "
            + pckVersion + " and version " + pckVersion + " found.");
      }
    }
    if (toRet != null) {
      LOG.info("Found package : "+toRet.getPackage().packageName+"/"+
          toRet.getPackage().version+" - "+toRet.getJarFile().getPath());
    }
    return toRet;
  } // end getDepedancy()

  public List<ALCManifest> getALCManifestList() {
    return Collections.unmodifiableList(this.lALCManifest);
  }

  public List<ALCManifest> getBundlesALCManifestList() {
    return Collections.unmodifiableList(this.lBundlesALCManifest);
  }

  /**
   * DOCUMENT ME!
   * 
   * @param context
   *            DOCUMENT ME!
   * 
   * @return DOCUMENT ME!
   */
  private final String getContextName(final ServletContext context) {
    try {
      String url = context.getResource("/").toExternalForm();

      if (url.endsWith("/")) {
        url = url.substring(0, url.length() - 1);
      } // end if

      if (url.lastIndexOf('/') != -1) {
        url = url.substring(url.lastIndexOf('/') + 1).trim();
      } // end if

      if (url.length() == 0) {
        return "ROOT";
      } // end if

      return url;
    } // end try
    catch (final Exception e) {
      final String result = context.getServletContextName();

      if (result == null) {
        return "unknown";
      } // end if

      return result;
    } // end catch
  } // end getContextName()

  /**
   * DOCUMENT ME!
   * 
   * @param files
   *            DOCUMENT ME!
   * @param context
   *            DOCUMENT ME!
   * 
   * @throws ServletException
   *             DOCUMENT ME!
   */
  private List<ALCManifest> getPackageToDeploy(final Directory archives,
      final ServletContext context) throws ServletException, IOException {
    LOG.info("Dependencies check started.");

    final List<ALCManifest> lALCManifest = new ArrayList<ALCManifest>();

    for (final Directory dir : archives.getDirectories()) {
      if (dir.getName().endsWith(".jar")) {
        FileSystem fs = null;
        try {
          fs = FileSystem.mount(UUID.randomUUID() + "_"
              + dir.getName(), FileSystemType.CHROOT, dir);

          final File alcManifest = fs.file("/META-INF/MANIFEST.MF");

          if ((alcManifest != null) && alcManifest.exists()) {
            final ALCManifest current = this.parseManifest(
                alcManifest, dir, fs);
            if (current != null) {
              if (ALCWebFilter.containsALCManifest(lALCManifest,
                  current, false)) {
                continue;
              } // end if

              lALCManifest.add(current);
            } // end if
          } // end if
        } // end try
        catch (final IOException e) {
          continue;
        } // end catch
        finally {
          try {
            fs.umount();
          } // end try
          catch (final Exception ignore) {
            ;
          } // end catch
        } // end finally
      }
    }

    for (final File file : archives.getFiles()) {
      if (file.getName().endsWith(".jar")) {
        FileSystem fs = null;
        try {
          fs = FileSystem.mount(UUID.randomUUID() + "_"
              + file.getName(), FileSystemType.ZIP, file);

          final File alcManifest = fs.file("/META-INF/MANIFEST.MF");

          if ((alcManifest != null) && alcManifest.exists()) {
            final ALCManifest current = this.parseManifest(
                alcManifest, file, fs);
            if (current != null) {
              if (ALCWebFilter.containsALCManifest(lALCManifest,
                  current, false)) {
                continue;
              } // end if

              lALCManifest.add(current);
            } // end if
          } // end if
        } // end try
        catch (final IOException e) {
          continue;
        } // end catch
        finally {
          try {
            fs.umount();
          } // end try
          catch (final Exception ignore) {
            ;
          } // end catch
        } // end finally
      }
    } // end for
    LOG.info("end looking for file !");

    // resolve dependencies
    for (int i = 0; i < lALCManifest.size();i++) {
      final ALCManifest dx = lALCManifest.get(i);
      if (dx.main.getDepends() != null && dx.main.getDepends().trim().length() > 0) {
        LOG.info("dependancies for "+dx.main.packageName+" : "+dx.main.getDepends());
        final StringTokenizer tkDep = new StringTokenizer(dx.main
            .getDepends(), ",\n\r\\/", false);
        while (tkDep.hasMoreTokens()) {
          final String token = tkDep.nextToken().trim();
          final StringTokenizer tkPackage = new StringTokenizer(token,
              " \\/,", false);
          if (tkPackage.countTokens() == 3) {
            final String sPckpackageName = tkPackage.nextToken();
            final String sOperator = tkPackage.nextToken();
            final String sPckversion = tkPackage.nextToken();
            if (sPckversion == null) {
              throw new ServletException("Dependency "
                  + sPckpackageName + " - " + sPckversion
                  + " not found.");
            }
            final ALCManifest dependency = this.findDependency(
                lALCManifest, sPckpackageName, sPckversion,
                sOperator);
            if (dependency != null) {
              dx.addDependency(dependency);
            } else {
              throw new ServletException("Dependency "
                  + sPckpackageName + " - " + sPckversion
                  + " not found.");
            }
          }
        }
      }
    } // end for
    // sort start order
    Collections.sort(lALCManifest, new Comparator<ALCManifest>() {
      public int compare(final ALCManifest o1, final ALCManifest o2) {
        if (ALCWebFilter.containsALCManifest(o1.getDependenciesList(),
            o2, true)) {
          return 1;
        }
        if (ALCWebFilter.containsALCManifest(o2.getDependenciesList(),
            o1, true)) {
          return -1;
        }
        return 0;
      }
    });

    LOG.info("Packages found:");

    for (final ALCManifest alcMf : lALCManifest) {
      LOG.info(alcMf.getPackage().getPackageName() + " - "
          + alcMf.getPackage().getVersion() + " - ("
          + alcMf.getPackage().title + ") "+alcMf.getJarFile().getPath());
    }

    LOG.info("Dependencies check finished.");
    return lALCManifest;
  } // end checkDeployment()

  // ~ Inner Interfaces
  // ---------------------------------------------------------

  /**
   * DOCUMENT ME!
   * 
   * @param config
   *            DOCUMENT ME!
   * 
   * @throws ServletException
   *             DOCUMENT ME!
   */
  public void init(final FilterConfig config) throws ServletException {
    final ClassLoader currentCL = Thread.currentThread()
        .getContextClassLoader();
    this.context = config.getServletContext();
    this.initThread = new Thread() {

      {
        this.setContextClassLoader(currentCL);
        this.setDaemon(true);
        this.start();
      }

      @Override
      public void run() {
        try {
          ALCWebFilter.this._init(config);
          ALCWebFilter.this.init = true;
        } // end try
        catch (final ServletException e) {
          e.printStackTrace();

          if (e.getCause() != null) {
            e.getCause().printStackTrace();
          } // end if

          if (e.getRootCause() != null) {
            e.getRootCause().printStackTrace();
          } // end if

          ALCWebFilter.this.init = false;
        } // end catch
      } // end run()
    } // end new
    ;
  } // end init()

  // ~ Inner Classes
  // ------------------------------------------------------------

  // ~ Inner Classes
  // ----------------------------------------------------------
  /**
   * DOCUMENT ME!
   * 
   * @param manifest
   *            DOCUMENT ME!
   * @param yar
   *            DOCUMENT ME!
   * 
   * @return DOCUMENT ME!
   * 
   * @throws RuntimeException
   *             DOCUMENT ME!
   */
  private ALCManifest parseManifest(final File manifest,
      final FileSystemElement file, final FileSystem fs) {
    InputStream in = null;
    try {
      in = manifest.toURL().openStream();
      LOG.info("parsing : "+manifest.getPath()+" - "+file.getPath());
      final Manifest mf = new Manifest(in);
      final Attributes alcAttributes = mf
          .getAttributes("org/allcolor/alc/");
      if (alcAttributes != null) {
        final String spackageName = alcAttributes
            .getValue("Extension-name") == null ? ""
            : alcAttributes.getValue("Extension-name").trim();
        if ("".equals(spackageName)) {
          return null;
        }
        final String sversion = alcAttributes
            .getValue("Specification-Version") == null ? ""
            : alcAttributes.getValue("Specification-Version")
                .trim();
        if ("".equals(sversion)) {
          return null;
        }
        final String sdepends = alcAttributes.getValue("Depends") == null ? ""
            : alcAttributes.getValue("Depends").trim();
        final String slicenses = alcAttributes.getValue("License") == null ? ""
            : alcAttributes.getValue("License").trim();
        final StringBuilder licensesText = new StringBuilder();
        final StringTokenizer tkLic = new StringTokenizer(slicenses,
            ",", false);
        while (tkLic.hasMoreTokens()) {
          final String token = tkLic.nextToken().trim();
          try {
            File licenseFile = null;
            if (token.endsWith("+")) {
              licenseFile = fs.file("/META-INF/"
                  + token.substring(0, token.length() - 1)
                  + ".license");
            } else {
              licenseFile = fs.file("/META-INF/" + token + ".license");
            }
            if ((licenseFile != null) && licenseFile.exists()) {
              ReaderUtils.forEachLine(licenseFile,
                  new ReaderUtils.LineListener() {
                    public void exception(
                        final IOException ioe) {
                    }

                    public boolean line(final String line)
                        throws IOException {
                      licensesText.append(line);
                      licensesText.append('\n');
                      return true;
                    }
                  });
            }
          } catch (final Exception ignore) {
          }
        }
        final String sdescription = alcAttributes
            .getValue("Description") == null ? "" : alcAttributes
            .getValue("Description");
        final String svendor = alcAttributes
            .getValue("Specification-Vendor") == null ? ""
            : alcAttributes.getValue("Specification-Vendor");
        final String stitle = alcAttributes
            .getValue("Specification-Title") == null ? ""
            : alcAttributes.getValue("Specification-Title");
        return new ALCManifest(file, mf, new YPackage(spackageName,
            sversion, sdepends,
            sdescription, slicenses, licensesText.toString(),
            svendor, stitle));
      }
      return null;
    } // end try
    catch (final RuntimeException ignore) {
      throw ignore;
    } // end catch
    catch (final Exception ignore) {
      throw new RuntimeException(ignore);
    } // end catch
    finally {
      try {
        if (in != null) {
          in.close();
        }
      } catch (final Exception ignore) {
      }
    }
  } // end parseDepXml()

  private void registerConfigMergers() throws IOException {
    final ClassLoader cl = Thread.currentThread().getContextClassLoader();
    for (final Enumeration<URL> it = cl
        .getResources("META-INF/config-merger.properties"); it
        .hasMoreElements();) {
      InputStream in = null;
      try {
        in = it.nextElement().openStream();
        final Properties props = new Properties();
        props.load(in);
        for (final Map.Entry<Object, Object> entry : props.entrySet()) {
          try {
            final ConfigMerger cm = (ConfigMerger) cl.loadClass(
                (String) entry.getValue()).newInstance();
            ConfigMergerImpl.getInstance().registerConfigMerger(
                (String) entry.getKey(), cm);
          } catch (final Exception ignore) {
          }
        }
      } catch (final Exception ignore) {
      } finally {
        try {
          if (in != null) {
            in.close();
          }
        } catch (final Exception ignore) {
        }
      }
    }
  }
} // end ALCWebFilter
/**
 * ALC. Copyright (C) 2009 Quentin Anciaux
 */
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.