diff options
Diffstat (limited to 'libjava/classpath/java')
21 files changed, 514 insertions, 34 deletions
diff --git a/libjava/classpath/java/io/Console.java b/libjava/classpath/java/io/Console.java new file mode 100644 index 0000000..5434b02 --- /dev/null +++ b/libjava/classpath/java/io/Console.java @@ -0,0 +1,122 @@ +/* Console.java -- A character-based console device + Copyright (C) 2012 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.io; + +/** + * @since 1.6 + */ +public final class Console implements Flushable +{ + private static Console console = new Console(); + + public static Console console() + { + return console; + } + + private Console() + { + } + + public PrintWriter writer() + { + return new PrintWriter(new OutputStreamWriter(System.out)); + } + + public Reader reader() + { + return new InputStreamReader(System.in); + } + + public Console format(String fmt, Object... args) + { + System.out.printf(fmt, args); + + return this; + } + + public Console printf(String fmt, Object... args) + { + return format(fmt, args); + } + + public String readLine(String fmt, Object... args) + { + format(fmt, args); + return readLine(); + } + + public String readLine() + { + String result = null; + try + { + result = new BufferedReader(reader()).readLine(); + } + catch (IOException e) + { + throw new IOError(e); + } + return result; + } + + public char[] readPassword(String fmt, Object... args) + { + format(fmt, args); + return readPassword(); + } + + public char[] readPassword() + { + String s = VMConsole.readPassword(this); + + System.out.println(); + + if (s == null) + { + return null; + } + return s.toCharArray(); + } + + public void flush() throws IOException + { + System.out.flush(); + } +} diff --git a/libjava/classpath/java/io/File.java b/libjava/classpath/java/io/File.java index 4f670e1..080b52f 100644 --- a/libjava/classpath/java/io/File.java +++ b/libjava/classpath/java/io/File.java @@ -700,11 +700,13 @@ public class File implements Serializable, Comparable<File> * * @return <code>true</code> if the file is hidden, <code>false</code> * otherwise. - * + * @throws SecurityException if a security manager exists and denies + * read access to this file. * @since 1.2 */ public boolean isHidden() { + checkRead(); return VMFile.isHidden(path); } diff --git a/libjava/classpath/java/io/IOError.java b/libjava/classpath/java/io/IOError.java new file mode 100644 index 0000000..52acb38 --- /dev/null +++ b/libjava/classpath/java/io/IOError.java @@ -0,0 +1,58 @@ +/* IOError.java -- Throw when unrecoverable I/O error happens. + Copyright (C) 2012 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.io; + +/** + * Throw when unrecoverable I/O error happens. + * + * @since 1.6 + */ +public class IOError extends Error +{ + private static final long serialVersionUID = 67100927991680413L; + + /** + * Create a new instance with a cause. + * @param cause the cause + */ + public IOError(Throwable cause) + { + super(cause); + } +} diff --git a/libjava/classpath/java/io/ObjectOutputStream.java b/libjava/classpath/java/io/ObjectOutputStream.java index 71d2e0b..8abf7f5 100644 --- a/libjava/classpath/java/io/ObjectOutputStream.java +++ b/libjava/classpath/java/io/ObjectOutputStream.java @@ -48,6 +48,8 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * An <code>ObjectOutputStream</code> can be used to write objects @@ -136,6 +138,10 @@ public class ObjectOutputStream extends OutputStream */ public ObjectOutputStream (OutputStream out) throws IOException { + SecurityManager secMan = System.getSecurityManager(); + if (secMan != null && overridesMethods(getClass())) + secMan.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); + realOutput = new DataOutputStream(out); blockData = new byte[ BUFFER_SIZE ]; blockDataCount = 0; @@ -1487,4 +1493,44 @@ public class ObjectOutputStream extends OutputStream private boolean dump = false; private static final boolean DEBUG = false; + + /** + * Returns true if the given class overrides either of the + * methods <code>putFields</code> or <code>writeUnshared</code>. + * + * @param clazz the class to check. + * @return true if the class overrides one of the methods. + */ + private static boolean overridesMethods(final Class<?> clazz) + { + if (clazz == ObjectOutputStream.class) + return false; + + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + public Boolean run() + { + Method[] methods = clazz.getDeclaredMethods(); + for (int a = 0; a < methods.length; ++a) + { + String name = methods[a].getName(); + if (name.equals("writeUnshared")) + { + Class<?>[] paramTypes = methods[a].getParameterTypes(); + if (paramTypes.length == 1 && + paramTypes[0] == Object.class && + methods[a].getReturnType() == Void.class) + return true; + } + else if (name.equals("putFields")) + { + if (methods[a].getParameterTypes().length == 0 && + methods[a].getReturnType() == PutField.class) + return true; + } + } + return false; + } + }); + } + } diff --git a/libjava/classpath/java/io/PrintStream.java b/libjava/classpath/java/io/PrintStream.java index eaab7c3..caa6035 100644 --- a/libjava/classpath/java/io/PrintStream.java +++ b/libjava/classpath/java/io/PrintStream.java @@ -181,10 +181,15 @@ public class PrintStream extends FilterOutputStream implements Appendable * @param out The <code>OutputStream</code> to write to. * @param auto_flush <code>true</code> to flush the stream after every * line, <code>false</code> otherwise + * @exception NullPointerException If out is null. */ public PrintStream (OutputStream out, boolean auto_flush) { super (out); + + if (out == null) + throw new NullPointerException("out is null"); + String encoding; try { encoding = SystemProperties.getProperty("file.encoding"); @@ -213,12 +218,19 @@ public class PrintStream extends FilterOutputStream implements Appendable * line, <code>false</code> otherwise * @param encoding The name of the character encoding to use for this * object. + * @exception NullPointerException If out or encoding is null. */ public PrintStream (OutputStream out, boolean auto_flush, String encoding) throws UnsupportedEncodingException { super (out); + if (out == null) + throw new NullPointerException("out is null"); + + if (encoding == null) + throw new NullPointerException("encoding is null"); + new String(new byte[]{0}, encoding); // check if encoding is supported this.encoding = encoding; this.auto_flush = auto_flush; diff --git a/libjava/classpath/java/lang/Class.java b/libjava/classpath/java/lang/Class.java index 1caee01..af0a0a2 100644 --- a/libjava/classpath/java/lang/Class.java +++ b/libjava/classpath/java/lang/Class.java @@ -440,11 +440,14 @@ public final class Class<T> * @return the field * @throws NoSuchFieldException if the field does not exist * @throws SecurityException if the security check fails + * @throws NullPointerException if <code>fieldName</code> is null * @see #getDeclaredFields() * @since 1.1 */ public Field getDeclaredField(String name) throws NoSuchFieldException { + if (name == null) + throw new NullPointerException(); memberAccessCheck(Member.DECLARED); Field[] fields = getDeclaredFields(false); for (int i = 0; i < fields.length; i++) @@ -496,12 +499,15 @@ public final class Class<T> * @return the method * @throws NoSuchMethodException if the method does not exist * @throws SecurityException if the security check fails + * @throws NullPointerException if <code>methodName</code> is null * @see #getDeclaredMethods() * @since 1.1 */ public Method getDeclaredMethod(String methodName, Class<?>... types) throws NoSuchMethodException { + if (methodName == null) + throw new NullPointerException(); memberAccessCheck(Member.DECLARED); Method match = matchMethod(getDeclaredMethods(false), methodName, types); if (match == null) @@ -560,12 +566,15 @@ public final class Class<T> * @return the field * @throws NoSuchFieldException if the field does not exist * @throws SecurityException if the security check fails + * @throws NullPointerException if <code>fieldName</code> is null * @see #getFields() * @since 1.1 */ public Field getField(String fieldName) throws NoSuchFieldException { + if (fieldName == null) + throw new NullPointerException(); memberAccessCheck(Member.PUBLIC); Field field = internalGetField(fieldName); if (field == null) @@ -700,12 +709,15 @@ public final class Class<T> * @return the method * @throws NoSuchMethodException if the method does not exist * @throws SecurityException if the security check fails + * @throws NullPointerException if <code>methodName</code> is null * @see #getMethods() * @since 1.1 */ public Method getMethod(String methodName, Class<?>... types) throws NoSuchMethodException { + if (methodName == null) + throw new NullPointerException(); memberAccessCheck(Member.PUBLIC); Method method = internalGetMethod(methodName, types); if (method == null) diff --git a/libjava/classpath/java/lang/System.java b/libjava/classpath/java/lang/System.java index 39d6da2..51b3259 100644 --- a/libjava/classpath/java/lang/System.java +++ b/libjava/classpath/java/lang/System.java @@ -1,5 +1,5 @@ /* System.java -- useful methods to interface with the system - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2012 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,6 +45,7 @@ import gnu.classpath.VMStackWalker; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.io.Console; import java.nio.channels.Channel; import java.nio.channels.spi.SelectorProvider; import java.util.AbstractCollection; @@ -703,6 +704,14 @@ public final class System return SelectorProvider.provider().inheritedChannel(); } + /* + * @since 1.6 + */ + public static Console console() + { + return Console.console(); + } + /** * This is a specialised <code>Collection</code>, providing * the necessary provisions for the collections used by the diff --git a/libjava/classpath/java/math/BigInteger.java b/libjava/classpath/java/math/BigInteger.java index 953e557..00f5c70 100644 --- a/libjava/classpath/java/math/BigInteger.java +++ b/libjava/classpath/java/math/BigInteger.java @@ -1,5 +1,6 @@ /* java.math.BigInteger -- Arbitary precision integers - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2010 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -64,7 +65,8 @@ import java.util.logging.Logger; */ public class BigInteger extends Number implements Comparable<BigInteger> { - private static final Logger log = Logger.getLogger(BigInteger.class.getName()); + private static final Logger log = Configuration.DEBUG ? + Logger.getLogger(BigInteger.class.getName()) : null; /** All integers are stored in 2's-complement form. * If words == null, the ival is the value of this BigInteger. diff --git a/libjava/classpath/java/net/DatagramSocket.java b/libjava/classpath/java/net/DatagramSocket.java index 6ca9c42..baa572c 100644 --- a/libjava/classpath/java/net/DatagramSocket.java +++ b/libjava/classpath/java/net/DatagramSocket.java @@ -525,7 +525,27 @@ public class DatagramSocket SecurityManager sm = System.getSecurityManager(); if (sm != null) - sm.checkConnect(address.getHostAddress(), port); + { + if (address.isMulticastAddress()) + sm.checkMulticast(address); + else + { + sm.checkConnect(address.getHostAddress(), port); + sm.checkAccept(address.getHostAddress(), port); + } + } + + if (!isBound()) + { + try + { + bind(new InetSocketAddress(0)); + } + catch (SocketException e) + { + throw new Error("Binding socket failed.", e); + } + } try { diff --git a/libjava/classpath/java/net/Socket.java b/libjava/classpath/java/net/Socket.java index d61e81f..32b12e8 100644 --- a/libjava/classpath/java/net/Socket.java +++ b/libjava/classpath/java/net/Socket.java @@ -428,7 +428,9 @@ public class Socket * @exception IllegalBlockingModeException If this socket has an associated * channel, and the channel is in non-blocking mode * @exception SocketTimeoutException If the timeout is reached - * + * @throws SecurityException if the SocketAddress is an {@link InetSocketAddress} + * and a security manager is present which does not + * allow connections on the given host and port. * @since 1.4 */ public void connect(SocketAddress endpoint, int timeout) @@ -440,6 +442,13 @@ public class Socket if (! (endpoint instanceof InetSocketAddress)) throw new IllegalArgumentException("unsupported address type"); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + InetSocketAddress inetAddr = (InetSocketAddress) endpoint; + sm.checkConnect(inetAddr.getHostName(), inetAddr.getPort()); + } + // The Sun spec says that if we have an associated channel and // it is in non-blocking mode, we throw an IllegalBlockingModeException. // However, in our implementation if the channel itself initiated this diff --git a/libjava/classpath/java/nio/channels/spi/SelectorProvider.java b/libjava/classpath/java/nio/channels/spi/SelectorProvider.java index 821bc43..18b9e83 100644 --- a/libjava/classpath/java/nio/channels/spi/SelectorProvider.java +++ b/libjava/classpath/java/nio/channels/spi/SelectorProvider.java @@ -46,6 +46,8 @@ import java.nio.channels.Pipe; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * @author Michael Koch @@ -145,14 +147,18 @@ public abstract class SelectorProvider * Returns the system-wide default selector provider for this invocation * of the Java virtual machine. * - * @return the default seletor provider + * @return the default selector provider */ public static synchronized SelectorProvider provider() { if (systemDefaultProvider == null) { - String propertyValue = - System.getProperty("java.nio.channels.spi.SelectorProvider"); + String propertyValue = AccessController.doPrivileged(new PrivilegedAction<String> () { + public String run() + { + return System.getProperty("java.nio.channels.spi.SelectorProvider"); + } + }); if (propertyValue == null || propertyValue.equals("")) systemDefaultProvider = new SelectorProviderImpl(); diff --git a/libjava/classpath/java/security/KeyStore.java b/libjava/classpath/java/security/KeyStore.java index b7a0e2a..25173e5 100644 --- a/libjava/classpath/java/security/KeyStore.java +++ b/libjava/classpath/java/security/KeyStore.java @@ -214,7 +214,12 @@ public class KeyStore { // Security reads every property in java.security so it // will return this property if it exists. - String tmp = Security.getProperty("keystore.type"); + String tmp = AccessController.doPrivileged(new PrivilegedAction<String> () { + public String run() + { + return Security.getProperty("keystore.type"); + } + }); if (tmp == null) tmp = "gkr"; diff --git a/libjava/classpath/java/security/ProtectionDomain.java b/libjava/classpath/java/security/ProtectionDomain.java index d5d657d..7be5875 100644 --- a/libjava/classpath/java/security/ProtectionDomain.java +++ b/libjava/classpath/java/security/ProtectionDomain.java @@ -41,6 +41,8 @@ import gnu.classpath.SystemProperties; import gnu.java.lang.CPStringBuilder; +import java.util.Enumeration; + /** * This class represents a group of classes, along with their granted * permissions. The classes are identified by a {@link CodeSource}. Thus, any @@ -71,6 +73,9 @@ public class ProtectionDomain /** Post 1.4 the policy may be refreshed! use false for pre 1.4. */ private boolean staticBinding; + /** True if this protection domain has all permissions */ + private boolean hasAllPermissions; + /** * Initializes a new instance of <code>ProtectionDomain</code> representing * the specified {@link CodeSource} and set of permissions. No permissions @@ -128,6 +133,13 @@ public class ProtectionDomain { perms = permissions; perms.setReadOnly(); + /* Check if this protection domain has all permissions */ + Enumeration<Permission> e = permissions.elements(); + while (e.hasMoreElements()) + { + if (e.nextElement() instanceof AllPermission) + hasAllPermissions = true; + } } this.classloader = classloader; @@ -190,6 +202,8 @@ public class ProtectionDomain */ public boolean implies(Permission permission) { + if (hasAllPermissions) + return true; if (staticBinding) return (perms == null ? false : perms.implies(permission)); // Else dynamically bound. Do we have it? @@ -241,7 +255,15 @@ public class ProtectionDomain sb.append(linesep); if (!staticBinding) // include all but dont force loading Policy.currentPolicy if (Policy.isLoaded()) - sb.append(Policy.getCurrentPolicy().getPermissions(this)); + try + { + sb.append(Policy.getPolicy().getPermissions(this)); + } + catch (SecurityException e) + { + // We are not allowed access to the policy. + sb.append(perms); + } else // fallback on this one's permissions sb.append(perms); else diff --git a/libjava/classpath/java/text/DateFormatSymbols.java b/libjava/classpath/java/text/DateFormatSymbols.java index c22dd38..53e7ba0 100644 --- a/libjava/classpath/java/text/DateFormatSymbols.java +++ b/libjava/classpath/java/text/DateFormatSymbols.java @@ -45,6 +45,7 @@ import java.io.IOException; import java.text.spi.DateFormatSymbolsProvider; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -125,9 +126,58 @@ public class DateFormatSymbols implements java.io.Serializable, Cloneable transient String[] dateFormats; transient String[] timeFormats; - private static String[] getStringArray(ResourceBundle res, String name) + /** + * Compiles a string array for a property using data from each of the locales in the + * hierarchy as necessary. + * + * @param bundles the locale hierarchy, starting with the most specific. + * @param name the name of the property. + * @param size the size the array should be when complete. + * @return a completed string array. + */ + private static String[] getStringArray(List<ResourceBundle> bundles, String name, int size) + { + return getStringArray(bundles, name, size, null); + } + + /** + * Compiles a string array for a property using data from each of the locales in the + * hierarchy as necessary. If non-null, the fallback array is also used for "sideways" + * inheritance (e.g. if there is no short name for a month, the long name is used rather + * than the empty string). + * + * @param bundles the locale hierarchy, starting with the most specific. + * @param name the name of the property. + * @param size the size the array should be when complete. + * @param fallback an array of long name fallback strings for data with both long and short names. + * @return a completed string array. + */ + private static String[] getStringArray(List<ResourceBundle> bundles, String name, int size, + String[] fallback) { - return res.getString(name).split("\u00ae"); + String[] data = new String[size]; + Arrays.fill(data, ""); + // Populate array with data from each locale back to the root, starting with the most specific + for (int a = 0; a < bundles.size(); ++a) + { + String localeData = bundles.get(a).getString(name); + String[] array = localeData.split("\u00ae", size); + for (int b = 0; b < data.length; ++b) + { + if (array.length > b && array[b] != null && data[b].isEmpty() && !array[b].isEmpty()) + data[b] = array[b]; + } + } + // Replace any remaining empty strings with data from the fallback array, if non-null + if (fallback != null && fallback.length == size) + { + for (int a = 0; a < data.length; ++a) + { + if (data[a].isEmpty() && fallback[a] != null && !fallback[a].isEmpty()) + data[a] = fallback[a]; + } + } + return data; } private String[][] getZoneStrings(ResourceBundle res, Locale locale) @@ -264,17 +314,26 @@ public class DateFormatSymbols implements java.io.Serializable, Cloneable public DateFormatSymbols (Locale locale) throws MissingResourceException { + ClassLoader ldr = ClassLoader.getSystemClassLoader(); + List<ResourceBundle> bundles = new ArrayList<ResourceBundle>(); ResourceBundle res - = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale, - ClassLoader.getSystemClassLoader()); - - ampms = getStringArray(res, "ampms"); - eras = getStringArray(res, "eras"); + = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale, ldr); + bundles.add(res); + Locale resLocale = res.getLocale(); + while (resLocale != Locale.ROOT) + { + res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + LocaleHelper.getFallbackLocale(resLocale), ldr); + bundles.add(res); + resLocale = res.getLocale(); + } + ampms = getStringArray(bundles, "ampms", 2); + eras = getStringArray(bundles, "eras", 2); localPatternChars = res.getString("localPatternChars"); - months = getStringArray(res, "months"); - shortMonths = getStringArray(res, "shortMonths"); - shortWeekdays = getStringArray(res, "shortWeekdays"); - weekdays = getStringArray(res, "weekdays"); + months = getStringArray(bundles, "months", 13); + shortMonths = getStringArray(bundles, "shortMonths", 13, months); + weekdays = getStringArray(bundles, "weekdays", 8); + shortWeekdays = getStringArray(bundles, "shortWeekdays", 8, weekdays); dateFormats = formatsForKey(res, "DateFormat"); timeFormats = formatsForKey(res, "TimeFormat"); runtimeZoneStrings = getZoneStrings(res, locale); diff --git a/libjava/classpath/java/util/Formatter.java b/libjava/classpath/java/util/Formatter.java index 04ae805..62f6845 100644 --- a/libjava/classpath/java/util/Formatter.java +++ b/libjava/classpath/java/util/Formatter.java @@ -1188,7 +1188,7 @@ public final class Formatter advance(); if (start == index) return -1; - return Integer.decode(format.substring(start, index)); + return Integer.parseInt(format.substring(start, index)); } /** diff --git a/libjava/classpath/java/util/HashMap.java b/libjava/classpath/java/util/HashMap.java index 55d81c6..f5194a2 100644 --- a/libjava/classpath/java/util/HashMap.java +++ b/libjava/classpath/java/util/HashMap.java @@ -100,11 +100,10 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable { /** - * Default number of buckets. This is the value the JDK 1.3 uses. Some - * early documentation specified this value as 101. That is incorrect. + * Default number of buckets; this is currently set to 16. * Package visible for use by HashSet. */ - static final int DEFAULT_CAPACITY = 11; + static final int DEFAULT_CAPACITY = 16; /** * The default load factor; this is explicitly specified by the spec. @@ -344,9 +343,12 @@ public class HashMap<K, V> extends AbstractMap<K, V> int idx = hash(key); HashEntry<K, V> e = buckets[idx]; + int hash1 = key == null ? 0 : key.hashCode(); while (e != null) { - if (equals(key, e.key)) + int hash2 = e.key == null ? 0 : e.key.hashCode(); + + if ((hash1 == hash2) && equals(key, e.key)) { e.access(); // Must call this for bookkeeping in LinkedHashMap. V r = e.value; diff --git a/libjava/classpath/java/util/logging/LogManager.java b/libjava/classpath/java/util/logging/LogManager.java index dffa44d..f8c6c33 100644 --- a/libjava/classpath/java/util/logging/LogManager.java +++ b/libjava/classpath/java/util/logging/LogManager.java @@ -211,11 +211,21 @@ public class LogManager /** * Registers a listener which will be notified when the * logging properties are re-read. + * + * @param listener the event listener to register. + * @throws NullPointerException if the listener is {@code null}. + * @throws SecurityException if a security manager exists and the + * calling code does not have the permission + * {@code LoggingPermission("control")}. */ public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { - /* do not register null. */ - listener.getClass(); + if (listener == null) + throw new NullPointerException("Attempt to add null property change listener"); + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new LoggingPermission("control", null)); pcs.addPropertyChangeListener(listener); } @@ -226,11 +236,22 @@ public class LogManager * If <code>listener</code> has not been registered previously, * nothing happens. Also, no exception is thrown if * <code>listener</code> is <code>null</code>. + * + * @param listener the listener to remove. + * @throws SecurityException if a security manager exists and the + * calling code does not have the permission + * {@code LoggingPermission("control")}. */ public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { if (listener != null) - pcs.removePropertyChangeListener(listener); + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new LoggingPermission("control", null)); + + pcs.removePropertyChangeListener(listener); + } } /** diff --git a/libjava/classpath/java/util/regex/Matcher.java b/libjava/classpath/java/util/regex/Matcher.java index be57471..8d033d5 100644 --- a/libjava/classpath/java/util/regex/Matcher.java +++ b/libjava/classpath/java/util/regex/Matcher.java @@ -169,6 +169,12 @@ public final class Matcher implements MatchResult if (match != null) { int endIndex = match.getEndIndex(); + // Is the match within input limits? + if (endIndex > input.length()) + { + match = null; + return false; + } // Are we stuck at the same position? if (!first && endIndex == position) { @@ -608,4 +614,27 @@ public final class Matcher implements MatchResult return snapshot; } + /** + * Returns a literalized string of s where characters {@code $} and {@code + * \\} are escaped. + * + * @param s the string to literalize. + * @return the literalized string. + * @since 1.5 + */ + public static String quoteReplacement(String s) + { + if (s == null) + throw new NullPointerException(); + CPStringBuilder sb = new CPStringBuilder(); + for (int i = 0; i < s.length(); i++) + { + char ch = s.charAt(i); + if (ch == '$' || ch == '\\') + sb.append('\\'); + sb.append(ch); + } + return sb.toString(); + } + } diff --git a/libjava/classpath/java/util/regex/Pattern.java b/libjava/classpath/java/util/regex/Pattern.java index 7d1fc84..b1c937f 100644 --- a/libjava/classpath/java/util/regex/Pattern.java +++ b/libjava/classpath/java/util/regex/Pattern.java @@ -1,5 +1,6 @@ /* Pattern.java -- Compiled regular expression ready to be applied. - Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2007, 2010 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,6 +38,8 @@ exception statement from your version. */ package java.util.regex; +import gnu.java.lang.CPStringBuilder; + import gnu.java.util.regex.RE; import gnu.java.util.regex.REException; import gnu.java.util.regex.RESyntax; @@ -260,6 +263,41 @@ public final class Pattern implements Serializable } /** + * Returns a literal pattern for the specified String. + * + * @param String to return a literal pattern for. + * @return a literal pattern for the specified String. + * @exception NullPointerException if str is null. + * @since 1.5 + */ + public static String quote(String str) + { + int eInd = str.indexOf("\\E"); + if (eInd < 0) + { + // No need to handle backslashes. + return "\\Q" + str + "\\E"; + } + + CPStringBuilder sb = new CPStringBuilder(str.length() + 16); + sb.append("\\Q"); // start quote + + int pos = 0; + do + { + // A backslash is quoted by another backslash; + // 'E' is not needed to be quoted. + sb.append(str.substring(pos, eInd)) + .append("\\E" + "\\\\" + "E" + "\\Q"); + pos = eInd + 2; + } while ((eInd = str.indexOf("\\E", pos)) >= 0); + + sb.append(str.substring(pos, str.length())) + .append("\\E"); // end quote + return sb.toString(); + } + + /** * Return the regular expression used to construct this object. * @specnote Prior to JDK 1.5 this method had a different behavior * @since 1.5 diff --git a/libjava/classpath/java/util/zip/InflaterHuffmanTree.java b/libjava/classpath/java/util/zip/InflaterHuffmanTree.java index c12c732..1a152d2 100644 --- a/libjava/classpath/java/util/zip/InflaterHuffmanTree.java +++ b/libjava/classpath/java/util/zip/InflaterHuffmanTree.java @@ -95,11 +95,14 @@ class InflaterHuffmanTree blCount[bits]++; } + int max = 0; int code = 0; int treeSize = 512; for (int bits = 1; bits <= MAX_BITLEN; bits++) { nextCode[bits] = code; + if (blCount[bits] > 0) + max = bits; code += blCount[bits] << (16 - bits); if (bits >= 10) { @@ -109,8 +112,8 @@ class InflaterHuffmanTree treeSize += (end - start) >> (16 - bits); } } - if (code != 65536) - throw new DataFormatException("Code lengths don't add up properly."); + if (code != 65536 && max > 1) + throw new DataFormatException("incomplete dynamic bit lengths tree"); /* Now create and fill the extra tables from longest to shortest * bit len. This way the sub trees will be aligned. diff --git a/libjava/classpath/java/util/zip/ZipFile.java b/libjava/classpath/java/util/zip/ZipFile.java index 3963bcb..b582c84 100644 --- a/libjava/classpath/java/util/zip/ZipFile.java +++ b/libjava/classpath/java/util/zip/ZipFile.java @@ -261,7 +261,10 @@ public class ZipFile implements ZipConstants if (inp.readLeInt() != CENSIG) throw new ZipException("Wrong Central Directory signature: " + name); - inp.skip(6); + inp.skip(4); + int flags = inp.readLeShort(); + if ((flags & 1) != 0) + throw new ZipException("invalid CEN header (encrypted entry)"); int method = inp.readLeShort(); int dostime = inp.readLeInt(); int crc = inp.readLeInt(); |