Cleanup of the Resource class. Make publicly available Resource an interface.

Change-Id: Ia9c06af5d8442d357ed4be9f26ce21dee09b4989
diff --git a/src/main/java/com/android/tools/r8/Resource.java b/src/main/java/com/android/tools/r8/Resource.java
index 8ea23d1..74236a0 100644
--- a/src/main/java/com/android/tools/r8/Resource.java
+++ b/src/main/java/com/android/tools/r8/Resource.java
@@ -8,20 +8,16 @@
 import java.io.InputStream;
 
 /** Represents application resources. */
-public abstract class Resource {
+public interface Resource {
 
   /** Application resource kind. */
-  public enum Kind {
+  enum Kind {
     PROGRAM, CLASSPATH, LIBRARY
   }
 
-  /** Kind of the resource. */
-  public final Kind kind;
-
-  protected Resource(Kind kind) {
-    this.kind = kind;
-  }
+  /** Get the kind of the resource. */
+  Kind getKind();
 
   /** Get the resource as a stream. */
-  public abstract InputStream getStream(Closer closer) throws IOException;
+  InputStream getStream(Closer closer) throws IOException;
 }
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 672f6bd..8ab8921 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -10,6 +10,7 @@
 import static com.android.tools.r8.dex.Constants.DEFAULT_ANDROID_API;
 import static com.android.tools.r8.utils.FileUtils.DEFAULT_DEX_FILENAME;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -87,20 +88,20 @@
     JarClassFileReader reader = new JarClassFileReader(
         application, builder::addClassIgnoringLibraryDuplicates);
     for (InternalResource input : inputApp.getClassProgramResources()) {
-      reader.read(DEFAULT_DEX_FILENAME, InternalResource.Kind.PROGRAM, input.getStream(closer));
+      reader.read(DEFAULT_DEX_FILENAME, Resource.Kind.PROGRAM, input.getStream(closer));
     }
     for (InternalResource input : inputApp.getClassClasspathResources()) {
       if (options.lazyClasspathLoading && input.getClassDescriptor() != null) {
         addLazyLoader(application, builder, input);
       } else {
-        reader.read(DEFAULT_DEX_FILENAME, InternalResource.Kind.CLASSPATH, input.getStream(closer));
+        reader.read(DEFAULT_DEX_FILENAME, Resource.Kind.CLASSPATH, input.getStream(closer));
       }
     }
     for (InternalResource input : inputApp.getClassLibraryResources()) {
       if (options.lazyLibraryLoading && input.getClassDescriptor() != null) {
         addLazyLoader(application, builder, input);
       } else {
-        reader.read(DEFAULT_DEX_FILENAME, InternalResource.Kind.LIBRARY, input.getStream(closer));
+        reader.read(DEFAULT_DEX_FILENAME, Resource.Kind.LIBRARY, input.getStream(closer));
       }
     }
   }
@@ -129,16 +130,16 @@
       for (InternalResource input : dexProgramSources) {
         DexFile file = new DexFile(input.getStream(closer));
         computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file);
-        fileReaders.add(new DexFileReader(file, InternalResource.Kind.PROGRAM, itemFactory));
+        fileReaders.add(new DexFileReader(file, Resource.Kind.PROGRAM, itemFactory));
       }
       for (InternalResource input : dexClasspathSources) {
         DexFile file = new DexFile(input.getStream(closer));
-        fileReaders.add(new DexFileReader(file, InternalResource.Kind.CLASSPATH, itemFactory));
+        fileReaders.add(new DexFileReader(file, Resource.Kind.CLASSPATH, itemFactory));
       }
       for (InternalResource input : dexLibrarySources) {
         DexFile file = new DexFile(input.getStream(closer));
         computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file);
