protected static ClassLoadingMetaData createMetaData(
      PredeterminedManagedObjectAttachments deployment,
      String name,
      Version version,
      boolean useVersionOnPackages,
      Class<?>... packages) {
    MockClassLoadingMetaData classLoadingMetaData = new MockClassLoadingMetaData(name, version);

    classLoadingMetaData.setPaths(packages);

    CapabilitiesMetaData capabilities = classLoadingMetaData.getCapabilities();
    Capability capability = classLoadingMetaDataFactory.createModule(name, version);
    capabilities.addCapability(capability);

    if (packages != null) {
      for (Class<?> pkg : packages) {
        if (useVersionOnPackages)
          capability =
              classLoadingMetaDataFactory.createPackage(pkg.getPackage().getName(), version);
        else capability = classLoadingMetaDataFactory.createPackage(pkg.getPackage().getName());
        capabilities.addCapability(capability);
      }
    }

    classLoadingMetaData.setCapabilities(capabilities);
    return classLoadingMetaData;
  }
  protected static void addRequirePackage(
      ClassLoadingMetaData classLoadingMetaData, Class<?> pck, VersionRange versionRange) {
    RequirementsMetaData requirements = classLoadingMetaData.getRequirements();

    Requirement requirement =
        classLoadingMetaDataFactory.createRequirePackage(pck.getPackage().getName(), versionRange);
    requirements.addRequirement(requirement);
  }
  protected static void addRequireModule(
      ClassLoadingMetaData classLoadingMetaData, String moduleName, VersionRange versionRange) {
    RequirementsMetaData requirements = classLoadingMetaData.getRequirements();

    Requirement requirement =
        classLoadingMetaDataFactory.createRequireModule(moduleName, versionRange);
    requirements.addRequirement(requirement);
  }
/**
 * ClassLoaderDependenciesTest.
 *
 * @author <a href="*****@*****.**">Adrian Brock</a>
 * @version $Revision: 1.1 $
 */
public abstract class ClassLoaderDependenciesTest extends AbstractDeployerTest {
  private static ClassLoadingMetaDataFactory classLoadingMetaDataFactory =
      ClassLoadingMetaDataFactory.getInstance();

  private ClassLoaderSystem system;

  public static final String NameA = "A";
  public static final String NameB = "B";

  public static final List<String> NONE = Collections.emptyList();
  public static final List<String> A = makeList(NameA);
  public static final List<String> B = makeList(NameB);
  public static final List<String> AB = makeList(NameA, NameB);
  public static final List<String> BA = makeList(NameB, NameA);
  public static final List<String> BAA = makeList(NameB, NameA, NameA);
  public static final List<String> BABA = makeList(NameB, NameA, NameB, NameA);

  @SuppressWarnings("unchecked")
  protected static <T> List<T> makeList(T... objects) {
    List<T> result = new ArrayList<T>();
    for (T object : objects) result.add(object);
    return result;
  }

  protected AbstractClassLoaderDescribeDeployer deployer1;
  protected MockLevelClassLoaderSystemDeployer deployer2;

  protected ClassLoaderDependenciesTest(String name) {
    super(name);
  }

  protected Class<?> assertLoadClass(ClassLoader start, Class<?> reference) throws Exception {
    return assertLoadClass(start, reference, start);
  }

  protected Class<?> assertLoadClass(ClassLoader start, Class<?> reference, ClassLoader expected)
      throws Exception {
    Class<?> clazz = start.loadClass(reference.getName());
    if (expected != null) assertEquals(expected, clazz.getClassLoader());
    return clazz;
  }

  protected void assertLoadClassFail(ClassLoader start, Class<?> reference) throws Exception {
    try {
      start.loadClass(reference.getName());
      fail("Should not be here!");
    } catch (Exception e) {
      checkThrowable(ClassNotFoundException.class, e);
    }
  }

  protected void assertLoadClassIllegal(ClassLoader start, Class<?> reference) throws Exception {
    try {
      start.loadClass(reference.getName());
      fail("Should not be here!");
    } catch (Exception e) {
      checkThrowable(IllegalStateException.class, e);
    }
  }

  protected void assertNoClassLoader(DeploymentUnit unit) throws Exception {
    try {
      unit.getClassLoader();
      fail("Should not be here!");
    } catch (Exception e) {
      checkThrowable(IllegalStateException.class, e);
    }
  }

