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

Source Code of net.sourceforge.javautil.classloader.resolver.impl.ClassPackageResolverImpl

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import net.sourceforge.javautil.classloader.resolver.ClassPackageResolverNetworkNode.Type;
import net.sourceforge.javautil.classloader.resolver.IClassArtifactReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackage;
import net.sourceforge.javautil.classloader.resolver.IClassPackageDependencyReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackageDescriptor;
import net.sourceforge.javautil.classloader.resolver.IClassPackageReference;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryLocal;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryLocalImportable;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryRemote;
import net.sourceforge.javautil.classloader.resolver.IClassPackageRepositoryRemoteAttempt;
import net.sourceforge.javautil.classloader.resolver.IClassPackageResolver;
import net.sourceforge.javautil.classloader.resolver.ClassPackageResolverContext;
import net.sourceforge.javautil.classloader.resolver.ClassPackageResolverContext;
import net.sourceforge.javautil.classloader.resolver.ClassPackageResolverNetworkNode;
import net.sourceforge.javautil.classloader.resolver.ClassPackageUpgradeException;
import net.sourceforge.javautil.classloader.resolver.IClassDependency.Scope;
import net.sourceforge.javautil.classloader.resolver.IClassPackage.IVersion;
import net.sourceforge.javautil.classloader.resolver.impl.maven.MavenRepositoryRemote;
import net.sourceforge.javautil.classloader.resolver.impl.maven.ProjectObjectModel;
import net.sourceforge.javautil.classloader.source.ClassSource;
import net.sourceforge.javautil.classloader.source.VirtualDirectoryClassSource;
import net.sourceforge.javautil.classloader.source.ZipClassSource;
import net.sourceforge.javautil.classloader.util.ClassPackageUtil;
import net.sourceforge.javautil.common.ArchiveUtil;
import net.sourceforge.javautil.common.StringUtil;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.io.IVirtualDirectory;
import net.sourceforge.javautil.common.io.impl.ISystemArtifact;
import net.sourceforge.javautil.common.io.impl.SystemDirectory;
import net.sourceforge.javautil.common.io.impl.SystemFile;
import net.sourceforge.javautil.common.logging.ILogger;
import net.sourceforge.javautil.common.logging.LoggingContext;
import net.sourceforge.javautil.common.reflection.cache.ClassDescriptor;

/**
* The default resolver implementation for {@link IClassPackage} resolution.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: ClassPackageResolverImpl.java 2745 2011-02-05 04:23:36Z ponderator $
*/
public class ClassPackageResolverImpl implements IClassPackageResolver {
 
  private static final ILogger log = LoggingContext.getContextualLogger(ClassPackageResolverImpl.class);
 
  /**
   * The main local repository, that has the capability of having packages imported into it.
   */
  protected final IClassPackageRepositoryLocalImportable repository;
 
  protected final List<IClassPackageRepositoryLocal> locals = new ArrayList<IClassPackageRepositoryLocal>();
 
  protected final Map<String, IClassPackageRepositoryRemote> remote = new HashMap<String, IClassPackageRepositoryRemote>();
  protected final Map<String, IClassPackage> cache = new HashMap<String, IClassPackage>();
 
  protected long remoteAttemptInterval = 24 * (60 * 60) * 1000;
 
  public ClassPackageResolverImpl(IClassPackageRepositoryLocalImportable repository) {
    this.repository = repository;
  }
 
  /**
   * Add a local repository for resolution only.
   *
   * @param local The local repository to add
   */
  public void addLocalRepository (IClassPackageRepositoryLocal local) { this.locals.add(local); }
 
  public List<IClassPackageRepositoryLocal> getLocalRepositories() {
    List<IClassPackageRepositoryLocal> local = new ArrayList<IClassPackageRepositoryLocal>(this.locals);
    local.add(0, repository);
    return local;
  }

  public List<IClassPackageRepositoryRemote> getRemoteRepositories() {
    return new ArrayList<IClassPackageRepositoryRemote>(this.remote.values());
  }
 
  public IClassPackageRepositoryLocalImportable getImportableRepository () {
    return this.repository;
  }

  /**
   * Add a remote repository for resolving locally unavailable packages.
   *
   * @param remote The remote repository to add
   */
  public void addRemoteRepository (IClassPackageRepositoryRemote remote) { this.remote.put(remote.getName(), remote); }

  public IVersion getLatestVersion(IClassArtifactReference reference, boolean localOnly) {
    List<IVersion> versions = this.getVersionsAvailable(reference, localOnly);
    return versions.size() == 0 ? null : versions.get(versions.size() - 1);
  }

  public List<IVersion> getVersionsAvailable(IClassArtifactReference reference, boolean localOnly) {
    List<IVersion> versions = new ArrayList<IVersion>();
   
    if (repository.contains(this, reference))
      versions.addAll( repository.getVersionsAvailable(reference) );
   
    for (IClassPackageRepositoryLocal local : this.locals) {
      versions.addAll( local.getVersionsAvailable(reference) );
    }
   
    if (!localOnly)
      for (String name : new ArrayList<String>(remote.keySet())) {
        IClassPackageRepositoryRemote remote = this.remote.get(name);
        if (remote.contains(reference))
          versions.addAll( remote.getVersionsAvailable(reference) );
      }
   
    Collections.sort(versions);
   
    return versions;
  }

