public DependentLoaderImplementation cloneLoader(
      DependentLoader loader, String aditionalDependency) {
    DependentLoaderImplementation otherAsImplementation = (DependentLoaderImplementation) loader;

    DependentLoaderImplementation newLoader =
        new DependentLoaderImplementation(
            otherAsImplementation.artifact,
            loader.getURLs(),
            exposed,
            otherAsImplementation.parent);
    newLoader.dependencies = otherAsImplementation.dependencies;

    if (!"".equals(aditionalDependency)) {
      DependentLoaderImplementation dependency =
          enshureDependencyJarLoaded(otherAsImplementation.artifact, aditionalDependency);
      ArrayList<DependentLoaderImplementation> depList =
          new ArrayList<DependentLoaderImplementation>();
      for (DependentLoaderImplementation dependentLoaderImplementation : newLoader.dependencies) {
        depList.add(dependentLoaderImplementation);
      }
      depList.add(dependency);
      newLoader.setDependencies(depList.toArray(new DependentLoaderImplementation[depList.size()]));
    }
    visitLoader(newLoader);
    return newLoader;
  }
  public void connect(String connectThis, String toThis) {
    List<DependentLoaderImplementation> connectLoaders =
        new ArrayList<DependentLoaderImplementation>();
    List<DependentLoaderImplementation> toLoaders = new ArrayList<DependentLoaderImplementation>();

    for (String stringKey : loaderMap.keySet()) {
      if (stringKey.startsWith(connectThis)) {
        connectLoaders.add(loaderMap.get(stringKey));
      }
      if (stringKey.startsWith(toThis)) {
        toLoaders.add(loaderMap.get(stringKey));
      }
    }

    for (DependentLoaderImplementation connectLoader : connectLoaders) {
      DependentLoaderImplementation[] newDependents =
          new DependentLoaderImplementation[connectLoader.dependencies.length + toLoaders.size()];

      int i = 0;
      for (DependentLoaderImplementation oldDependency : connectLoader.dependencies) {
        newDependents[i++] = oldDependency;
      }
      for (DependentLoaderImplementation toLoader : toLoaders) {
        newDependents[i++] = toLoader;
      }
      connectLoader.dependencies = newDependents;
    }
  }
  public DependentLoaderImplementation nameArtifact(
      Artifact artifactId, URL[] jar, Object... dependsOn) {
    DependentLoaderImplementation theLoader = null;
    if (jar == null)
      theLoader = new DependentLoaderImplementation(artifactId, exposed, parentLoader);
    else theLoader = new DependentLoaderImplementation(artifactId, jar, exposed, parentLoader);

    List<DependentLoaderImplementation> dependencies =
        new ArrayList<DependentLoaderImplementation>();

    for (Object dependency : dependsOn) {
      if (dependency instanceof DependentLoaderImplementation) {
        dependencies.add((DependentLoaderImplementation) dependency);
      } else if (dependency instanceof String) {
        DependentLoaderImplementation candidate =
            enshureDependencyJarLoaded(artifactId, new DefaultArtifact((String) dependency));
        if (candidate != null) dependencies.add((DependentLoaderImplementation) dependency);
      } else if (dependency instanceof Artifact) {
        DependentLoaderImplementation candidate =
            enshureDependencyJarLoaded(artifactId, (Artifact) dependency);
        if (candidate != null) dependencies.add((DependentLoaderImplementation) dependency);
      }
    }
    theLoader.setDependencies(
        dependencies.toArray(new DependentLoaderImplementation[dependencies.size()]));

    if (artifactId != null) {
      assert (theLoader != null);
      setLoader(theLoader);
      assert (loaderMap.get(toString(artifactId)) != null);
    }
    visitLoader(theLoader);
    return theLoader;
  }
  public DependentLoaderImplementation cloneLoader(DependentLoader loader) {
    DependentLoaderImplementation otherAsImplementation = (DependentLoaderImplementation) loader;
    DependentLoaderImplementation newLoader =
        new DependentLoaderImplementation(
            otherAsImplementation.artifact,
            loader.getURLs(),
            exposed,
            otherAsImplementation.parent);
    newLoader.setDependencies(otherAsImplementation.dependencies);

    visitLoader(newLoader);
    return newLoader;
  }
 @Override
 public void registerUnpackedJar(String what, String... where) {
   DependentLoaderImplementation loader =
       DependentLoaderImplementation.createClassFileLoader(what, where, exposed, parentLoader);
   File[] files = new File[where.length];
   int i = 0;
   for (String directory : where) {
     files[i] = new File(directory);
     i++;
   }
   setLoader(loader);
   overridingLoaders.add(new Wildcards(what, loader, files));
 }
 private void getCompileClasspath(
     List<String> list, Set<Artifact> cutoff, DependentLoaderImplementation depLoader) {
   if (!cutoff.contains(depLoader.artifact)) {
     cutoff.add(depLoader.artifact);
     DependentLoaderImplementation depLoaderImpl = enshureJarLoaded(depLoader.artifact);
     for (URL url : depLoader.getURLs()) {
       try {
         String path = Paths.get(url.toURI()).toFile().getAbsolutePath();
         if (!list.contains(path)) {
           list.add(path);
         }
       } catch (Exception e) {
       }
     }
     for (DependentLoaderImplementation dep : depLoaderImpl.dependencies) {
       getCompileClasspath(list, cutoff, dep);
     }
   }
 }
 void setLoader(DependentLoaderImplementation loader) {
   synchronized (loaderMap) {
     this.loaderMap.put(loader.getArtifact(), loader);
   }
 }
  public DependentLoaderImplementation enshureJarLoaded(Artifact _artifactId) {
    Artifact artifactId = unify(_artifactId);

    if ("dependent".equals(artifactId.getArtifactId())
        && "no.dbwatch".equals(artifactId.getGroupId())) {
      return null;
    }
    DependentLoaderImplementation theLoader = findOverride(artifactId);
    if (theLoader != null) {
      visitLoader(theLoader);
      return theLoader;
    }
    if (loaderMap.containsKey(toString(artifactId))) return loaderMap.get(toString(artifactId));
    // Fetch jar and dependencies.
    OutputBouble bouble = OutputBouble.push();

    try {
      Result<File> localFileName = dependencyManager.getLocalFile(artifactId);

      if (localFileName.success())
        theLoader =
            new DependentLoaderImplementation(
                artifactId,
                localFileName.val.getAbsoluteFile().toURI().toURL(),
                exposed,
                parentLoader);
      else theLoader = new DependentLoaderImplementation(artifactId, exposed, parentLoader);
      setLoader(theLoader);

      List<Artifact> dependencies = dependencyManager.getDirectDependencies(artifactId);

      DependentLoaderImplementation[] actualDependencies =
          new DependentLoaderImplementation[dependencies.size() + theLoader.dependencies.length];
      int i = 0;
      for (DependentLoaderImplementation dependencyFromConf : theLoader.dependencies) {
        actualDependencies[i++] = dependencyFromConf;
      }
      for (Artifact dependencyId : dependencies) {

        DependentLoaderImplementation loader = enshureDependencyJarLoaded(artifactId, dependencyId);
        if (loader == null) {
          OutputBouble.logFile.println(artifactId.toString() + ":");
          OutputBouble.logFile.println("\t Missing dependency " + dependencyId.toString());
          OutputBouble.logFile.println("\t Ignoring");
        } else {
          actualDependencies[i++] = loader;
        }
      }
      if (actualDependencies.length > i) {
        actualDependencies = Arrays.copyOf(actualDependencies, i);
      }

      theLoader.setDependencies(actualDependencies);

      extraDependencies.loaderAdded(theLoader);

      visitLoader(theLoader);
      return theLoader;
    } catch (Exception e) {
      OutputBouble.reportError(e);
      return theLoader;
    } finally {
      bouble.pop();
      if (bouble.isError) bouble.writeToParent();
    }
    // return null;
  }