Rename java_prebuilt_library to java_import

And make it work like bazel's java_import, using a "jars" property
instead of "srcs", and allowing multiple jars to be listed.

Test: soong tests
Change-Id: Ida2ace6412bd77b4feb423646000a1401004e0ea
diff --git a/java/androidmk.go b/java/androidmk.go
index 9ccf856..92af0ed 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -15,17 +15,28 @@
 package java
 
 import (
+	"fmt"
+	"io"
+
 	"android/soong/android"
 )
 
 func (library *Library) AndroidMk() (ret android.AndroidMkData, err error) {
 	ret.Class = "JAVA_LIBRARIES"
 	ret.OutputFile = android.OptionalPathForPath(library.outputFile)
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
+		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := .jar")
+		return nil
+	})
 	return
 }
 
-func (prebuilt *Prebuilt) AndroidMk() (ret android.AndroidMkData, err error) {
+func (prebuilt *Import) AndroidMk() (ret android.AndroidMkData, err error) {
 	ret.Class = "JAVA_LIBRARIES"
-	ret.OutputFile = android.OptionalPathForPath(prebuilt.classpathFile)
+	ret.OutputFile = android.OptionalPathForPath(prebuilt.combinedClasspathFile)
+	ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
+		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := .jar")
+		return nil
+	})
 	return
 }
diff --git a/java/app.go b/java/app.go
index 8a221ef..ceb7791 100644
--- a/java/app.go
+++ b/java/app.go
@@ -231,18 +231,19 @@
 	aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
-		var depFile android.OptionalPath
+		var depFiles android.Paths
 		if sdkDep, ok := module.(sdkDependency); ok {
-			depFile = android.OptionalPathForPath(sdkDep.ClasspathFile())
+			depFiles = sdkDep.ClasspathFiles()
 		} else if javaDep, ok := module.(Dependency); ok {
 			if ctx.OtherModuleName(module) == "framework-res" {
-				depFile = android.OptionalPathForPath(javaDep.(*AndroidApp).exportPackage)
+				depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
 			}
 		}
-		if depFile.Valid() {
-			aaptFlags = append(aaptFlags, "-I "+depFile.String())
-			aaptDeps = append(aaptDeps, depFile.Path())
+
+		for _, dep := range depFiles {
+			aaptFlags = append(aaptFlags, "-I "+dep.String())
 		}
+		aaptDeps = append(aaptDeps, depFiles...)
 	})
 
 	sdkVersion := a.deviceProperties.Sdk_version