-        fileReaders.add(new DexFileReader(file, InternalResource.Kind.LIBRARY, itemFactory));
+        fileReaders.add(new DexFileReader(file, Resource.Kind.LIBRARY, itemFactory));
       }
       options.minApiLevel = computedMinApiLevel;
       for (DexFileReader reader : fileReaders) {
diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
index bdafdc4..a38d397 100644
--- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
@@ -8,6 +8,7 @@
 import static com.android.tools.r8.utils.EncodedValueUtils.parseSigned;
 import static com.android.tools.r8.utils.EncodedValueUtils.parseUnsigned;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.code.InstructionFactory;
 import com.android.tools.r8.graph.Descriptor;
@@ -68,12 +69,12 @@
   private DexFile file;
   private final Segment[] segments;
   private int[] stringIDs;
-  private final InternalResource.Kind fileKind;
+  private final Resource.Kind fileKind;
 
   public static Segment[] parseMapFrom(Path file) throws IOException {
     DexFileReader reader =
         new DexFileReader(
-            new DexFile(file.toString()), InternalResource.Kind.PROGRAM, new DexItemFactory());
+            new DexFile(file.toString()), Resource.Kind.PROGRAM, new DexItemFactory());
     return reader.parseMap();
   }
 
@@ -99,7 +100,7 @@
   private final DexItemFactory dexItemFactory;
 
   public DexFileReader(
-      DexFile file, InternalResource.Kind fileKind, DexItemFactory dexItemFactory) {
+      DexFile file, Resource.Kind fileKind, DexItemFactory dexItemFactory) {
     this.file = file;
     this.dexItemFactory = dexItemFactory;
     file.setByteOrder();
@@ -113,7 +114,7 @@
   }
 
   void addCodeItemsTo() {
-    if (fileKind == InternalResource.Kind.LIBRARY) {
+    if (fileKind == Resource.Kind.LIBRARY) {
       // Ignore contents of library files.
       return;
     }
@@ -638,13 +639,13 @@
                 directMethodsSize,
                 annotationsDirectory.methods,
                 annotationsDirectory.parameters,
-                fileKind != InternalResource.Kind.PROGRAM);
+                fileKind != Resource.Kind.PROGRAM);
         virtualMethods =
             readMethods(
                 virtualMethodsSize,
                 annotationsDirectory.methods,
                 annotationsDirectory.parameters,
-                fileKind != InternalResource.Kind.PROGRAM);
+                fileKind != Resource.Kind.PROGRAM);
       }
       clazz = DexClass.factoryForResourceKind(fileKind).create(
           type,
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index bff12e7..232019c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
@@ -180,7 +181,7 @@
   }
 
   /** Get a class factory for a particular resource kind */
