package com.dianping.ant; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.regex.Pattern; public class UpdateProject { /** * @param args */ public static void main(String[] args) throws Exception { System.out .println("Prepare your android project to build to a plugin."); if (args.length < 2) { System.out.println("Useage:"); System.out.println(" update <sdk> <workspace or project>"); System.out.println(" - search and update all projects which"); System.out.println(" contains \"fragment.properties\""); return; } File sdkdir = new File(args[0]); if (!sdkdir.isDirectory()) { System.out.println(sdkdir + " is not a directory"); System.exit(1); } byte[] host; { File f = new File(sdkdir, "lib"); f = new File(f, "host.jar"); if (!f.isFile()) { System.out.println(f + " not found"); System.exit(1); } FileInputStream fis = new FileInputStream(f); host = new byte[fis.available()]; fis.read(host); fis.close(); } File pluginXml = new File(sdkdir, "build-plugin.xml"); if (!pluginXml.isFile()) { System.out.println(pluginXml + " not found"); System.exit(1); } File workspaceXml = new File(sdkdir, "build-workspace.xml"); if (!workspaceXml.isFile()) { System.out.println(workspaceXml + " not found"); System.exit(1); } File basedir = new File(args[1]); if (!basedir.isDirectory()) { System.out.println(basedir + " is not a directory"); System.exit(1); } ArrayList<File> dirs = new ArrayList<File>(); search(basedir, dirs); // if more than one plugin in a dir, it is a workspace HashMap<File, Integer> workspaces = new HashMap<File, Integer>(); for (File dir : dirs) { File am = new File(dir, "AndroidManifest.xml"); FileInputStream fis = new FileInputStream(am); byte[] buf = new byte[4096]; int l = fis.read(buf); fis.close(); String str = new String(buf, 0, l, "UTF-8"); int i = str.indexOf("package=\""); if (i < 0) { System.out.println(" [plugin] fail to process " + am); continue; } int j = str.indexOf('\"', i + "package=\"".length()); if (j < 0) { System.out.println(" [plugin] fail to process " + am); continue; } String packageName = str.substring(i + "package=\"".length(), j); System.out.println(" [plugin] " + dir + ", package = " + packageName); String androidCmd = System.getProperty("os.name").startsWith( "Windows") ? "android.bat" : "android"; Process p = Runtime.getRuntime().exec( new String[] { androidCmd, "update", "project", "-p", dir.getAbsolutePath(), "-n", packageName, "-t", "android-16" }); int pcode = p.waitFor(); if (pcode == 0) { System.out.println(" android update success"); } else { System.out.println(" android update fail (" + pcode + ")"); } File bxml = new File(dir, "build.xml"); fis = new FileInputStream(bxml); buf = new byte[fis.available()]; fis.read(buf); fis.close(); str = new String(buf, "UTF-8"); str = str.replace("${sdk.dir}/tools/ant/build.xml", String.valueOf(getRelativeFile(pluginXml, dir))); FileOutputStream fos = new FileOutputStream(bxml); fos.write(str.getBytes("UTF-8")); fos.close(); File llib = new File(dir, "libs"); llib = new File(llib, "host.jar"); fos = new FileOutputStream(llib); fos.write(host); fos.close(); File ws = dir.getParentFile(); if (workspaces.get(ws) != null) { workspaces.put(ws, workspaces.get(ws) + 1); } else { workspaces.put(ws, 1); } } for (File ws : workspaces.keySet()) { if (workspaces.get(ws) > 1) { StringBuilder sb = new StringBuilder(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); sb.append("<project name=\"dev\" default=\"help\">\n"); sb.append(" <import file=\"") .append(getRelativeFile(workspaceXml, ws)) .append("\" />\n"); sb.append("</project>\n"); File buildXml = new File(ws, "build.xml"); FileOutputStream fos = new FileOutputStream(buildXml); fos.write(sb.toString().getBytes("utf-8")); fos.close(); System.out.println(" [workspace] workspace " + ws + ", " + workspaces.get(ws) + " plugins"); } } } static boolean isPlugin(File dir) { File am = new File(dir, "AndroidManifest.xml"); if (am.exists()) { File f = new File(dir, "fragment.properties"); if (f.exists()) { return true; } } return false; } static void search(File dir, ArrayList<File> output) { if (isPlugin(dir)) { output.add(dir); } else { File[] files = dir.listFiles(); for (File sub : files) { if (sub.isDirectory()) { search(sub, output); } } } } /** * Returns the path of one File relative to another. * * @param target * the target directory * @param base * the base directory * @return target's path relative to the base directory * @throws IOException * if an error occurs while resolving the files' canonical names */ static File getRelativeFile(File target, File base) throws IOException { String[] baseComponents = base.getCanonicalPath().split( Pattern.quote(File.separator)); String[] targetComponents = target.getCanonicalPath().split( Pattern.quote(File.separator)); // skip common components int index = 0; for (; index < targetComponents.length && index < baseComponents.length; ++index) { if (!targetComponents[index].equals(baseComponents[index])) break; } StringBuilder result = new StringBuilder(); if (index != baseComponents.length) { // backtrack to base directory for (int i = index; i < baseComponents.length; ++i) result.append(".." + File.separator); } for (; index < targetComponents.length; ++index) result.append(targetComponents[index] + File.separator); if (!target.getPath().endsWith("/") && !target.getPath().endsWith("\\")) { // remove final path separator result.delete(result.length() - File.separator.length(), result.length()); } return new File(result.toString()); } }