  public boolean contains(IClassPackageReference reference, boolean localOnly) {
    if (repository.contains(this, reference)) return true;
   
    for (IClassPackageRepositoryLocal local : this.locals) {
      if (local.contains(this, reference)) return true;
    }
   
    if (!localOnly)
      for (String name : new ArrayList<String>(remote.keySet())) {
        IClassPackageRepositoryRemote remote = this.remote.get(name);
        if (remote.contains(reference)) return true;
      }
   
    return false;
  }
 
  @Override public IClassPackage locate(IClassPackageReference reference) {
    ClassPackageResolverContext ctx = this.resolve(new ClassPackageResolverContext(reference));
    ClassPackageResolverNetworkNode node = ctx.getResolved(reference);
    return node.getType() == Type.Available ? node.createPackage() : null;
  }

  public ClassPackageResolverContext resolve(IClassPackageDependencyReference reference, IClassPackageDescriptor descriptor) {
    return this.resolve(new ClassPackageResolverContext().pushNode(reference, descriptor)).popNode();
  }

  public ClassPackageResolverContext resolve(ClassPackageResolverContext context, IClassPackageDependencyReference reference) {
    return this.resolve(context.pushNode(reference, context.getDescriptor())).popNode();
  }
 
  @Override public IClassPackage getPackage(IClassPackageReference reference) {
    ClassPackageResolverContext ctx = new ClassPackageResolverContext(reference);
    ctx.setResolveDependencies(false);
   
    this.resolve(ctx);
   
    ClassPackageResolverNetworkNode node = ctx.getResolved(reference);
   
    if (node != null) {
      ClassPackageUtil.downloadDependencies(this, node);
      return node.createPackage();
    }
   
    return null;
  }

  @Override public IClassPackageDescriptor getDescriptor(IClassPackageReference reference) {
    ClassPackageResolverContext ctx = new ClassPackageResolverContext(reference);
    ctx.setResolveDependencies(false);
   
    this.resolve(ctx);
   
    ClassPackageResolverNetworkNode node = ctx.getResolved(reference);
   
    return node == null ? null : node.getDescriptor();
  }

  public ClassPackageResolverContext resolve(ClassPackageResolverContext ctx) {
    if ("net.sourceforge.javautil".equals( ctx.getCurrentDependency().getGroupId() )) {
      if ("classloader".equals( ctx.getCurrentDependency().getArtifactId() ) || "common".equals( ctx.getCurrentDependency().getArtifactId() )) {
        if (log.isDebug())
          log.debug("Ignoring implied reference: " + ctx.getCurrentDependency());
       
        return ctx;
      }
    }
   
    ClassPackageResolverNetworkNode node = ctx.getResolved(ctx.getCurrentDependency());
   
    if (node != null) {
      if (node.getReference().getVersion().compareTo(ctx.getCurrentDependency().getVersion()) < 0 && !node.isPrimary()) {
        log.warn("Upgrading from: " + node.getReference() + " to " + ctx.getCurrentDependency());
        ctx.remove(node);
      } else {
        ctx.relate(node);
        return ctx;
      }
    }
   
    if (ctx.getCurrentDependency().isSystemReference()) {
      ISystemArtifact artifact = ctx.getCurrentDependency().getSystemArtifact();
     
      ctx.setAvailable(this, null, artifact instanceof SystemDirectory ?
          new VirtualDirectoryClassSource((IVirtualDirectory)artifact) :
            new ZipClassSource(artifact.getRealArtifact()), ctx.getCurrentDependency().getSystemDescriptor());
     
      return ctx;
    }
   
    if (!this.resolveInternally(ctx)) {
      Map<String, IClassPackageRepositoryRemote> remoteRepositories = new LinkedHashMap<String, IClassPackageRepositoryRemote>();

      for (String name : this.remote.keySet()) {
        IClassPackageRepositoryRemote rr = remote.get(name);
        remoteRepositories.put(rr.getRepositoryURL().toExternalForm(), rr);
      }
     
      Set<IClassPackageDescriptor> cpdrs = ctx.getDescriptors();
     
      if (cpdrs.size() != 0) {
        for (IClassPackageDescriptor cpdr : cpdrs) {
          for (String url : cpdr.getRemoteRepositories()) {
            IClassPackageRepositoryRemote rr = cpdr.createRepository(url);
            remoteRepositories.put(rr.getRepositoryURL().toExternalForm(), rr);
          }
        }
      }
     
      if (!this.resolveRemotely(ctx, remoteRepositories)) {
        log.warn("Could not resolve: " + ctx.getCurrentDependency());
        ctx.setUnavailable();
      }
    }
    return ctx;
  }