-  public static Factory factoryForResourceKind(InternalResource.Kind kind) {
+  public static Factory factoryForResourceKind(Resource.Kind kind) {
     switch (kind) {
       case PROGRAM:
         return DexProgramClass::new;
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 07a7231..1673470 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -7,6 +7,7 @@
 import static org.objectweb.asm.Opcodes.ACC_DEPRECATED;
 import static org.objectweb.asm.Opcodes.ASM5;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
@@ -58,7 +59,7 @@
     this.classConsumer = classConsumer;
   }
 
-  public void read(String file, InternalResource.Kind kind, InputStream input) throws IOException {
+  public void read(String file, Resource.Kind kind, InputStream input) throws IOException {
     ClassReader reader = new ClassReader(input);
     reader.accept(new CreateDexClassVisitor(
         file, kind, reader.b, application, classConsumer), SKIP_FRAMES);
@@ -92,7 +93,7 @@
 
   private static class CreateDexClassVisitor extends ClassVisitor {
     private final String file;
-    private final InternalResource.Kind kind;
+    private final Resource.Kind kind;
     private final JarApplicationReader application;
     private final Consumer<DexClass> classConsumer;
     private final ReparseContext context = new ReparseContext();
@@ -115,7 +116,7 @@
 
     public CreateDexClassVisitor(
         String file,
-        InternalResource.Kind kind,
+        Resource.Kind kind,
         byte[] classCache,
         JarApplicationReader application,
         Consumer<DexClass> classConsumer) {
@@ -259,7 +260,7 @@
           instanceFields.toArray(new DexEncodedField[instanceFields.size()]),
           directMethods.toArray(new DexEncodedMethod[directMethods.size()]),
           virtualMethods.toArray(new DexEncodedMethod[virtualMethods.size()]));
-      if (kind == InternalResource.Kind.PROGRAM) {
+      if (kind == Resource.Kind.PROGRAM) {
         context.owner = clazz.asProgramClass();
       }
       classConsumer.accept(clazz);
@@ -497,7 +498,7 @@
       Code code = null;
       if (!flags.isAbstract()
           && !flags.isNative()
-          && parent.kind == InternalResource.Kind.PROGRAM) {
+          && parent.kind == Resource.Kind.PROGRAM) {
         code = new JarCode(method, parent.context, parent.application);
       }
       DexAnnotationSetRefList parameterAnnotationSets;
diff --git a/src/main/java/com/android/tools/r8/graph/LazyClassFileLoader.java b/src/main/java/com/android/tools/r8/graph/LazyClassFileLoader.java
index 01bf132..d5fa09a 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyClassFileLoader.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyClassFileLoader.java
@@ -6,6 +6,7 @@
 
 import static com.android.tools.r8.utils.FileUtils.DEFAULT_DEX_FILENAME;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.utils.InternalResource;
@@ -56,17 +57,17 @@
 
   @Override
   public boolean isProgramClass() {
-    return resource.kind == InternalResource.Kind.PROGRAM;
+    return resource.getKind() == Resource.Kind.PROGRAM;
   }
 
   @Override
   public boolean isClasspathClass() {
-    return resource.kind == InternalResource.Kind.CLASSPATH;
+    return resource.getKind() == Resource.Kind.CLASSPATH;
   }
 
   @Override
   public boolean isLibraryClass() {
-    return resource.kind == InternalResource.Kind.LIBRARY;
+    return resource.getKind() == Resource.Kind.LIBRARY;
   }
 
   // Loads the class from the resource. Synchronized on `this` to avoid
@@ -80,7 +81,7 @@
 
     try (Closer closer = Closer.create()) {
       JarClassFileReader reader = new JarClassFileReader(this.reader, this::addClass);
-      reader.read(DEFAULT_DEX_FILENAME, resource.kind, resource.getStream(closer));
+      reader.read(DEFAULT_DEX_FILENAME, resource.getKind(), resource.getStream(closer));
     } catch (IOException e) {
       throw new CompilationError("Failed to load class: " + resource.getClassDescriptor(), e);
     }
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 53680ee..6d46efe 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -8,6 +8,7 @@
 import static com.android.tools.r8.utils.FileUtils.isClassFile;
 import static com.android.tools.r8.utils.FileUtils.isDexFile;
 
+import com.android.tools.r8.Resource;
 import com.android.tools.r8.errors.CompilationError;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.ByteStreams;
@@ -135,39 +136,39 @@
 
   /** Get input streams for all dex program resources. */
   public List<InternalResource> getDexProgramResources() {
-    return filter(dexSources, InternalResource.Kind.PROGRAM);
+    return filter(dexSources, Resource.Kind.PROGRAM);
   }
 
   /** Get input streams for all Java-bytecode program resources. */
   public List<InternalResource> getClassProgramResources() {
-    return filter(classSources, InternalResource.Kind.PROGRAM);
+    return filter(classSources, Resource.Kind.PROGRAM);
   }
 
   /** Get input streams for all dex program classpath resources. */
   public List<InternalResource> getDexClasspathResources() {
-    return filter(dexSources, InternalResource.Kind.CLASSPATH);
+    return filter(dexSources, Resource.Kind.CLASSPATH);
   }
 
   /** Get input streams for all Java-bytecode classpath resources. */
   public List<InternalResource> getClassClasspathResources() {
-    return filter(classSources, InternalResource.Kind.CLASSPATH);
+    return filter(classSources, Resource.Kind.CLASSPATH);
   }
 
   /** Get input streams for all dex library resources. */
   public List<InternalResource> getDexLibraryResources() {
-    return filter(dexSources, InternalResource.Kind.LIBRARY);
+    return filter(dexSources, Resource.Kind.LIBRARY);
   }
 
   /** Get input streams for all Java-bytecode library resources. */
   public List<InternalResource> getClassLibraryResources() {
-    return filter(classSources, InternalResource.Kind.LIBRARY);
+    return filter(classSources, Resource.Kind.LIBRARY);
   }
 
   private List<InternalResource> filter(
-      List<InternalResource> resources, InternalResource.Kind kind) {
+      List<InternalResource> resources, Resource.Kind kind) {
     List<InternalResource> out = new ArrayList<>(resources.size());
     for (InternalResource resource : resources) {
-      if (kind == resource.kind) {
+      if (kind == resource.getKind()) {
         out.add(resource);
       }
     }
@@ -390,7 +391,7 @@
     public Builder addProgramDirectory(Path directory) throws IOException {
       File[] resources = directory.toFile().listFiles(file -> isDexFile(file.toPath()));
       for (File source : resources) {
-        addFile(source.toPath(), InternalResource.Kind.PROGRAM);
+        addFile(source.toPath(), Resource.Kind.PROGRAM);
       }
       File mapFile = new File(directory.toFile(), DEFAULT_PROGUARD_MAP_FILE);
       if (mapFile.exists()) {
@@ -409,7 +410,7 @@
     /** Add program file resources. */
     public Builder addProgramFiles(Collection<Path> files) throws IOException {
       for (Path file : files) {
-        addFile(file, InternalResource.Kind.PROGRAM);
+        addFile(file, Resource.Kind.PROGRAM);
       }
       return this;
     }
@@ -424,7 +425,7 @@
     /** Add classpath file resources. */
     public Builder addClasspathFiles(Collection<Path> files) throws IOException {
       for (Path file : files) {
-        addFile(file, InternalResource.Kind.CLASSPATH);
+        addFile(file, Resource.Kind.CLASSPATH);
       }
       return this;
     }
@@ -439,7 +440,7 @@
     /** Add library file resources. */
     public Builder addLibraryFiles(Collection<Path> files) throws IOException {
       for (Path file : files) {
-        addFile(file, InternalResource.Kind.LIBRARY);
+        addFile(file, Resource.Kind.LIBRARY);
       }
       return this;
     }
@@ -454,7 +455,7 @@
     /** Add dex program-data. */
     public Builder addDexProgramData(Collection<byte[]> data) {
       for (byte[] datum : data) {
-        dexSources.add(InternalResource.fromBytes(InternalResource.Kind.PROGRAM, datum));
+        dexSources.add(InternalResource.fromBytes(Resource.Kind.PROGRAM, datum));
       }
       return this;
     }
@@ -469,7 +470,7 @@
     /** Add Java-bytecode program data. */
     public Builder addClassProgramData(Collection<byte[]> data) {
       for (byte[] datum : data) {
-        classSources.add(InternalResource.fromBytes(InternalResource.Kind.PROGRAM, datum));
+        classSources.add(InternalResource.fromBytes(Resource.Kind.PROGRAM, datum));
       }
       return this;
     }
@@ -522,7 +523,7 @@
           mainDexList);
     }
 
-    private void addFile(Path file, InternalResource.Kind kind) throws IOException {
+    private void addFile(Path file, Resource.Kind kind) throws IOException {
       if (!Files.exists(file)) {
         throw new FileNotFoundException("Non-existent input file: " + file);
       }
@@ -537,7 +538,7 @@
       }
     }
 
-    private void addArchive(Path archive, InternalResource.Kind kind) throws IOException {
+    private void addArchive(Path archive, Resource.Kind kind) throws IOException {
       assert isArchive(archive);
       boolean containsDexData = false;
       boolean containsClassData = false;
diff --git a/src/main/java/com/android/tools/r8/utils/InternalResource.java b/src/main/java/com/android/tools/r8/utils/InternalResource.java
index 14656e6..2d9bdb9 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalResource.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalResource.java
@@ -18,15 +18,22 @@
  * from the javadoc for the D8 API. If we decide to expose those methods
  * later the split between Resource and InternalResource can be removed.
  */
-public abstract class InternalResource extends Resource {
+public abstract class InternalResource implements Resource {
+
+  private final Kind kind;
 
   private InternalResource(Kind kind) {
-    super(kind);
+    this.kind = kind;
   }
 
   /** Returns class descriptor if known, otherwise returns null. */
   public abstract String getClassDescriptor();
 
+  /** Get the kind of the resource. */
+  public Kind getKind() {
+    return kind;
+  }
+
   /** Create an application resource for a given file and kind. */
   public static InternalResource fromFile(Kind kind, Path file) {
     return new FileResource(kind, file);