diff options
14 files changed, 279 insertions, 153 deletions
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java index ce3e95c..6f64c5f 100644 --- a/dalvik/src/main/java/dalvik/system/VMDebug.java +++ b/dalvik/src/main/java/dalvik/system/VMDebug.java @@ -34,6 +34,8 @@ import java.io.IOException; public final class VMDebug { /** * Specifies the default method trace data file name. + * + * @deprecated only used in one place, which is unused and deprecated */ static public final String DEFAULT_METHOD_TRACE_FILE_NAME = "/sdcard/dmtrace.trace"; @@ -44,11 +46,13 @@ public final class VMDebug { public static final int TRACE_COUNT_ALLOCS = 1; /* constants for getAllocCount */ - private static final int KIND_ALLOCATED_OBJECTS = 1<<0; - private static final int KIND_ALLOCATED_BYTES = 1<<1; - private static final int KIND_FREED_OBJECTS = 1<<2; - private static final int KIND_FREED_BYTES = 1<<3; - private static final int KIND_GC_INVOCATIONS = 1<<4; + private static final int KIND_ALLOCATED_OBJECTS = 1<<0; + private static final int KIND_ALLOCATED_BYTES = 1<<1; + private static final int KIND_FREED_OBJECTS = 1<<2; + private static final int KIND_FREED_BYTES = 1<<3; + private static final int KIND_GC_INVOCATIONS = 1<<4; + private static final int KIND_CLASS_INIT_COUNT = 1<<5; + private static final int KIND_CLASS_INIT_TIME = 1<<6; private static final int KIND_EXT_ALLOCATED_OBJECTS = 1<<12; private static final int KIND_EXT_ALLOCATED_BYTES = 1<<13; private static final int KIND_EXT_FREED_OBJECTS = 1<<14; @@ -64,6 +68,10 @@ public final class VMDebug { KIND_FREED_BYTES; public static final int KIND_GLOBAL_GC_INVOCATIONS = KIND_GC_INVOCATIONS; + public static final int KIND_GLOBAL_CLASS_INIT_COUNT = + KIND_CLASS_INIT_COUNT; + public static final int KIND_GLOBAL_CLASS_INIT_TIME = + KIND_CLASS_INIT_TIME; public static final int KIND_GLOBAL_EXT_ALLOCATED_OBJECTS = KIND_EXT_ALLOCATED_OBJECTS; public static final int KIND_GLOBAL_EXT_ALLOCATED_BYTES = @@ -83,6 +91,10 @@ public final class VMDebug { KIND_FREED_BYTES << 16; public static final int KIND_THREAD_GC_INVOCATIONS = KIND_GC_INVOCATIONS << 16; + public static final int KIND_THREAD_CLASS_INIT_COUNT = + KIND_CLASS_INIT_COUNT << 16; + public static final int KIND_THREAD_CLASS_INIT_TIME = + KIND_CLASS_INIT_TIME << 16; public static final int KIND_THREAD_EXT_ALLOCATED_OBJECTS = KIND_EXT_ALLOCATED_OBJECTS << 16; public static final int KIND_THREAD_EXT_ALLOCATED_BYTES = @@ -131,6 +143,8 @@ public final class VMDebug { /** * Start method tracing with default name, size, and with <code>0</code> * flags. + * + * @deprecated not used, not needed */ public static void startMethodTracing() { startMethodTracing(DEFAULT_METHOD_TRACE_FILE_NAME, 0, 0); diff --git a/luni-kernel/src/main/java/java/lang/Class.java b/luni-kernel/src/main/java/java/lang/Class.java index b8e3903..101d593 100644 --- a/luni-kernel/src/main/java/java/lang/Class.java +++ b/luni-kernel/src/main/java/java/lang/Class.java @@ -177,7 +177,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws ExceptionInInitializerError * if an exception occurs during static initialization of a * class. - * @since Android 1.0 */ public static Class<?> forName(String className) throws ClassNotFoundException { return forName(className, true, VMStack.getCallingClassLoader()); @@ -210,7 +209,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws ExceptionInInitializerError * if an exception occurs during static initialization of a * class. - * @since Android 1.0 */ public static Class<?> forName(String className, boolean initializeBoolean, ClassLoader classLoader) throws ClassNotFoundException { @@ -270,7 +268,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws SecurityException * if a security manager exists and it does not allow member * access. - * @since Android 1.0 */ public Class[] getClasses() { // BEGIN android-note @@ -289,7 +286,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * the annotation type. * @return the annotation of the given type, or {@code null} if there is no * such annotation. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { @@ -309,7 +305,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return a copy of the array containing this class' annotations. * @see #getDeclaredAnnotations() - * @since Android 1.0 */ public Annotation[] getAnnotations() { /* @@ -353,7 +348,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return this class' canonical name, or {@code null} if it does not have a * canonical name. - * @since Android 1.0 */ public String getCanonicalName() { if (isLocalClass() || isAnonymousClass()) @@ -403,7 +397,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow accessing * the class loader. * @see ClassLoader - * @since Android 1.0 */ public ClassLoader getClassLoader() { SecurityManager smgr = System.getSecurityManager(); @@ -459,7 +452,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * the type of the elements of the array. * * @return the component type of this class. - * @since Android 1.0 */ public native Class<?> getComponentType(); @@ -477,7 +469,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredConstructor(Class...) - * @since Android 1.0 */ @SuppressWarnings("unchecked") public Constructor<T> getConstructor(Class... parameterTypes) throws NoSuchMethodException, @@ -498,7 +489,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredConstructors() - * @since Android 1.0 */ public Constructor[] getConstructors() throws SecurityException { // BEGIN android-note @@ -518,7 +508,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return a copy of the array containing the annotations defined for the * class that this {@code Class} represents. * @see #getAnnotations() - * @since Android 1.0 */ native public Annotation[] getDeclaredAnnotations(); @@ -534,7 +523,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws SecurityException * if a security manager exists and it does not allow member * access. - * @since Android 1.0 */ public Class[] getDeclaredClasses() throws SecurityException { // BEGIN android-note @@ -596,7 +584,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getConstructor(Class...) - * @since Android 1.0 */ @SuppressWarnings("unchecked") public Constructor<T> getDeclaredConstructor(Class... parameterTypes) @@ -618,7 +605,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getConstructors() - * @since Android 1.0 */ public Constructor[] getDeclaredConstructors() throws SecurityException { // BEGIN android-note @@ -688,7 +674,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getField(String) - * @since Android 1.0 */ public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { @@ -716,7 +701,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getFields() - * @since Android 1.0 */ public Field[] getDeclaredFields() throws SecurityException { checkDeclaredMemberAccess(); @@ -755,7 +739,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getMethod(String, Class...) - * @since Android 1.0 */ public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { @@ -783,7 +766,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getMethods() - * @since Android 1.0 */ public Method[] getDeclaredMethods() throws SecurityException { checkDeclaredMemberAccess(); @@ -829,7 +811,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * {@code Class} represents an array class, a primitive type or void. * * @return the declaring {@code Class} or {@code null}. - * @since Android 1.0 */ native public Class<?> getDeclaringClass(); @@ -838,7 +819,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * enclosing class the method returns {@code null}. * * @return the enclosing {@code Class} or {@code null}. - * @since Android 1.0 */ native public Class<?> getEnclosingClass(); @@ -847,7 +827,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * anonymous or local/automatic class; otherwise {@code null}. * * @return the enclosing {@code Constructor} instance or {@code null}. - * @since Android 1.0 */ native public Constructor<?> getEnclosingConstructor(); @@ -856,7 +835,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * anonymous or local/automatic class; otherwise {@code null}. * * @return the enclosing {@code Method} instance or {@code null}. - * @since Android 1.0 */ native public Method getEnclosingMethod(); @@ -866,7 +844,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * enum} type. * * @return an array with the {@code enum} constants or {@code null}. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public T[] getEnumConstants() { @@ -896,7 +873,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredField(String) - * @since Android 1.0 */ public Field getField(String name) throws NoSuchFieldException, SecurityException { checkPublicMemberAccess(); @@ -927,7 +903,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredFields() - * @since Android 1.0 */ public Field[] getFields() throws SecurityException { checkPublicMemberAccess(); @@ -944,7 +919,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return an array of {@link Type} instances directly implemented by the * class represented by this {@code class}. - * @since Android 1.0 */ public Type[] getGenericInterfaces() { GenericSignatureParser parser = new GenericSignatureParser( @@ -958,7 +932,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * class}. * * @return an instance of {@code Type} representing the superclass. - * @since Android 1.0 */ public Type getGenericSuperclass() { GenericSignatureParser parser = new GenericSignatureParser( @@ -976,7 +949,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return an array with the interfaces of the class represented by this * class. - * @since Android 1.0 */ public native Class[] getInterfaces(); // BEGIN android-note @@ -1004,7 +976,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredMethod(String, Class...) - * @since Android 1.0 */ public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { @@ -1036,7 +1007,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * if a security manager exists and it does not allow member * access. * @see #getDeclaredMethods() - * @since Android 1.0 */ public Method[] getMethods() throws SecurityException { checkPublicMemberAccess(); @@ -1097,7 +1067,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * defined by constants in the {@link Modifier} class. * * @return the modifiers of the class represented by this {@code Class}. - * @since Android 1.0 */ public int getModifiers() { return getModifiers(this, false); @@ -1118,7 +1087,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * {@link Class}. * * @return the name of the class represented by this {@code Class}. - * @since Android 1.0 */ public native String getName(); @@ -1130,7 +1098,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * example {@code "Integer[]"}) is returned. * * @return the simple name of the class represented by this {@code Class}. - * @since Android 1.0 */ public String getSimpleName() { if (isArray()) { @@ -1199,7 +1166,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return the requested resource's {@code URL} object or {@code null} if * the resource can not be found. * @see ClassLoader - * @since Android 1.0 */ public URL getResource(String resName) { // Get absolute resource name, but without the leading slash @@ -1236,7 +1202,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return a stream for the requested resource or {@code null} if no * resource with the specified name can be found. * @see ClassLoader - * @since Android 1.0 */ public InputStream getResourceAsStream(String resName) { // Get absolute resource name, but without the leading slash @@ -1264,15 +1229,15 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the signers for the class represented by this {@code Class} or - * {@code null} if either there are no signers or this {@code Class} - * represents a primitive type or void. + * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files. + * All classes from any given dex file will have the same signers, but different dex + * files may have different signers. This does not fit well with the original + * {@code ClassLoader}-based model of {@code getSigners}.) * - * @return the signers of the class represented by this {@code Class}. - * @since Android 1.0 + * @return null. */ public Object[] getSigners() { - // TODO Delegate this to class loader somehow? What are these signers? + // See http://code.google.com/p/android/issues/detail?id=1766. return null; } @@ -1284,7 +1249,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * class then the {@code Object} class is returned. * * @return the superclass of the class represented by this {@code Class}. - * @since Android 1.0 */ public native Class<? super T> getSuperclass(); @@ -1295,7 +1259,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return an array with the type variables of the class represented by this * class. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public synchronized TypeVariable<Class<T>>[] getTypeParameters() { @@ -1310,7 +1273,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if this {@code Class} represents an annotation * class; {@code false} otherwise. - * @since Android 1.0 */ public boolean isAnnotation() { final int ACC_ANNOTATION = 0x2000; // not public in reflect.Modifiers @@ -1326,7 +1288,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * the annotation to look for. * @return {@code true} if the class represented by this {@code Class} is * annotated with {@code annotationClass}; {@code false} otherwise. - * @since Android 1.0 */ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { return getAnnotation(annotationClass) != null; @@ -1338,7 +1299,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if the class represented by this {@code Class} is * anonymous; {@code false} otherwise. - * @since Android 1.0 */ native public boolean isAnonymousClass(); @@ -1348,7 +1308,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if the class represented by this {@code Class} is an * array class; {@code false} otherwise. - * @since Android 1.0 */ public boolean isArray() { return getComponentType() != null; @@ -1367,7 +1326,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * represented by this {@code Class}; {@code false} otherwise. * @throws NullPointerException * if {@code cls} is {@code null}. - * @since Android 1.0 */ public native boolean isAssignableFrom(Class<?> cls); @@ -1377,7 +1335,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if the class represented by this {@code Class} is an * {@code enum}; {@code false} otherwise. - * @since Android 1.0 */ public boolean isEnum() { return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class); @@ -1393,7 +1350,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return {@code true} if {@code object} can be cast to the type * represented by this {@code Class}; {@code false} if {@code * object} is {@code null} or cannot be cast. - * @since Android 1.0 */ public native boolean isInstance(Object object); @@ -1402,7 +1358,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if this {@code Class} represents an interface; * {@code false} otherwise. - * @since Android 1.0 */ public native boolean isInterface(); @@ -1412,7 +1367,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if the class represented by this {@code Class} is * defined locally; {@code false} otherwise. - * @since Android 1.0 */ public boolean isLocalClass() { boolean enclosed = (getEnclosingMethod() != null || @@ -1426,7 +1380,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if the class represented by this {@code Class} is a * member class; {@code false} otherwise. - * @since Android 1.0 */ public boolean isMemberClass() { return getDeclaringClass() != null; @@ -1437,7 +1390,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if this {@code Class} represents a primitive type; * {@code false} otherwise. - * @since Android 1.0 */ public native boolean isPrimitive(); @@ -1446,7 +1398,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return {@code true} if this {@code Class} represents a synthetic type; * {@code false} otherwise. - * @since Android 1.0 */ public boolean isSynthetic() { final int ACC_SYNTHETIC = 0x1000; // not public in reflect.Modifiers @@ -1471,7 +1422,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @throws SecurityException * if a security manager exists and it does not allow creating * new instances. - * @since Android 1.0 */ public T newInstance() throws IllegalAccessException, InstantiationException { @@ -1498,7 +1448,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return Package the {@code Package} of which this {@code Class} is a * member or {@code null}. - * @since Android 1.0 */ public Package getPackage() { // TODO This might be a hack, but the VM doesn't have the necessary info. @@ -1519,7 +1468,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * * @return the assertion status for the class represented by this {@code * Class}. - * @since Android 1.0 */ public native boolean desiredAssertionStatus(); @@ -1533,7 +1481,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return this {@code Class} cast as a subclass of the given type. * @throws ClassCastException * if this {@code Class} cannot be cast to the specified type. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public <U> Class<? extends U> asSubclass(Class<U> clazz) { @@ -1552,7 +1499,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return the object that has been cast. * @throws ClassCastException * if the object cannot be cast to the specified type. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public T cast(Object obj) { diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index fccfc4c..ad96ed6 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -187,12 +187,6 @@ public class InetAddress implements Serializable { } }; - static final Comparator<byte[]> LONGEST_FIRST = new Comparator<byte[]>() { - public int compare(byte[] a1, byte[] a2) { - return a2.length - a1.length; - } - }; - /** * Converts an array of byte arrays representing raw IP addresses of a host * to an array of InetAddress objects, sorting to respect the value of the @@ -204,10 +198,12 @@ public class InetAddress implements Serializable { */ static InetAddress[] bytesToInetAddresses(byte[][] rawAddresses, String hostName) { - // Sort the raw byte arrays. - Comparator<byte[]> comparator = NetUtil.preferIPv6Addresses() - ? LONGEST_FIRST : SHORTEST_FIRST; - Arrays.sort(rawAddresses, comparator); + // If we prefer IPv4, ignore the RFC3484 ordering we get from getaddrinfo + // and always put IPv4 addresses first. Arrays.sort() is stable, so the + // internal ordering will not be changed. + if (!NetUtil.preferIPv6Addresses()) { + Arrays.sort(rawAddresses, SHORTEST_FIRST); + } // Convert the byte arrays to InetAddresses. InetAddress[] returnedAddresses = new InetAddress[rawAddresses.length]; diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java index 33e216a..b28c9da 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java @@ -31,7 +31,7 @@ import org.w3c.dom.Node; */ public class CDATASectionImpl extends TextImpl implements CDATASection { - CDATASectionImpl(DocumentImpl document, String data) { + public CDATASectionImpl(DocumentImpl document, String data) { super(document, data); } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java index c39423c..6354747 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java @@ -51,6 +51,13 @@ public abstract class CharacterDataImpl extends LeafNodeImpl implements return buffer.toString(); } + /** + * Appends this node's text content to the given builder. + */ + public void appendDataTo(StringBuilder stringBuilder) { + stringBuilder.append(buffer); + } + public int getLength() { return buffer.length(); } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java index 834cc47..1283eeb 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java @@ -31,7 +31,7 @@ import org.w3c.dom.DocumentType; * the DOM implementation can easily access them while maintaining the DOM tree * structure. */ -public class DOMImplementationImpl implements DOMImplementation { +public final class DOMImplementationImpl implements DOMImplementation { // Singleton instance. private static DOMImplementationImpl instance; diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java index c8819cb..b2f16d1 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java @@ -48,7 +48,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { private DOMImplementation domImplementation; - DocumentImpl(DOMImplementationImpl impl, String namespaceURI, + public DocumentImpl(DOMImplementationImpl impl, String namespaceURI, String qualifiedName, DocumentType doctype) { super(null); diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index ebfdd52..24ed102 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -224,7 +224,6 @@ public abstract class NodeImpl implements Node { * account null arguments and the "*" special case. * * @param name The required name. - * @param wildcard TODO * @return True if and only if the actual name matches the required one. */ public boolean matchesName(String name, boolean wildcard) { @@ -238,7 +237,6 @@ public abstract class NodeImpl implements Node { * * @param namespaceURI The required namespace. * @param localName The required local name. - * @param wildcard TODO * @return True if and only if the actual namespace and local name match * the required pair of namespace and local name. */ @@ -309,7 +307,7 @@ public abstract class NodeImpl implements Node { removeChild(child); } // create a text node to hold the given content - if (textContent != null && textContent.length() != 0){ + if (textContent != null && textContent.length() != 0) { appendChild(getOwnerDocument().createTextNode(textContent)); } return; diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java index 5c9d123..3840ef4 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java @@ -32,7 +32,7 @@ import org.w3c.dom.Text; */ public class TextImpl extends CharacterDataImpl implements Text { - TextImpl(DocumentImpl document, String data) { + public TextImpl(DocumentImpl document, String data) { super(document, data); } @@ -46,7 +46,7 @@ public class TextImpl extends CharacterDataImpl implements Text { return Node.TEXT_NODE; } - public Text splitText(int offset) throws DOMException { + public final Text splitText(int offset) throws DOMException { Text newText = getOwnerDocument().createTextNode( substringData(offset, getLength() - offset)); deleteData(0, offset); @@ -61,15 +61,83 @@ public class TextImpl extends CharacterDataImpl implements Text { return this; } - public boolean isElementContentWhitespace() { - throw new UnsupportedOperationException(); // TODO + public final boolean isElementContentWhitespace() { + // Undefined because we don't validate. Whether whitespace characters + // constitute "element content whitespace" is defined by the containing + // element's declaration (DTD) and we don't parse that. + // TODO: wire this up when we support document validation + return false; } - public String getWholeText() { - throw new UnsupportedOperationException(); // TODO + public final String getWholeText() { + // TODO: support entity references. This code should expand through + // the child elements of entity references. + // http://code.google.com/p/android/issues/detail?id=6807 + + StringBuilder result = new StringBuilder(); + for (TextImpl n = firstTextNodeInCurrentRun(); n != null; n = n.nextTextNode()) { + n.appendDataTo(result); + } + return result.toString(); } - public Text replaceWholeText(String content) throws DOMException { - throw new UnsupportedOperationException(); // TODO + public final Text replaceWholeText(String content) throws DOMException { + // TODO: support entity references. This code should expand and replace + // the child elements of entity references. + // http://code.google.com/p/android/issues/detail?id=6807 + + Node parent = getParentNode(); + Text result = null; + + // delete all nodes in the current run of text... + for (TextImpl n = firstTextNodeInCurrentRun(); n != null; ) { + + // ...except the current node if we have content for it + if (n == this && content != null && content.length() > 0) { + setData(content); + result = this; + n = n.nextTextNode(); + + } else { + Node toRemove = n; // because removeChild() detaches siblings + n = n.nextTextNode(); + parent.removeChild(toRemove); + } + } + + return result; + } + + /** + * Returns the first text or CDATA node in the current sequence of text and + * CDATA nodes. + */ + private TextImpl firstTextNodeInCurrentRun() { + TextImpl firstTextInCurrentRun = this; + for (Node p = getPreviousSibling(); p != null; p = p.getPreviousSibling()) { + short nodeType = p.getNodeType(); + if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + firstTextInCurrentRun = (TextImpl) p; + } else { + break; + } + } + return firstTextInCurrentRun; + } + + /** + * Returns the next sibling node if it exists and it is text or CDATA. + * Otherwise returns null. + */ + private TextImpl nextTextNode() { + Node nextSibling = getNextSibling(); + if (nextSibling == null) { + return null; + } + + short nodeType = nextSibling.getNodeType(); + return nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE + ? (TextImpl) nextSibling + : null; } } diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java index 52240aa..ca2ff98 100644 --- a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java @@ -23,10 +23,14 @@ import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; +import org.apache.harmony.xml.dom.CDATASectionImpl; +import org.apache.harmony.xml.dom.DocumentImpl; +import org.apache.harmony.xml.dom.TextImpl; import org.kxml2.io.KXmlParser; import org.w3c.dom.Attr; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; @@ -49,7 +53,7 @@ import org.apache.harmony.xml.dom.DOMImplementationImpl; */ class DocumentBuilderImpl extends DocumentBuilder { - private static DOMImplementation dom = DOMImplementationImpl.getInstance(); + private static DOMImplementationImpl dom = DOMImplementationImpl.getInstance(); private boolean coalescing; @@ -72,25 +76,6 @@ class DocumentBuilderImpl extends DocumentBuilder { return dom; } - /** - * Reflects whether this DocumentBuilder is configured to ignore comments. - * - * @return True if and only if comments are ignored. - */ - public boolean isIgnoringComments() { - return ignoreComments; - } - - /** - * Reflects whether this DocumentBuilder is configured to ignore element - * content whitespace. - * - * @return True if and only if whitespace element content is ignored. - */ - public boolean isIgnoringElementContentWhitespace() { - return ignoreElementContentWhitespace; - } - @Override public boolean isNamespaceAware() { return namespaceAware; @@ -112,7 +97,10 @@ class DocumentBuilderImpl extends DocumentBuilder { throw new IllegalArgumentException(); } - Document document = newDocument(); + String namespaceURI = null; + String qualifiedName = null; + DocumentType doctype = null; + DocumentImpl document = new DocumentImpl(dom, namespaceURI, qualifiedName, doctype); try { KXmlParser parser = new KXmlParser(); @@ -189,7 +177,7 @@ class DocumentBuilderImpl extends DocumentBuilder { * @throws XmlPullParserException If a parsing error occurs. * @throws IOException If a general IO error occurs. */ - private void parse(XmlPullParser parser, Document document, Node node, + private void parse(XmlPullParser parser, DocumentImpl document, Node node, int endToken) throws XmlPullParserException, IOException { int token = parser.getEventType(); @@ -271,7 +259,7 @@ class DocumentBuilderImpl extends DocumentBuilder { * whitespace at all. */ if (!ignoreElementContentWhitespace) { - appendText(document, node, true, parser.getText()); + appendText(document, node, token, parser.getText()); } } else if (token == XmlPullParser.TEXT || token == XmlPullParser.CDSECT) { /* @@ -279,7 +267,7 @@ class DocumentBuilderImpl extends DocumentBuilder { * That's the easiest case. We simply take it and create a new text node, * or merge with an adjacent text node. */ - appendText(document, node, token == XmlPullParser.TEXT, parser.getText()); + appendText(document, node, token, parser.getText()); } else if (token == XmlPullParser.ENTITY_REF) { /* * Found an entity reference. If an entity resolver is @@ -294,7 +282,7 @@ class DocumentBuilderImpl extends DocumentBuilder { String replacement = resolveStandardEntity(entity); if (replacement != null) { - appendText(document, node, true, replacement); + appendText(document, node, token, replacement); } else { node.appendChild(document.createEntityReference(entity)); } @@ -380,17 +368,17 @@ class DocumentBuilderImpl extends DocumentBuilder { } /** - * @param isText true for a normal TextNode, false for a CDATA section. - * (If we're not coalescing, it matters which kind of node we put into the DOM.) + * @param token the XML pull parser token type, such as XmlPullParser.CDSECT + * or XmlPullParser.ENTITY_REF. */ - private void appendText(Document document, Node node, boolean isText, String text) { + private void appendText(DocumentImpl document, Node parent, int token, String text) { // Ignore empty runs. if (text.length() == 0) { return; } // Merge with any previous text node if possible. if (coalescing) { - Node lastChild = node.getLastChild(); + Node lastChild = parent.getLastChild(); if (lastChild != null && lastChild.getNodeType() == Node.TEXT_NODE) { Text textNode = (Text) lastChild; textNode.setData(textNode.getNodeValue() + text); @@ -398,11 +386,9 @@ class DocumentBuilderImpl extends DocumentBuilder { } } // Okay, we really do need a new text node - if (isText) { - node.appendChild(document.createTextNode(text)); - } else { - node.appendChild(document.createCDATASection(text)); - } + parent.appendChild(token == XmlPullParser.CDSECT + ? new CDATASectionImpl(document, text) + : new TextImpl(document, text)); } @Override diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java index 6b10a0d..ea7abed 100644 --- a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java @@ -562,24 +562,18 @@ public class DocumentBuilderTest extends TestCase { method = "parse", args = {java.lang.String.class} ) - public void test_parseLjava_lang_String() { + public void test_parseLjava_lang_String() throws Exception { // case 1: Trivial use. File f = new File(getClass().getResource("/simple.xml").getFile()); - try { - Document d = db.parse(f.getAbsolutePath()); - assertNotNull(d); + Document d = db.parse(f.getAbsolutePath()); + assertNotNull(d); // TBD getXmlEncoding() is not supported // assertEquals("ISO-8859-1", d.getXmlEncoding()); - assertEquals(2, d.getChildNodes().getLength()); - assertEquals("#comment", - d.getChildNodes().item(0).getNodeName()); - assertEquals("breakfast_menu", - d.getChildNodes().item(1).getNodeName()); - } catch (IOException ioe) { - fail("Unexpected IOException " + ioe.toString()); - } catch (SAXException sax) { - fail("Unexpected SAXException " + sax.toString()); - } + assertEquals(2, d.getChildNodes().getLength()); + assertEquals("#comment", + d.getChildNodes().item(0).getNodeName()); + assertEquals("breakfast_menu", + d.getChildNodes().item(1).getNodeName()); // case 2: Try to call parse with null argument try { @@ -587,10 +581,6 @@ public class DocumentBuilderTest extends TestCase { fail("Expected IllegalArgumentException was not thrown"); } catch (IllegalArgumentException iae) { // expected - } catch (IOException ioe) { - fail("Unexpected IOException " + ioe.toString()); - } catch (SAXException sax) { - fail("Unexpected SAXException " + sax.toString()); } // case 3: Try to parse a non-existent uri @@ -599,8 +589,6 @@ public class DocumentBuilderTest extends TestCase { fail("Expected IOException was not thrown"); } catch (IOException ioe) { // expected - } catch (SAXException sax) { - fail("Unexpected SAXException " + sax.toString()); } // case 4: Try to parse incorrect xml file @@ -608,8 +596,6 @@ public class DocumentBuilderTest extends TestCase { f = new File(getClass().getResource("/wrong.xml").getFile()); db.parse(f.getAbsolutePath()); fail("Expected SAXException was not thrown"); - } catch (IOException ioe) { - fail("Unexpected IOException " + ioe.toString()); } catch (SAXException sax) { // expected } diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java index ca7cf71..e6d6481 100644 --- a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java +++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java @@ -677,8 +677,7 @@ public class SAXParserTest extends TestCase { MyDefaultHandler dh = new MyDefaultHandler(); InputStream is = new FileInputStream(list_wf[i]); parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID); - assertTrue(SAXParserTestSupport.equalsMaps(hm, - dh.createData())); + assertEquals(hm, dh.createData()); } catch (IOException ioe) { fail("Unexpected IOException " + ioe.toString()); } catch (SAXException sax) { diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java index 89da364..597e35e 100644 --- a/xml/src/test/java/tests/xml/AllTests.java +++ b/xml/src/test/java/tests/xml/AllTests.java @@ -24,6 +24,7 @@ public class AllTests { public static Test suite() { TestSuite suite = tests.TestSuiteFactory.createTestSuite(); + suite.addTestSuite(DomTest.class); suite.addTestSuite(SimpleParserTest.class); suite.addTestSuite(SimpleBuilderTest.class); suite.addTestSuite(NodeTest.class); diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java index 5f0a19a..69e8b37 100644 --- a/xml/src/test/java/tests/xml/DomTest.java +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -109,7 +109,6 @@ public class DomTest extends TestCase { factory.setNamespaceAware(true); builder = factory.newDocumentBuilder(); domImplementation = builder.getDOMImplementation(); - document = builder.parse(new InputSource(new StringReader(xml))); // doctype nodes @@ -448,7 +447,6 @@ public class DomTest extends TestCase { document.appendChild(root); EntityReference entityReference = document.createEntityReference("sp"); - entityReference.setNodeValue("Maple Syrup"); root.appendChild(entityReference); try { @@ -461,8 +459,7 @@ public class DomTest extends TestCase { public void testAttributeSetTextContent() throws TransformerException { String original = domToString(document); standard.setTextContent("foobar"); - String expected = original.replaceFirst( - "standard=\"strawberry\"", "standard=\"foobar\""); + String expected = original.replace("standard=\"strawberry\"", "standard=\"foobar\""); assertEquals(expected, domToString(document)); } @@ -614,8 +611,136 @@ public class DomTest extends TestCase { } } - private String domToString(Document document) - throws TransformerException { + public void testIsElementContentWhitespaceWithoutDeclaration() throws Exception { + String xml = "<menu> <item/> </menu>"; + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Text text = (Text) factory.newDocumentBuilder() + .parse(new InputSource(new StringReader(xml))) + .getDocumentElement().getChildNodes().item(0); + assertFalse(text.isElementContentWhitespace()); + } + + public void testIsElementContentWhitespaceWithDeclaration() throws Exception { + String xml = "<!DOCTYPE menu [\n" + + " <!ELEMENT menu (item)*>\n" + + " <!ELEMENT item (#PCDATA)>\n" + + "]><menu> <item/> </menu>"; + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Text text = (Text) factory.newDocumentBuilder() + .parse(new InputSource(new StringReader(xml))) + .getDocumentElement().getChildNodes().item(0); + assertTrue("This implementation does not recognize element content whitespace", + text.isElementContentWhitespace()); + } + + public void testGetWholeTextFirst() { + assertEquals("Belgian waffles & strawberries (< 5g of fat)", + descriptionText1.getWholeText()); + } + + public void testGetWholeTextMiddle() { + assertEquals("This implementation doesn't include preceding nodes in getWholeText()", + "Belgian waffles & strawberries (< 5g of fat)", descriptionText2.getWholeText()); + } + + public void testGetWholeTextLast() { + assertEquals("This implementation doesn't include preceding nodes in getWholeText()", + "Belgian waffles & strawberries (< 5g of fat)", descriptionText3.getWholeText()); + } + + public void testGetWholeTextOnly() { + assertEquals("60%", vitamincText.getWholeText()); + } + + public void testGetWholeTextWithEntityReference() { + EntityReference spReference = document.createEntityReference("sp"); + description.insertBefore(spReference, descriptionText2); + + assertEquals("This implementation doesn't resolve entity references in getWholeText()", + "BelgianMaple Syrup waffles & strawberries (< 5g of fat)", + descriptionText1.getWholeText()); + } + + public void testReplaceWholeTextFirst() throws TransformerException { + String original = domToString(document); + Text replacement = descriptionText1.replaceWholeText("Eggos"); + assertSame(descriptionText1, replacement); + String expected = original.replace( + "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos"); + assertEquals(expected, domToString(document)); + } + + public void testReplaceWholeTextMiddle() throws TransformerException { + String original = domToString(document); + Text replacement = descriptionText2.replaceWholeText("Eggos"); + assertSame(descriptionText2, replacement); + String expected = original.replace( + "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "<![CDATA[Eggos]]>"); + assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()", + expected, domToString(document)); + } + + public void testReplaceWholeTextLast() throws TransformerException { + String original = domToString(document); + Text replacement = descriptionText3.replaceWholeText("Eggos"); + assertSame(descriptionText3, replacement); + String expected = original.replace( + "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos"); + assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()", + expected, domToString(document)); + } + + public void testReplaceWholeTextOnly() throws TransformerException { + String original = domToString(document); + Text replacement = vitamincText.replaceWholeText("70%"); + assertEquals(Node.TEXT_NODE, replacement.getNodeType()); + assertSame(vitamincText, replacement); + String expected = original.replace("60%", "70%"); + assertEquals(expected, domToString(document)); + } + + public void testReplaceWholeTextFirstWithNull() throws TransformerException { + String original = domToString(document); + assertNull(descriptionText1.replaceWholeText(null)); + String expected = original.replaceFirst(">.*</description>", "/>"); + assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)", + expected, domToString(document)); + } + + public void testReplaceWholeTextMiddleWithNull() throws TransformerException { + String original = domToString(document); + assertNull(descriptionText2.replaceWholeText(null)); + String expected = original.replaceFirst(">.*</description>", "/>"); + assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)", + expected, domToString(document)); + } + + public void testReplaceWholeTextLastWithNull() throws TransformerException { + String original = domToString(document); + assertNull(descriptionText3.replaceWholeText(null)); + String expected = original.replaceFirst(">.*</description>", "/>"); + assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)", + expected, domToString(document)); + } + + public void testReplaceWholeTextFirstWithEmptyString() throws TransformerException { + String original = domToString(document); + assertNull(descriptionText1.replaceWholeText("")); + String expected = original.replaceFirst(">.*</description>", "/>"); + assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)", + expected, domToString(document)); + } + + public void testReplaceWholeTextOnlyWithEmptyString() throws TransformerException { + String original = domToString(document); + assertNull(vitamincText.replaceWholeText("")); + String expected = original.replaceFirst(">.*</a:vitaminc>", "/>"); + assertEquals(expected, domToString(document)); + } + + private String domToString(Document document) throws TransformerException { StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(document), new StreamResult(writer)); return writer.toString(); |