Package net.sourceforge.javautil.classloader.resolver.impl

Source Code of net.sourceforge.javautil.classloader.resolver.impl.ClassDependencyPoolImpl$DependencyPoolSource

package net.sourceforge.javautil.classloader.resolver.impl;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.sourceforge.javautil.classloader.resolver.IClassArtifactReference;
import net.sourceforge.javautil.classloader.resolver.IClassDependency;
import net.sourceforge.javautil.classloader.resolver.IClassPackage;
import net.sourceforge.javautil.classloader.resolver.IClassDependencyPool;
import net.sourceforge.javautil.classloader.resolver.IClassDependencyPool.PoolScope;
import net.sourceforge.javautil.classloader.resolver.IClassPackage.IVersion;
import net.sourceforge.javautil.classloader.source.ClassSource;
import net.sourceforge.javautil.classloader.source.CompositeClassSource;
import net.sourceforge.javautil.common.StringUtil;
import net.sourceforge.javautil.common.logging.ILogger;
import net.sourceforge.javautil.common.logging.LoggingContext;

/**
* A pool of dependencies, which can have a parent, is a collection of unique {@link IClassPackage}'s.<br/><br/>
*
* The heiarchy of {@link ClassDependencyPoolImpl}'s must only have a single version of a particular
* {@link IClassPackage} in an entire pool heiarchy branch.
*
* TODO: Make sure dependency conflict is stable at some point
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: ClassDependencyPoolImpl.java 2709 2010-12-31 00:46:45Z ponderator $
*/
public class ClassDependencyPoolImpl implements IClassDependencyPool {
 
  protected static final ILogger log = LoggingContext.getContextualLogger(ClassDependencyPoolImpl.class);
 
  protected final ClassDependencyPoolImpl parent;
  protected final PoolScope scope;
  protected final String name;

  protected List<IClassPackage> primary = new ArrayList<IClassPackage>();
  protected Map<String, IClassPackage> packages = new HashMap<String, IClassPackage>();
  protected List<IClassPackage> conflicts = new ArrayList<IClassPackage>();
  protected List<String> ignore = new ArrayList<String>();
  protected List<IClassDependencyPool> children = new ArrayList<IClassDependencyPool>();
 
  protected long lastModified = System.currentTimeMillis();
 
  public ClassDependencyPoolImpl(String name) { this(name, null, PoolScope.Root); }
 
  protected ClassDependencyPoolImpl(String name, ClassDependencyPoolImpl parent, PoolScope scope) {
    this.parent = parent;
    this.scope = scope;
    this.name = name;
   
    if (this.parent != null) this.parent.link(this);
  }
 
  /**
   * @return The parent pool, or null if this is the top most pool
   */
  public IClassDependencyPool getParent() { return parent; }
 
  public void removeFromScope(IClassArtifactReference reference, IClassDependencyPool caller) {
    String id = this.getUniqueId(reference.getGroupId(), reference.getArtifactId());
    this.packages.remove(id);
    if (scope == PoolScope.Component && caller != parent) { this.parent.removeFromScope(reference, this); }
    for (IClassDependencyPool pool : this.children) {
      if (pool == caller) continue;
      if (pool.getScope() == PoolScope.Component) pool.removeFromScope(reference, this);
    }
  }
 
  /**
   * This will update the last modified for this pool and its parent if this is not a root pool
   */
  protected void touch () {
    this.lastModified = System.currentTimeMillis();
    if (this.scope == PoolScope.Component) this.parent.touch();
  }

  public long getLastModified() { return this.lastModified; }

  public boolean isPrimaryPackage(IClassArtifactReference reference, IClassDependencyPool caller) {
    for (IClassPackage pkg : this.primary) {
      if (pkg.compareTo(reference) == 0) return true;
    }
    for (IClassDependencyPool pool : this.children) {
      if (pool == caller) continue;
      if (pool.getScope() == PoolScope.Component && pool.isPrimaryPackage(reference, this)) return true;
    }
    return scope == PoolScope.Component && caller != parent ? this.parent.isPrimaryPackage(reference, this) : false;
  }

  public void link(IClassDependencyPool pool) {
    if (!this.children.contains(pool)) this.children.add(pool);
  }

  public void remove(IClassDependencyPool child) {
    this.children.remove(child);
  }

  public List<IClassDependencyPool> getChildPools() {
    return new ArrayList<IClassDependencyPool>(this.children);
  }

  public ClassDependencyPoolImpl createChild(String name, PoolScope scope) {
    return new ClassDependencyPoolImpl(name, this, scope);
  }

  public String getName() {
    return this.name;
  }

  public PoolScope getScope() { return scope; }

  /**
   * This will remove any package with the specified
   * id's and will make sure they are not added to this
   * pool in the future.
   *
   * @param groupId The group id of the package to ignore
   * @param artifactId The artifact of the package to ignore
   */
  public void ignore (String groupId, String artifactId) {
    String id = this.getUniqueId(groupId, artifactId);
    if (this.packages.containsKey(id)) {
      this.primary.remove(this.packages.remove(id));
    }
    this.ignore.add( id );
  }
 
  public void addWithDependencies (IClassPackage pkg) {
    this.addWithDependencies(pkg, true);
  }
 
  public void addWithDependencies (IClassPackage pkg, boolean primary) {
    if (this.add(primary, pkg).size() == 1)
      return;
   
    for (IClassDependency cp : pkg.getDependencies()) {
      if (conflicts.contains(cp.getPackage())) continue;
      this.addWithDependencies(cp.getPackage(), false);
    }
   
    this.touch();
  }

