diff options
Diffstat (limited to 'apigenerator/src')
3 files changed, 0 insertions, 537 deletions
diff --git a/apigenerator/src/com/android/apigenerator/AndroidJarReader.java b/apigenerator/src/com/android/apigenerator/AndroidJarReader.java deleted file mode 100644 index 07a3ce6..0000000 --- a/apigenerator/src/com/android/apigenerator/AndroidJarReader.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.apigenerator; - -import com.android.utils.Pair; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.MethodNode; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * Reads all the android.jar files found in an SDK and generate a map of {@link ApiClass}. - * - */ -public class AndroidJarReader { - - private static final byte[] BUFFER = new byte[65535]; - - private final String mSdkFolder; - - public AndroidJarReader(String sdkFolder) { - mSdkFolder = sdkFolder; - } - - public Map<String, ApiClass> getClasses() { - HashMap<String, ApiClass> map = new HashMap<String, ApiClass>(); - - // Get all the android.jar. They are in platforms-# - int apiLevel = 0; - while (true) { - apiLevel++; - try { - File jar = new File(mSdkFolder, "platforms/android-" + apiLevel + "/android.jar"); - if (jar.exists() == false) { - System.out.println("Last API level found: " + (apiLevel-1)); - break; - } - - FileInputStream fis = new FileInputStream(jar); - ZipInputStream zis = new ZipInputStream(fis); - ZipEntry entry = zis.getNextEntry(); - while (entry != null) { - String name = entry.getName(); - - if (name.endsWith(".class")) { - - int index = 0; - do { - int size = zis.read(BUFFER, index, BUFFER.length - index); - if (size >= 0) { - index += size; - } else { - break; - } - } while (true); - - byte[] b = new byte[index]; - System.arraycopy(BUFFER, 0, b, 0, index); - - ClassReader reader = new ClassReader(b); - ClassNode classNode = new ClassNode(); - reader.accept(classNode, 0 /*flags*/); - - if (classNode != null) { - ApiClass theClass = addClass(map, classNode.name, apiLevel); - - // super class - if (classNode.superName != null) { - theClass.addSuperClass(classNode.superName, apiLevel); - } - - // interfaces - for (Object interfaceName : classNode.interfaces) { - theClass.addInterface((String) interfaceName, apiLevel); - } - - // fields - for (Object field : classNode.fields) { - FieldNode fieldNode = (FieldNode) field; - if ((fieldNode.access & Opcodes.ACC_PRIVATE) != 0) { - continue; - } - if (fieldNode.name.startsWith("this$") == false && - fieldNode.name.equals("$VALUES") == false) { - theClass.addField(fieldNode.name, apiLevel); - } - } - - // methods - for (Object method : classNode.methods) { - MethodNode methodNode = (MethodNode) method; - if ((methodNode.access & Opcodes.ACC_PRIVATE) != 0) { - continue; - } - if (methodNode.name.equals("<clinit>") == false) { - theClass.addMethod(methodNode.name + methodNode.desc, apiLevel); - } - } - } - } - entry = zis.getNextEntry(); - } - - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - - } - } - - postProcessClasses(map); - - return map; - } - - private void postProcessClasses(Map<String, ApiClass> classes) { - for (ApiClass theClass : classes.values()) { - Map<String, Integer> methods = theClass.getMethods(); - Map<String, Integer> fixedMethods = new HashMap<String, Integer>(); - - List<Pair<String, Integer>> superClasses = theClass.getSuperClasses(); - List<Pair<String, Integer>> interfaces = theClass.getInterfaces(); - - methodLoop: for (Entry<String, Integer> method : methods.entrySet()) { - String methodName = method.getKey(); - int apiLevel = method.getValue(); - - if (methodName.startsWith("<init>(") == false) { - - for (Pair<String, Integer> parent : superClasses) { - // only check the parent if it was a parent class at the introduction - // of the method. - if (parent.getSecond() <= apiLevel) { - ApiClass parentClass = classes.get(parent.getFirst()); - assert parentClass != null; - if (parentClass != null && - checkClassContains(theClass.getName(), - methodName, apiLevel, - classes, parentClass)) { - continue methodLoop; - } - } - } - - for (Pair<String, Integer> parent : interfaces) { - // only check the parent if it was a parent class at the introduction - // of the method. - if (parent.getSecond() <= apiLevel) { - ApiClass parentClass = classes.get(parent.getFirst()); - assert parentClass != null; - if (parentClass != null && - checkClassContains(theClass.getName(), - methodName, apiLevel, - classes, parentClass)) { - continue methodLoop; - } - } - } - } - - // if we reach here. the method isn't an override - fixedMethods.put(methodName, method.getValue()); - } - - theClass.replaceMethods(fixedMethods); - } - } - - private boolean checkClassContains(String className, String methodName, int apiLevel, - Map<String, ApiClass> classMap, ApiClass parentClass) { - - Integer parentMethodApiLevel = parentClass.getMethods().get(methodName); - if (parentMethodApiLevel != null && parentMethodApiLevel <= apiLevel) { - // the parent class has the method and it was introduced in the parent at the - // same api level as the method, or before. - return true; - } - - // check on this class parents. - List<Pair<String, Integer>> superClasses = parentClass.getSuperClasses(); - List<Pair<String, Integer>> interfaces = parentClass.getInterfaces(); - - for (Pair<String, Integer> parent : superClasses) { - // only check the parent if it was a parent class at the introduction - // of the method. - if (parent.getSecond() <= apiLevel) { - ApiClass superParentClass = classMap.get(parent.getFirst()); - assert superParentClass != null; - if (superParentClass != null && checkClassContains(className, methodName, apiLevel, - classMap, superParentClass)) { - return true; - } - } - } - - for (Pair<String, Integer> parent : interfaces) { - // only check the parent if it was a parent class at the introduction - // of the method. - if (parent.getSecond() <= apiLevel) { - ApiClass superParentClass = classMap.get(parent.getFirst()); - assert superParentClass != null; - if (superParentClass != null && checkClassContains(className, methodName, apiLevel, - classMap, superParentClass)) { - return true; - } - } - } - - return false; - } - - private ApiClass addClass(HashMap<String, ApiClass> classes, String name, int apiLevel) { - ApiClass theClass = classes.get(name); - if (theClass == null) { - theClass = new ApiClass(name, apiLevel); - classes.put(name, theClass); - } - - return theClass; - } -} diff --git a/apigenerator/src/com/android/apigenerator/ApiClass.java b/apigenerator/src/com/android/apigenerator/ApiClass.java deleted file mode 100644 index 50ee8c8..0000000 --- a/apigenerator/src/com/android/apigenerator/ApiClass.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.apigenerator; - -import com.android.utils.Pair; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** - * Represents a class and its methods/fields. - * This is used to write the simplified XML file containing all the public API. - * - */ -public class ApiClass { - - private final String mName; - private final int mSince; - - private final List<Pair<String, Integer>> mSuperClasses = - new ArrayList<Pair<String, Integer>>(); - - private final List<Pair<String, Integer>> mInterfaces = new ArrayList<Pair<String, Integer>>(); - - private final Map<String, Integer> mFields = new HashMap<String, Integer>(); - private final Map<String, Integer> mMethods = new HashMap<String, Integer>(); - - public ApiClass(String name, int since) { - mName = name; - mSince = since; - } - - public String getName() { - return mName; - } - - int getSince() { - return mSince; - } - - public void addField(String name, int since) { - Integer i = mFields.get(name); - if (i == null || i.intValue() > since) { - mFields.put(name, Integer.valueOf(since)); - } - } - - public void addMethod(String name, int since) { - Integer i = mMethods.get(name); - if (i == null || i.intValue() > since) { - mMethods.put(name, Integer.valueOf(since)); - } - } - - public Map<String, Integer> getMethods() { - return mMethods; - } - - public void replaceMethods(Map<String, Integer> fixedMethods) { - mMethods.clear(); - mMethods.putAll(fixedMethods); - } - - public void addSuperClass(String superClass, int since) { - addToArray(mSuperClasses, superClass, since); - } - - public List<Pair<String, Integer>> getSuperClasses() { - return mSuperClasses; - } - - public void addInterface(String interfaceClass, int since) { - addToArray(mInterfaces, interfaceClass, since); - } - - public List<Pair<String, Integer>> getInterfaces() { - return mInterfaces; - } - - void addToArray(List<Pair<String, Integer>> list, String name, int value) { - // check if we already have that name (at a lower level) - for (Pair<String, Integer> pair : list) { - if (name.equals(pair.getFirst()) && pair.getSecond() < value) { - return; - } - } - - list.add(Pair.of(name, Integer.valueOf(value))); - } - - public void print(PrintStream stream) { - stream.print("\t<class name=\""); - stream.print(mName); - stream.print("\" since=\""); - stream.print(mSince); - stream.println("\">"); - - print(mSuperClasses, "extends", stream); - print(mInterfaces, "implements", stream); - print(mMethods, "method", stream); - print(mFields, "field", stream); - - stream.println("\t</class>"); - } - - private void print(List<Pair<String, Integer> > list, String name, PrintStream stream) { - Collections.sort(list, new Comparator<Pair<String, Integer> >() { - - @Override - public int compare(Pair<String, Integer> o1, Pair<String, Integer> o2) { - return o1.getFirst().compareTo(o2.getFirst()); - } - }); - - for (Pair<String, Integer> pair : list) { - if (mSince == pair.getSecond()) { - stream.print("\t\t<"); - stream.print(name); - stream.print(" name=\""); - stream.print(encodeAttribute(pair.getFirst())); - stream.println("\" />"); - } else { - stream.print("\t\t<"); - stream.print(name); - stream.print(" name=\""); - stream.print(encodeAttribute(pair.getFirst())); - stream.print("\" since=\""); - stream.print(pair.getSecond()); - stream.println("\" />"); - } - } - } - - private void print(Map<String, Integer> map, String name, PrintStream stream) { - TreeMap<String, Integer> map2 = new TreeMap<String, Integer>(map); - - for (Entry<String, Integer> entry : map2.entrySet()) { - if (mSince == entry.getValue()) { - stream.print("\t\t<"); - stream.print(name); - stream.print(" name=\""); - stream.print(encodeAttribute(entry.getKey())); - stream.println("\" />"); - } else { - stream.print("\t\t<"); - stream.print(name); - stream.print(" name=\""); - stream.print(encodeAttribute(entry.getKey())); - stream.print("\" since=\""); - stream.print(entry.getValue()); - stream.println("\" />"); - } - } - } - - private String encodeAttribute(String attribute) { - StringBuilder sb = new StringBuilder(); - int n = attribute.length(); - // &, ", ' and < are illegal in attributes; see http://www.w3.org/TR/REC-xml/#NT-AttValue - // (' legal in a " string and " is legal in a ' string but here we'll stay on the safe - // side) - for (int i = 0; i < n; i++) { - char c = attribute.charAt(i); - if (c == '"') { - sb.append("""); //$NON-NLS-1$ - } else if (c == '<') { - sb.append("<"); //$NON-NLS-1$ - } else if (c == '\'') { - sb.append("'"); //$NON-NLS-1$ - } else if (c == '&') { - sb.append("&"); //$NON-NLS-1$ - } else { - sb.append(c); - } - } - - return sb.toString(); - } - - @Override - public String toString() { - return mName; - } -} diff --git a/apigenerator/src/com/android/apigenerator/Main.java b/apigenerator/src/com/android/apigenerator/Main.java deleted file mode 100644 index 4ce7ac9..0000000 --- a/apigenerator/src/com/android/apigenerator/Main.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.apigenerator; - - - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintStream; -import java.util.Map; -import java.util.TreeMap; - -/** - * Main class for command line command to convert the existing API XML/TXT files into diff-based - * simple text files. - * - */ -public class Main { - - /** - * @param args - */ - public static void main(String[] args) { - if (args.length != 2) { - printUsage(); - } - - AndroidJarReader reader = new AndroidJarReader(args[0]); - Map<String, ApiClass> classes = reader.getClasses(); - createApiFile(new File(args[1]), classes); - } - - private static void printUsage() { - System.err.println("Generates a single API file from the content of an SDK.\n"); - System.err.println("Usage\n"); - System.err.println("\tApiCheck SDKFOLDER OUTFILE\n"); - System.exit(1); - } - - /** - * Creates the simplified diff-based API level. - * @param outFolder the out folder. - * @param classes - */ - private static void createApiFile(File outFile, Map<String, ApiClass> classes) { - - PrintStream ps = null; - try { - ps = new PrintStream(outFile); - ps.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); - ps.println("<api version=\"1\">"); - TreeMap<String, ApiClass> map = new TreeMap<String, ApiClass>(classes); - for (ApiClass theClass : map.values()) { - (theClass).print(ps); - } - ps.println("</api>"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } finally { - if (ps != null) { - ps.close(); - } - } - } -} |