diff --git a/java/builder.go b/java/builder.go
index ed9d82c..2e41a60 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -237,11 +237,11 @@
 }
 
 func TransformPrebuiltJarToClasses(ctx android.ModuleContext,
-	prebuilt android.Path) (classJarSpec, resourceJarSpec jarSpec) {
+	subdir string, prebuilt android.Path) (classJarSpec, resourceJarSpec jarSpec) {
 
-	classDir := android.PathForModuleOut(ctx, "extracted/classes")
-	classFileList := android.PathForModuleOut(ctx, "extracted/classes.list")
-	resourceFileList := android.PathForModuleOut(ctx, "extracted/resources.list")
+	classDir := android.PathForModuleOut(ctx, subdir, "classes")
+	classFileList := android.PathForModuleOut(ctx, subdir, "classes.list")
+	resourceFileList := android.PathForModuleOut(ctx, subdir, "resources.list")
 
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:        extractPrebuilt,
diff --git a/java/java.go b/java/java.go
index f7191bf..37d959b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -20,6 +20,7 @@
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -37,7 +38,8 @@
 	android.RegisterModuleType("java_library_host", LibraryHostFactory)
 	android.RegisterModuleType("java_binary", BinaryFactory)
 	android.RegisterModuleType("java_binary_host", BinaryHostFactory)
-	android.RegisterModuleType("java_prebuilt_library", PrebuiltFactory)
+	android.RegisterModuleType("java_import", ImportFactory)
+	android.RegisterModuleType("java_import_host", ImportFactoryHost)
 	android.RegisterModuleType("android_prebuilt_sdk", SdkPrebuiltFactory)
 	android.RegisterModuleType("android_app", AndroidAppFactory)
 
@@ -144,7 +146,7 @@
 }
 
 type Dependency interface {
-	ClasspathFile() android.Path
+	ClasspathFiles() android.Paths
 	ClassJarSpecs() []jarSpec
 	ResourceJarSpecs() []jarSpec
 	AidlIncludeDirs() android.Paths
@@ -220,7 +222,7 @@
 }
 
 func (j *Module) collectDeps(ctx android.ModuleContext) (classpath android.Paths,
-	bootClasspath android.OptionalPath, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess android.OptionalPath,
+	bootClasspath android.Paths, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess android.OptionalPath,
 	aidlIncludeDirs android.Paths, srcFileLists android.Paths) {
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
@@ -239,11 +241,11 @@
 
 		switch tag {
 		case bootClasspathTag:
-			bootClasspath = android.OptionalPathForPath(dep.ClasspathFile())
+			bootClasspath = append(bootClasspath, dep.ClasspathFiles()...)
 		case libTag:
-			classpath = append(classpath, dep.ClasspathFile())
+			classpath = append(classpath, dep.ClasspathFiles()...)
 		case staticLibTag:
-			classpath = append(classpath, dep.ClasspathFile())
+			classpath = append(classpath, dep.ClasspathFiles()...)
 			classJarSpecs = append(classJarSpecs, dep.ClassJarSpecs()...)
 			resourceJarSpecs = append(resourceJarSpecs, dep.ResourceJarSpecs()...)
 		case frameworkResTag:
@@ -296,9 +298,9 @@
 
 	var deps android.Paths
 
-	if bootClasspath.Valid() {
-		flags.bootClasspath = "-bootclasspath " + bootClasspath.String()
-		deps = append(deps, bootClasspath.Path())
+	if len(bootClasspath) > 0 {
+		flags.bootClasspath = "-bootclasspath " + strings.Join(bootClasspath.Strings(), ":")
+		deps = append(deps, bootClasspath...)
 	}
 
 	if len(classpath) > 0 {
@@ -350,7 +352,7 @@
 			return
 		}
 
-		classes, _ := TransformPrebuiltJarToClasses(ctx, outputFile)
+		classes, _ := TransformPrebuiltJarToClasses(ctx, "jarjar_extracted", outputFile)
 		classJarSpecs = []jarSpec{classes}
 	}
 
@@ -399,8 +401,8 @@
 
 var _ Dependency = (*Library)(nil)
 
-func (j *Module) ClasspathFile() android.Path {
-	return j.classpathFile
+func (j *Module) ClasspathFiles() android.Paths {
+	return android.Paths{j.classpathFile}
 }
 
 func (j *Module) ClassJarSpecs() []jarSpec {
@@ -519,63 +521,92 @@
 // Java prebuilts
 //
 
-type Prebuilt struct {
+type ImportProperties struct {
+	Jars []string
+}
+
+type Import struct {
 	android.ModuleBase
 	prebuilt android.Prebuilt
 
-	classpathFile                   android.Path
+	properties ImportProperties
+
+	classpathFiles                  android.Paths
+	combinedClasspathFile           android.Path
 	classJarSpecs, resourceJarSpecs []jarSpec
 }
 
-func (j *Prebuilt) Prebuilt() *android.Prebuilt {
+func (j *Import) Prebuilt() *android.Prebuilt {
 	return &j.prebuilt
 }
 
-func (j *Prebuilt) Name() string {
+func (j *Import) PrebuiltSrcs() []string {
+	return j.properties.Jars
+}
+
+func (j *Import) Name() string {
 	return j.prebuilt.Name(j.ModuleBase.Name())
 }
 
-func (j *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
 }
 
-func (j *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	prebuilt := j.prebuilt.Path(ctx)
+func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars)
 
-	classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
+	for i, prebuilt := range j.classpathFiles {
+		subdir := "extracted" + strconv.Itoa(i)
+		classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, subdir, prebuilt)
+		j.classJarSpecs = append(j.classJarSpecs, classJarSpec)
+		j.resourceJarSpecs = append(j.resourceJarSpecs, resourceJarSpec)
+	}
 
-	j.classpathFile = prebuilt
-	j.classJarSpecs = []jarSpec{classJarSpec}
-	j.resourceJarSpecs = []jarSpec{resourceJarSpec}
-	ctx.InstallFileName(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.classpathFile)
+	j.combinedClasspathFile = TransformClassesToJar(ctx, j.classJarSpecs, android.OptionalPath{})
+
+	ctx.InstallFileName(android.PathForModuleInstall(ctx, "framework"),
+		ctx.ModuleName()+".jar", j.combinedClasspathFile)
 }
 
-var _ Dependency = (*Prebuilt)(nil)
+var _ Dependency = (*Import)(nil)
 
-func (j *Prebuilt) ClasspathFile() android.Path {
-	return j.classpathFile
+func (j *Import) ClasspathFiles() android.Paths {
+	return j.classpathFiles
 }
 
-func (j *Prebuilt) ClassJarSpecs() []jarSpec {
+func (j *Import) ClassJarSpecs() []jarSpec {
 	return j.classJarSpecs
 }
 
-func (j *Prebuilt) ResourceJarSpecs() []jarSpec {
+func (j *Import) ResourceJarSpecs() []jarSpec {
 	return j.resourceJarSpecs
 }
 
-func (j *Prebuilt) AidlIncludeDirs() android.Paths {
+func (j *Import) AidlIncludeDirs() android.Paths {
 	return nil
 }
 
-func PrebuiltFactory() android.Module {
-	module := &Prebuilt{}
+var _ android.PrebuiltInterface = (*Import)(nil)
 
-	module.AddProperties(&module.prebuilt.Properties)
+func ImportFactory() android.Module {
+	module := &Import{}
 
+	module.AddProperties(&module.properties)
+
+	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	return module
 }
 
+func ImportFactoryHost() android.Module {
+	module := &Import{}
+
+	module.AddProperties(&module.properties)
+
+	android.InitPrebuiltModule(module, &module.properties.Jars)
+	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+	return module
+}
+
 //
 // SDK java prebuilts (.jar containing resources plus framework.aidl)
 //
@@ -592,7 +623,7 @@
 }
 
 type sdkPrebuilt struct {
-	Prebuilt
+	Import
 
 	sdkProperties sdkPrebuiltProperties
 
@@ -600,7 +631,7 @@
 }
 
 func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	j.Prebuilt.GenerateAndroidBuildActions(ctx)
+	j.Import.GenerateAndroidBuildActions(ctx)
 
 	j.aidlPreprocessed = android.OptionalPathForModuleSrc(ctx, j.sdkProperties.Aidl_preprocessed)
 }
@@ -612,10 +643,9 @@
 func SdkPrebuiltFactory() android.Module {
 	module := &sdkPrebuilt{}
 
-	module.AddProperties(
-		&module.prebuilt.Properties,
-		&module.sdkProperties)
+	module.AddProperties(&module.sdkProperties)
 
+	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	return module
 }
diff --git a/java/java_test.go b/java/java_test.go
index de3be49..eb116c9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -55,7 +55,7 @@
 	ctx := android.NewTestContext()
 	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
-	ctx.RegisterModuleType("java_prebuilt_library", android.ModuleFactoryAdaptor(PrebuiltFactory))
+	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
 	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
@@ -209,14 +209,14 @@
 			static_libs: ["baz"],
 		}
 
-		java_prebuilt_library {
+		java_import {
 			name: "bar",
-			srcs: ["a.jar"],
+			jars: ["a.jar"],
 		}
 
-		java_prebuilt_library {
+		java_import {
 			name: "baz",
-			srcs: ["b.jar"],
+			jars: ["b.jar"],
 		}
 		`)
 
@@ -228,7 +228,7 @@
 		t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], bar)
 	}
 
-	baz := filepath.Join(buildDir, ".intermediates", "baz", "extracted", "classes.list")
+	baz := filepath.Join(buildDir, ".intermediates", "baz", "extracted0", "classes.list")
 	if !strings.Contains(jar.Args["jarArgs"], baz) {
 		t.Errorf("foo jarArgs %v does not contain %q", jar.Args["jarArgs"], baz)
 	}