  /**
   * This will verify there is not already a package in the pool or parent pool.
   * If there is and it is the same version it will simply ignore the addition.
   * If there is a version conflict the version that would have been added will be
   * aggregated to a list that will be returned.
   *
   * @param packages The packages to add to the pool
   * @return A list (possibly empty) of packages that had version conflicts with versions already in the pool
   */
  protected List<IClassPackage> add (boolean primary, IClassPackage... packages) {
    List<IClassPackage> conflicts = new ArrayList<IClassPackage>();
   
    for (IClassPackage pkg : packages) {
      if (ClassPackageImpl.isSelfPackage(pkg)) continue;
      String id = this.getUniqueId(pkg);
     
      if (this.ignore.contains(id)) continue;
     
      if (primary) {
        this.packages.put(id, pkg);
        this.primary.add(pkg);
        continue;
      }
     
      IVersion version = this.getVersion(pkg.getGroupId(), pkg.getArtifactId(), id, null);
      if (version == null) {
        this.packages.put(id, pkg);
      } else if (version.compareTo( pkg.getVersion() ) < 0) {
        IClassPackage old = this.packages.get(id);
       
        if (this.isPrimaryPackage(pkg, this)) {
          conflicts.add(pkg);
          log.info("Canceling upgrade for primary " + old + " [new: " + pkg + "]");
        } else {
          log.info("Upgrading from " + old + " to " + pkg);
          this.removeFromScope(pkg, this);
          this.packages.put(id, pkg);
        }
      } else if (version.compareTo( pkg.getVersion() ) > 0) {
        conflicts.add(pkg); this.conflicts.add(pkg);
      }
    }
   
    return conflicts;
  }
 
  public List<IClassPackage> getPackages (boolean recursive) {
    List<IClassPackage> pkgs = new ArrayList<IClassPackage>(this.packages.values());
   
    if (recursive)
      for (IClassDependencyPool pool : new ArrayList<IClassDependencyPool>(this.children)) {
        if (pool.getScope() == PoolScope.Component)
          pkgs.addAll(pool.getPackages(recursive));
      }
   
    return pkgs;
  }
 
  public IVersion getVersion (String groupId, String artifactId, IClassDependencyPool caller) {
    return this.getVersion(groupId, artifactId, this.getUniqueId(groupId, artifactId), caller);
  }
 
  protected IVersion getVersion (String groupId, String artifactId, String uniqueId, IClassDependencyPool caller) {
    IVersion version = null;
   
    if (parent != null && caller != parent) version = parent.getVersion(groupId, artifactId, this);
   
    if (version == null) {
      for (IClassDependencyPool pool : new ArrayList<IClassDependencyPool>(this.children)) {
        if (pool.getScope() == PoolScope.Root || caller == pool) continue;
        version = pool.getVersion(groupId, artifactId, this);
        if (version != null) break;
      }
    }
   
    return version == null ? this.getVersion( uniqueId ) : version;
  }
 
  public DependencyPoolSource getCompositeClassSource () {
    DependencyPoolSource ccs = new DependencyPoolSource();
   
    if (log.isDebug())
      log.debug("Composite source for pool:");
   
    List<String> packageList = new ArrayList<String>();
    List<IClassPackage> pkgs = new ArrayList<IClassPackage>(this.packages.values());
    Collections.sort(pkgs);
    for (IClassPackage pkg : pkgs) {
     
      if (log.isDebug())
        log.debug("  ---->" + pkg);
     
      packageList.add(this.getUniqueId(pkg));
      ccs.add( pkg.getMainJarSource() );
    }
   
    for (IClassDependencyPool pool : new ArrayList<IClassDependencyPool>(this.children)) {
      if (pool.getScope() == PoolScope.Component) {
        ccs.add(pool.getCompositeClassSource());
      }
    }
   
    return ccs;
  }
 
  public void printHeiarchy(PrintStream out) {
    if (this.parent != null) {
      this.parent.printHeiarchy(out);
    } else {
      this.printHeiarchyInternal(this, out, 0);
    }
  }
 
  protected void printHeiarchyInternal(IClassDependencyPool pool, PrintStream out, int level) {
    String prefix = StringUtil.repeat('\t', level);
   
    out.println(prefix + "Pool: " + pool.getName());
    for (IClassPackage pkg : pool.getPackages(false)) {
      out.println(prefix + " -> " + pkg);
    }
   
    for (IClassDependencyPool child : pool.getChildPools()) {
      this.printHeiarchyInternal(child, out, level + 1);
    }
  }

  /**
   * @param packageId The unique package id
   * @return The version of the package found in the pool (or pools parent), or null if it could not be located
   */
  protected IVersion getVersion (String packageId) {
    return packages.containsKey(packageId) ? packages.get(packageId).getVersion() : null;
  }
 
  /**
   * @see #getUniqueId(String, String)
   */
  protected String getUniqueId (IClassPackage pkg) {
    return this.getUniqueId(pkg.getGroupId(), pkg.getArtifactId());
  }
 
  /**
   * @param groupId The group id of the package
   * @param artifactId The artifact id of the package
   * @return A unique package id
   */
  protected String getUniqueId (String groupId, String artifactId) {
    return groupId + ":" + artifactId;
  }
 
  /**
   * This will allow the pool to be accessible via the returned class source.
   *
   * @author elponderador
   * @author $Author: ponderator $
   * @version $Id: ClassDependencyPoolImpl.java 2709 2010-12-31 00:46:45Z ponderator $
   */
  public class DependencyPoolSource extends CompositeClassSource {
   
    public DependencyPoolSource () {
      super(ClassDependencyPoolImpl.this.getName());
    }
   
    /**
     * @return The pool this source was generated from
     */
    public ClassDependencyPoolImpl getPool () { return ClassDependencyPoolImpl.this; }
   
  }

}
TOP

Related Classes of net.sourceforge.javautil.classloader.resolver.impl.ClassDependencyPoolImpl$DependencyPoolSource

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.