  protected static ClassLoadingMetaData addClassLoadingMetaData(
      PredeterminedManagedObjectAttachments deployment,
      String name,
      Version version,
      Class<?>... packages) {
    return addClassLoadingMetaData(deployment, name, version, false, packages);
  }

  protected static ClassLoadingMetaData addClassLoadingMetaData(
      PredeterminedManagedObjectAttachments deployment,
      String name,
      Version version,
      boolean useVersionOnPackages,
      Class<?>... packages) {
    ClassLoadingMetaData classLoadingMetaData =
        createMetaData(deployment, name, version, useVersionOnPackages, packages);
    addMetaData(deployment, classLoadingMetaData);
    return classLoadingMetaData;
  }

  protected static ClassLoadingMetaData createMetaData(
      PredeterminedManagedObjectAttachments deployment,
      String name,
      Version version,
      Class<?>... packages) {
    return createMetaData(deployment, name, version, false, packages);
  }

  protected static ClassLoadingMetaData createMetaData(
      PredeterminedManagedObjectAttachments deployment,
      String name,
      Version version,
      boolean useVersionOnPackages,
      Class<?>... packages) {
    MockClassLoadingMetaData classLoadingMetaData = new MockClassLoadingMetaData(name, version);

    classLoadingMetaData.setPaths(packages);

    CapabilitiesMetaData capabilities = classLoadingMetaData.getCapabilities();
    Capability capability = classLoadingMetaDataFactory.createModule(name, version);
    capabilities.addCapability(capability);

    if (packages != null) {
      for (Class<?> pkg : packages) {
        if (useVersionOnPackages)
          capability =
              classLoadingMetaDataFactory.createPackage(pkg.getPackage().getName(), version);
        else capability = classLoadingMetaDataFactory.createPackage(pkg.getPackage().getName());
        capabilities.addCapability(capability);
      }
    }

    classLoadingMetaData.setCapabilities(capabilities);
    return classLoadingMetaData;
  }

  protected static void addRequireModule(
      ClassLoadingMetaData classLoadingMetaData, String moduleName, VersionRange versionRange) {
    RequirementsMetaData requirements = classLoadingMetaData.getRequirements();

    Requirement requirement =
        classLoadingMetaDataFactory.createRequireModule(moduleName, versionRange);
    requirements.addRequirement(requirement);
  }

  protected static void addRequirePackage(
      ClassLoadingMetaData classLoadingMetaData, Class<?> pck, VersionRange versionRange) {
    RequirementsMetaData requirements = classLoadingMetaData.getRequirements();

    Requirement requirement =
        classLoadingMetaDataFactory.createRequirePackage(pck.getPackage().getName(), versionRange);
    requirements.addRequirement(requirement);
  }

  protected static void addMetaData(
      PredeterminedManagedObjectAttachments attachments, ClassLoadingMetaData md) {
    MutableAttachments mutable = (MutableAttachments) attachments.getPredeterminedManagedObjects();
    mutable.addAttachment(ClassLoadingMetaData.class, md);
  }

  protected ClassLoaderDomain assertDomain(String name) throws Exception {
    ClassLoaderDomain result = system.getDomain(name);
    assertNotNull("Expected domain " + name, result);
    return result;
  }

  protected void assertNoDomain(String name) throws Exception {
    assertNull("Did not expect domain " + name, system.getDomain(name));
  }

  protected DeployerClient getMainDeployer(Deployer... deployers) {
    ClassLoading classLoading = new ClassLoading();
    system = new DefaultClassLoaderSystem();
    system.getDefaultDomain().setParentPolicy(ParentPolicy.BEFORE_BUT_JAVA_ONLY);

    deployer1 = new MockClassLoaderDescribeDeployer();
    deployer1.setClassLoading(classLoading);

    deployer2 = new MockLevelClassLoaderSystemDeployer();
    deployer2.setClassLoading(classLoading);
    deployer2.setSystem(system);

    if (deployers != null && deployers.length > 0) {
      Deployer[] allDeployers = new Deployer[deployers.length + 2];
      allDeployers[0] = deployer1;
      allDeployers[1] = deployer2;
      System.arraycopy(deployers, 0, allDeployers, 2, deployers.length);
      return createMainDeployer(allDeployers);
    }

    return createMainDeployer(deployer1, deployer2);
  }
}