  protected boolean resolveRemotely (ClassPackageResolverContext ctx, Map<String, IClassPackageRepositoryRemote> remoteRepositories) {
    IClassPackageDependencyReference reference = ctx.getCurrentDependency();
   
    List<IClassPackageRepositoryRemoteAttempt> attempts = this.repository.getLastRemoteAttempts(reference);
    if (attempts.size() > 0) {
      Set<String> urls = new HashSet<String>(remoteRepositories.keySet());
      for (String url : urls) {
        for (IClassPackageRepositoryRemoteAttempt attempt : attempts) {
          if (attempt.getId().equals(url)) {
            if (System.currentTimeMillis() - attempt.getStamp() < this.remoteAttemptInterval) {
              remoteRepositories.remove(url);
            }
          }
        }
      }
    }
   
    List<IClassPackageRepositoryRemote> attempted = new ArrayList<IClassPackageRepositoryRemote>();
    for (IClassPackageRepositoryRemote remote : remoteRepositories.values()) {
      log.warn("Attempting to locate " + reference + " @ " + remote.getRepositoryURL());
      IClassPackageDescriptor descriptor = this.getImportableRepository().getCachedRemotedDescriptor(this, remote, reference);
     
      if (descriptor == null && remote.contains(this, reference)) {
        descriptor = remote.getDescriptor(this, reference);
        this.getImportableRepository().cacheRemoteDescriptor(remote, descriptor);
      } else {
        log.warn("Locally cached copy found of " + reference);
      }
     
      if (descriptor != null) {
        if (descriptor.getRelocation() != null) {
          getImportableRepository().importPackage(remote, this, descriptor);
         
          ClassPackageDependencyReferenceImpl dep = new ClassPackageDependencyReferenceImpl(
            ClassPackageReferenceImpl.getRelocation(ctx.getCurrentDependency(), descriptor.getRelocation())
          );
         
          return this.resolveRemotely(ctx.popNode().pushNode(dep, null), remoteRepositories);
        }
       
        if (descriptor.isDescriptorOnly()) {
          ctx.setAvailable(this, repository, null, descriptor);
        } else {     
          ctx.setDownloadable(this, this.repository, remote);
        }
        this.resolveDependencies(ctx, descriptor);
        return true;
      } else {
        attempted.add(remote);
        this.repository.cacheRemoteAttempt(attempted, reference);
      }
    }
   
    return false;
  }

  protected boolean resolveInternally (ClassPackageResolverContext ctx) {
    IClassPackageRepositoryLocal found = this.repository;
    IClassPackageDescriptor descriptor = found.getDescriptor(this, ctx.getCurrentDependency());
    if (descriptor == null) {
      for (IClassPackageRepositoryLocal local : this.locals) {
        found = local;
        descriptor = local.getDescriptor(this, ctx.getCurrentDependency());
        if (descriptor != null) break;
      }
    }
    if (descriptor == null) return false;
   
    if (descriptor.getRelocation() != null) {
      ClassPackageReferenceImpl ref = ClassPackageReferenceImpl.getRelocation(ctx.getCurrentDependency(), descriptor.getRelocation());
      ClassPackageDependencyReferenceImpl dep = new ClassPackageDependencyReferenceImpl(ref);

      this.resolve(ctx.popNode().pushNode(dep, null));
      return ctx.getResolved(ref).getType() != Type.Unavailable;
    }
   
    ClassSource src = found.getMainClassSource(this, ctx.getCurrentDependency());
    if (src == null) {
      // This probably means the descriptor was downloaded, but the source was not
      if (descriptor.isDescriptorOnly()) {
        ctx.setAvailable(this, found, null, descriptor);
        return true;
      }
      return false;
    }
   
    ctx.setAvailable(this, found, src, descriptor);
   
    if (ctx.isResolveDependencies()) {
      printResolutionTree(ctx, "[STA] - Dependency Resolve");
      this.resolveDependencies(ctx, descriptor);
      printResolutionTree(ctx, "[END] - Dependency Resolve");
    }
   
    return true;
  }
 
  protected void resolveDependencies (ClassPackageResolverContext ctx, IClassPackageDescriptor descriptor) {
    if (descriptor != null) {
      for (IClassPackageDependencyReference reference : descriptor.getDependencies(Scope.Runtime)) {
        if (reference.getVersion() == null) {
          log.warn("Could not determine version for: " + reference);
          continue;
        }
       
        if (ctx.isExcluded(reference) || ctx.isInStack(reference)) continue;
        try {
          printResolutionTree(ctx, "[STA] : " + reference);
          this.resolve( ctx.pushNode(reference, descriptor) );
        } catch (Exception e) {
          log.warn("Failed dependency resolution for " + reference + ": " + e.getMessage(), e);
          ThrowableManagerRegistry.caught(e);
        } finally {
          ctx.popNode();
          printResolutionTree(ctx, "[END] : " + reference);
        }
      }
    }
  }
 
  protected void printResolutionTree (ClassPackageResolverContext ctx, String msg) {
    log.debug(StringUtil.repeat("->", ctx.getStackSize() - 1) + "[" + ctx.getDescriptor() + "]: " + msg);
  }
 
}
TOP

Related Classes of net.sourceforge.javautil.classloader.resolver.impl.ClassPackageResolverImpl

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.