@SuppressWarnings("restriction")
  public IStatus getRawArtifact(
      IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
    // TODO consolidate this logic with getArtifactFile
    GAV gav = getGAV(descriptor);
    String classifier = RepositoryLayoutHelper.getClassifier(descriptor.getProperties());
    String extension = RepositoryLayoutHelper.getExtension(descriptor.getProperties());

    if ("packed".equals(descriptor.getProperty(IArtifactDescriptor.FORMAT))) {
      classifier = "pack200";
      extension = "jar.pack.gz";
    }

    try {
      InputStream source = contentLocator.getContents(gav, classifier, extension);

      // copy to destination and close source
      FileUtils.copyStream(source, true, destination, false);
    } catch (IOException e) {
      return new Status(
          IStatus.ERROR,
          Activator.ID,
          "I/O exception while reading artifact "
              + gav.toExternalForm()
              + ":"
              + classifier
              + ":"
              + extension,
          e);
    }
    return Status.OK_STATUS;
  }
  public File getArtifactFile(IArtifactDescriptor descriptor) {
    // TODO consolidate this logic with getRawArtifact
    GAV gav = getGAV(descriptor);
    String classifier = RepositoryLayoutHelper.getClassifier(descriptor.getProperties());
    String extension = RepositoryLayoutHelper.getExtension(descriptor.getProperties());

    // TODO where does this magic come from? the logic behind this should be made explicit and e.g.
    // moved into a separate class
    // TODO bring together with other pack200 magic in
    // org.eclipse.tycho.p2.maven.repository.MavenArtifactRepository.downloadArtifact(IArtifactDescriptor, OutputStream)
    if ("packed".equals(descriptor.getProperty(IArtifactDescriptor.FORMAT))) {
      classifier = "pack200";
      extension = "jar.pack.gz";
    }

    return contentLocator.getLocalArtifactLocation(gav, classifier, extension);
  }