ADT: Support class folders during build.

Change-Id: If1d6840082f96dd98c8be0658c6ce157b4801bd3
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidPrintStream.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidPrintStream.java
index 5323742..9eac361 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidPrintStream.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidPrintStream.java
@@ -60,9 +60,10 @@
         String tag = getMessageTag(mProject != null ? mProject.getName() : null);
 
         print(tag);
-        print(": ");
+        print(" "); //$NON-NLS-1$
         if (mPrefix != null) {
             print(mPrefix);
+            print(" "); //$NON-NLS-1$
         }
 
         // then write the regular message
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
index b43571a..982ca33 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
@@ -278,52 +278,60 @@
             writeStandardResources(apkBuilder, javaProject, referencedJavaProjects);
 
             // Now we write the standard resources from the external jars
-            for (String libraryOsPath : getExternalJars(resMarker)) {
-                JarStatus jarStatus = apkBuilder.addResourcesFromJar(new File(libraryOsPath));
+            for (String libraryOsPath : getExternalDependencies(resMarker)) {
+                File libFile = new File(libraryOsPath);
+                if (libFile.isFile()) {
+                    JarStatus jarStatus = apkBuilder.addResourcesFromJar(new File(libraryOsPath));
 
-                // check if we found native libraries in the external library. This
-                // constitutes an error or warning depending on if they are in lib/
-                if (jarStatus.getNativeLibs().size() > 0) {
-                    String libName = new File(libraryOsPath).getName();
+                    // check if we found native libraries in the external library. This
+                    // constitutes an error or warning depending on if they are in lib/
+                    if (jarStatus.getNativeLibs().size() > 0) {
+                        String libName = new File(libraryOsPath).getName();
 
-                    String msg = String.format(
-                            "Native libraries detected in '%1$s'. See console for more information.",
-                            libName);
+                        String msg = String.format(
+                                "Native libraries detected in '%1$s'. See console for more information.",
+                                libName);
 
-                    ArrayList<String> consoleMsgs = new ArrayList<String>();
+                        ArrayList<String> consoleMsgs = new ArrayList<String>();
 
-                    consoleMsgs.add(String.format(
-                            "The library '%1$s' contains native libraries that will not run on the device.",
-                            libName));
+                        consoleMsgs.add(String.format(
+                                "The library '%1$s' contains native libraries that will not run on the device.",
+                                libName));
 
-                    if (jarStatus.hasNativeLibsConflicts()) {
-                        consoleMsgs.add("Additionally some of those libraries will interfer with the installation of the application because of their location in lib/");
-                        consoleMsgs.add("lib/ is reserved for NDK libraries.");
-                    }
-
-                    consoleMsgs.add("The following libraries were found:");
-
-                    for (String lib : jarStatus.getNativeLibs()) {
-                        consoleMsgs.add(" - " + lib);
-                    }
-
-                    String[] consoleStrings = consoleMsgs.toArray(new String[consoleMsgs.size()]);
-
-                    // if there's a conflict or if the prefs force error on any native code in jar
-                    // files, throw an exception
-                    if (jarStatus.hasNativeLibsConflicts() ||
-                            AdtPrefs.getPrefs().getBuildForceErrorOnNativeLibInJar()) {
-                        throw new NativeLibInJarException(jarStatus, msg, libName, consoleStrings);
-                    } else {
-                        // otherwise, put a warning, and output to the console also.
-                        if (resMarker != null) {
-                            resMarker.setWarning(mProject, msg);
+                        if (jarStatus.hasNativeLibsConflicts()) {
+                            consoleMsgs.add("Additionally some of those libraries will interfer with the installation of the application because of their location in lib/");
+                            consoleMsgs.add("lib/ is reserved for NDK libraries.");
                         }
 
-                        for (String string : consoleStrings) {
-                            mOutStream.println(string);
+                        consoleMsgs.add("The following libraries were found:");
+
+                        for (String lib : jarStatus.getNativeLibs()) {
+                            consoleMsgs.add(" - " + lib);
+                        }
+
+                        String[] consoleStrings = consoleMsgs.toArray(new String[consoleMsgs.size()]);
+
+                        // if there's a conflict or if the prefs force error on any native code in jar
+                        // files, throw an exception
+                        if (jarStatus.hasNativeLibsConflicts() ||
+                                AdtPrefs.getPrefs().getBuildForceErrorOnNativeLibInJar()) {
+                            throw new NativeLibInJarException(jarStatus, msg, libName, consoleStrings);
+                        } else {
+                            // otherwise, put a warning, and output to the console also.
+                            if (resMarker != null) {
+                                resMarker.setWarning(mProject, msg);
+                            }
+
+                            for (String string : consoleStrings) {
+                                mOutStream.println(string);
+                            }
                         }
                     }
+                } else if (libFile.isDirectory()) {
+                    // this is technically not a source folder (class folder instead) but since we
+                    // only care about Java resources (ie non class/java files) this will do the
+                    // same
+                    apkBuilder.addSourceFolder(libFile);
                 }
             }
 
@@ -386,7 +394,7 @@
             throws CoreException {
 
         // get the list of libraries to include with the source code
-        String[] libraries = getExternalJars(resMarker);
+        String[] libraries = getExternalDependencies(resMarker);
 
         int startIndex = 0;
 
@@ -772,10 +780,13 @@
     }
 
     /**
-     * Returns an array of external jar files used by the project.
+     * Returns an array of external dependencies used the project. This can be paths to jar files
+     * or to source folders.
+     *
+     * @param resMarker if non null, used to put Resource marker on problem files.
      * @return an array of OS-specific absolute file paths
      */
-    private final String[] getExternalJars(ResourceMarker resMarker) {
+    private final String[] getExternalDependencies(ResourceMarker resMarker) {
         // get a java project from it
         IJavaProject javaProject = JavaCore.create(mProject);
 
@@ -795,9 +806,9 @@
                     // get the IPath
                     IPath path = e.getPath();
 
-                    // check the name ends with .jar
+                    IResource resource = wsRoot.findMember(path);
+                    // case of a jar file (which could be relative to the workspace or a full path)
                     if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
-                        IResource resource = wsRoot.findMember(path);
                         if (resource != null && resource.exists() &&
                                 resource.getType() == IResource.FILE) {
                             oslibraryList.add(resource.getLocation().toOSString());
@@ -807,7 +818,7 @@
                             String osFullPath = path.toOSString();
 
                             File f = new File(osFullPath);
-                            if (f.exists()) {
+                            if (f.isFile()) {
                                 oslibraryList.add(osFullPath);
                             } else {
                                 String message = String.format( Messages.Couldnt_Locate_s_Error,
@@ -821,6 +832,21 @@
                                 }
                             }
                         }
+                    } else {
+                        // this can be the case for a class folder.
+                        if (resource != null && resource.exists() &&
+                                resource.getType() == IResource.FOLDER) {
+                            oslibraryList.add(resource.getLocation().toOSString());
+                        } else {
+                            // if the path doesn't match a workspace resource,
+                            // then we get an OSString and check if this links to a valid folder.
+                            String osFullPath = path.toOSString();
+
+                            File f = new File(osFullPath);
+                            if (f.isDirectory()) {
+                                oslibraryList.add(osFullPath);
+                            }
+                        }
                     }
                 }
             }
diff --git a/testapps/basicProjectWithJavaFolder/.classpath b/testapps/basicProjectWithJavaFolder/.classpath
new file mode 100644
index 0000000..2fc51f4
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="lib" path="/basicJavaProject/bin"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testapps/basicProjectWithJavaFolder/.project b/testapps/basicProjectWithJavaFolder/.project
new file mode 100644
index 0000000..5ff4505
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>basicProjectWithJava</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/testapps/basicProjectWithJavaFolder/AndroidManifest.xml b/testapps/basicProjectWithJavaFolder/AndroidManifest.xml
new file mode 100644
index 0000000..1f968cd
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      android:versionCode="1"
+      android:versionName="1.0" package="com.android.tests.basicProjectWithJava">
+    <uses-sdk android:minSdkVersion="9"/>
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:label="@string/app_name" android:name="Main">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/testapps/basicProjectWithJavaFolder/default.properties b/testapps/basicProjectWithJavaFolder/default.properties
new file mode 100644
index 0000000..8ee25b8
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-AOSP
diff --git a/testapps/basicProjectWithJavaFolder/res/drawable-hdpi/icon.png b/testapps/basicProjectWithJavaFolder/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/testapps/basicProjectWithJavaFolder/res/drawable-ldpi/icon.png b/testapps/basicProjectWithJavaFolder/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/testapps/basicProjectWithJavaFolder/res/drawable-mdpi/icon.png b/testapps/basicProjectWithJavaFolder/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/testapps/basicProjectWithJavaFolder/res/layout/main.xml b/testapps/basicProjectWithJavaFolder/res/layout/main.xml
new file mode 100644
index 0000000..1fd9814
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/res/layout/main.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:text="basicProjectWithJava"
+    android:id="@+id/text"
+    />
+<!-- <com.android.tests.basicProjectWithJava.MyTextView
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:id="@+id/text"
+    /> -->
+</LinearLayout>
diff --git a/testapps/basicProjectWithJavaFolder/res/values/strings.xml b/testapps/basicProjectWithJavaFolder/res/values/strings.xml
new file mode 100644
index 0000000..96d8724
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">basicProjectWithJava</string>
+</resources>
diff --git a/testapps/basicProjectWithJavaFolder/src/com/android/tests/basicProjectWithJava/Main.java b/testapps/basicProjectWithJavaFolder/src/com/android/tests/basicProjectWithJava/Main.java
new file mode 100644
index 0000000..994382e
--- /dev/null
+++ b/testapps/basicProjectWithJavaFolder/src/com/android/tests/basicProjectWithJava/Main.java
@@ -0,0 +1,21 @@
+package com.android.tests.basicProjectWithJava;
+
+import com.android.tests.basicJavaProject.Foo;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class Main extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        Foo foo = new Foo();
+
+        TextView tv = (TextView) findViewById(R.id.text);
+        tv.setText("basicProjectWithJava\nvalue from java project:" + foo.getRandomFoo());
+    }
+}
\ No newline at end of file