Merge
This commit is contained in:
commit
f70e9b8dd9
@ -29,7 +29,6 @@ FILES_c = \
|
||||
Deflater.c \
|
||||
Inflater.c \
|
||||
ZipFile.c \
|
||||
ZipEntry.c \
|
||||
zadler32.c \
|
||||
zcrc32.c \
|
||||
deflate.c \
|
||||
|
@ -50,15 +50,17 @@ SUNWprivate_1.1 {
|
||||
Java_java_util_zip_Inflater_initIDs;
|
||||
Java_java_util_zip_Inflater_reset;
|
||||
Java_java_util_zip_Inflater_setDictionary;
|
||||
Java_java_util_zip_ZipEntry_initFields;
|
||||
Java_java_util_zip_ZipEntry_initIDs;
|
||||
Java_java_util_zip_ZipFile_close;
|
||||
Java_java_util_zip_ZipFile_freeEntry;
|
||||
Java_java_util_zip_ZipFile_getCSize;
|
||||
Java_java_util_zip_ZipFile_getEntry;
|
||||
Java_java_util_zip_ZipFile_getMethod;
|
||||
Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
Java_java_util_zip_ZipFile_getEntrySize;
|
||||
Java_java_util_zip_ZipFile_getEntryTime;
|
||||
Java_java_util_zip_ZipFile_getNextEntry;
|
||||
Java_java_util_zip_ZipFile_getSize;
|
||||
Java_java_util_zip_ZipFile_getZipMessage;
|
||||
Java_java_util_zip_ZipFile_getTotal;
|
||||
Java_java_util_zip_ZipFile_initIDs;
|
||||
|
@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
@ -19,12 +19,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
@ -50,6 +50,12 @@
|
||||
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
|
||||
#define JAR_ERROR3 "Error: Invalid or corrupt jarfile %s"
|
||||
|
||||
#define CLS_ERROR1 "Error: Could not find the main class %s.\n" JNI_ERROR
|
||||
#define CLS_ERROR2 "Error: Failed to load Main Class: %s\n%s"
|
||||
#define CLS_ERROR3 "Error: No main method found in specified class.\n" GEN_ERROR
|
||||
#define CLS_ERROR4 "Error: Main method not public\n" GEN_ERROR
|
||||
#define CLS_ERROR5 "Error: main-class: attribute exceeds system limits of %d bytes\n" GEN_ERROR
|
||||
|
||||
#define CFG_WARN1 "Warning: %s VM not supported; %s VM will be used"
|
||||
#define CFG_WARN2 "Warning: No leading - on line %d of `%s'"
|
||||
#define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'"
|
||||
|
@ -915,8 +915,14 @@ SelectVersion(int argc, char **argv, char **main_class)
|
||||
* to avoid locating, expanding and parsing the manifest extra
|
||||
* times.
|
||||
*/
|
||||
if (info.main_class != NULL)
|
||||
(void)JLI_StrCat(env_entry, info.main_class);
|
||||
if (info.main_class != NULL) {
|
||||
if (JLI_StrLen(info.main_class) <= MAXNAMELEN) {
|
||||
(void)JLI_StrCat(env_entry, info.main_class);
|
||||
} else {
|
||||
JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
(void)putenv(env_entry);
|
||||
ExecJRE(jre, new_argv);
|
||||
JLI_FreeManifest();
|
||||
|
@ -22,7 +22,6 @@
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -34,6 +33,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import javax.security.auth.Subject;
|
||||
@ -54,7 +54,10 @@ import com.sun.jmx.remote.util.EnvHelp;
|
||||
|
||||
|
||||
public abstract class ClientNotifForwarder {
|
||||
public ClientNotifForwarder(Map<String, ?> env) {
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
public ClientNotifForwarder(Map env) {
|
||||
this(null, env);
|
||||
}
|
||||
|
||||
@ -87,6 +90,8 @@ public abstract class ClientNotifForwarder {
|
||||
this.command = command;
|
||||
if (thread == null) {
|
||||
thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
Runnable r;
|
||||
@ -130,6 +135,7 @@ public abstract class ClientNotifForwarder {
|
||||
|
||||
this.defaultClassLoader = defaultClassLoader;
|
||||
this.executor = ex;
|
||||
this.acc = AccessController.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -380,28 +386,85 @@ public abstract class ClientNotifForwarder {
|
||||
setState(TERMINATED);
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// private classes
|
||||
// -------------------------------------------------
|
||||
|
||||
// -------------------------------------------------
|
||||
// private classes
|
||||
// -------------------------------------------------
|
||||
//
|
||||
|
||||
private class NotifFetcher implements Runnable {
|
||||
|
||||
private volatile boolean alreadyLogged = false;
|
||||
|
||||
private void logOnce(String msg, SecurityException x) {
|
||||
if (alreadyLogged) return;
|
||||
// Log only once.
|
||||
logger.config("setContextClassLoader",msg);
|
||||
if (x != null) logger.fine("setContextClassLoader", x);
|
||||
alreadyLogged = true;
|
||||
}
|
||||
|
||||
// Set new context class loader, returns previous one.
|
||||
private final ClassLoader setContextClassLoader(final ClassLoader loader) {
|
||||
final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
|
||||
// if ctxt is null, log a config message and throw a
|
||||
// SecurityException.
|
||||
if (ctxt == null) {
|
||||
logOnce("AccessControlContext must not be null.",null);
|
||||
throw new SecurityException("AccessControlContext must not be null");
|
||||
}
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<ClassLoader>() {
|
||||
public ClassLoader run() {
|
||||
try {
|
||||
// get context class loader - may throw
|
||||
// SecurityException - though unlikely.
|
||||
final ClassLoader previous =
|
||||
Thread.currentThread().getContextClassLoader();
|
||||
|
||||
// if nothing needs to be done, break here...
|
||||
if (loader == previous) return previous;
|
||||
|
||||
// reset context class loader - may throw
|
||||
// SecurityException
|
||||
Thread.currentThread().setContextClassLoader(loader);
|
||||
return previous;
|
||||
} catch (SecurityException x) {
|
||||
logOnce("Permission to set ContextClassLoader missing. " +
|
||||
"Notifications will not be dispatched. " +
|
||||
"Please check your Java policy configuration: " +
|
||||
x, x);
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}, ctxt);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final ClassLoader previous;
|
||||
if (defaultClassLoader != null) {
|
||||
previous = setContextClassLoader(defaultClassLoader);
|
||||
} else {
|
||||
previous = null;
|
||||
}
|
||||
try {
|
||||
doRun();
|
||||
} finally {
|
||||
if (defaultClassLoader != null) {
|
||||
setContextClassLoader(previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doRun() {
|
||||
synchronized (ClientNotifForwarder.this) {
|
||||
currentFetchThread = Thread.currentThread();
|
||||
|
||||
if (state == STARTING)
|
||||
if (state == STARTING) {
|
||||
setState(STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultClassLoader != null) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
Thread.currentThread().
|
||||
setContextClassLoader(defaultClassLoader);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
NotificationResult nr = null;
|
||||
if (!shouldStop() && (nr = fetchNotifs()) != null) {
|
||||
@ -434,8 +497,9 @@ public abstract class ClientNotifForwarder {
|
||||
// check if an mbean unregistration notif
|
||||
if (!listenerID.equals(mbeanRemovedNotifID)) {
|
||||
final ClientListenerInfo li = infoList.get(listenerID);
|
||||
if (li != null)
|
||||
listeners.put(listenerID,li);
|
||||
if (li != null) {
|
||||
listeners.put(listenerID, li);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
final Notification notif = tn.getNotification();
|
||||
@ -799,9 +863,7 @@ public abstract class ClientNotifForwarder {
|
||||
private long clientSequenceNumber = -1;
|
||||
private final int maxNotifications;
|
||||
private final long timeout;
|
||||
|
||||
private Integer mbeanRemovedNotifID = null;
|
||||
|
||||
private Thread currentFetchThread;
|
||||
|
||||
// state
|
||||
|
@ -111,6 +111,22 @@ public abstract class MBeanServerAccessController
|
||||
*/
|
||||
protected abstract void checkWrite();
|
||||
|
||||
/**
|
||||
* Check if the caller can create the named class. The default
|
||||
* implementation of this method calls {@link #checkWrite()}.
|
||||
*/
|
||||
protected void checkCreate(String className) {
|
||||
checkWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can unregister the named MBean. The default
|
||||
* implementation of this method calls {@link #checkWrite()}.
|
||||
*/
|
||||
protected void checkUnregister(ObjectName name) {
|
||||
checkWrite();
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
//--------------------------------------------
|
||||
//
|
||||
@ -148,7 +164,7 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className, ObjectName name)
|
||||
@ -158,7 +174,7 @@ public abstract class MBeanServerAccessController
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className);
|
||||
@ -170,7 +186,7 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className, ObjectName name,
|
||||
@ -181,7 +197,7 @@ public abstract class MBeanServerAccessController
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
@ -196,7 +212,7 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className,
|
||||
@ -209,7 +225,7 @@ public abstract class MBeanServerAccessController
|
||||
MBeanException,
|
||||
NotCompliantMBeanException,
|
||||
InstanceNotFoundException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
@ -222,7 +238,7 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className,
|
||||
@ -237,7 +253,7 @@ public abstract class MBeanServerAccessController
|
||||
MBeanException,
|
||||
NotCompliantMBeanException,
|
||||
InstanceNotFoundException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
@ -394,45 +410,45 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className)
|
||||
throws ReflectionException, MBeanException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className,
|
||||
Object params[],
|
||||
String signature[])
|
||||
throws ReflectionException, MBeanException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, params, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName)
|
||||
throws ReflectionException, MBeanException, InstanceNotFoundException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, loaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName,
|
||||
Object params[], String signature[])
|
||||
throws ReflectionException, MBeanException, InstanceNotFoundException {
|
||||
checkWrite();
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, loaderName,
|
||||
params, signature);
|
||||
}
|
||||
@ -579,12 +595,12 @@ public abstract class MBeanServerAccessController
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* Call <code>checkUnregister()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void unregisterMBean(ObjectName name)
|
||||
throws InstanceNotFoundException, MBeanRegistrationException {
|
||||
checkWrite();
|
||||
checkUnregister(name);
|
||||
getMBeanServer().unregisterMBean(name);
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,17 @@ import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
/**
|
||||
@ -46,7 +52,8 @@ import javax.security.auth.Subject;
|
||||
* not allowed; in this case the request is not forwarded to the
|
||||
* wrapped object.</p>
|
||||
*
|
||||
* <p>This class implements the {@link #checkRead()} and {@link #checkWrite()}
|
||||
* <p>This class implements the {@link #checkRead()}, {@link #checkWrite()},
|
||||
* {@link #checkCreate(String)}, and {@link #checkUnregister(ObjectName)}
|
||||
* methods based on an access level properties file containing username/access
|
||||
* level pairs. The set of username/access level pairs is passed either as a
|
||||
* filename which denotes a properties file on disk, or directly as an instance
|
||||
@ -56,14 +63,50 @@ import javax.security.auth.Subject;
|
||||
* has exactly one access level. The same access level can be shared by several
|
||||
* usernames.</p>
|
||||
*
|
||||
* <p>The supported access level values are <i>readonly</i> and
|
||||
* <i>readwrite</i>.</p>
|
||||
* <p>The supported access level values are {@code readonly} and
|
||||
* {@code readwrite}. The {@code readwrite} access level can be
|
||||
* qualified by one or more <i>clauses</i>, where each clause looks
|
||||
* like <code>create <i>classNamePattern</i></code> or {@code
|
||||
* unregister}. For example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* monitorRole readonly
|
||||
* controlRole readwrite \
|
||||
* create javax.management.timer.*,javax.management.monitor.* \
|
||||
* unregister
|
||||
* </pre>
|
||||
*
|
||||
* <p>(The continuation lines with {@code \} come from the parser for
|
||||
* Properties files.)</p>
|
||||
*/
|
||||
public class MBeanServerFileAccessController
|
||||
extends MBeanServerAccessController {
|
||||
|
||||
public static final String READONLY = "readonly";
|
||||
public static final String READWRITE = "readwrite";
|
||||
static final String READONLY = "readonly";
|
||||
static final String READWRITE = "readwrite";
|
||||
|
||||
static final String CREATE = "create";
|
||||
static final String UNREGISTER = "unregister";
|
||||
|
||||
private enum AccessType {READ, WRITE, CREATE, UNREGISTER};
|
||||
|
||||
private static class Access {
|
||||
final boolean write;
|
||||
final String[] createPatterns;
|
||||
private boolean unregister;
|
||||
|
||||
Access(boolean write, boolean unregister, List<String> createPatternList) {
|
||||
this.write = write;
|
||||
int npats = (createPatternList == null) ? 0 : createPatternList.size();
|
||||
if (npats == 0)
|
||||
this.createPatterns = NO_STRINGS;
|
||||
else
|
||||
this.createPatterns = createPatternList.toArray(new String[npats]);
|
||||
this.unregister = unregister;
|
||||
}
|
||||
|
||||
private final String[] NO_STRINGS = new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new MBeanServerAccessController that forwards all the
|
||||
@ -87,8 +130,8 @@ public class MBeanServerFileAccessController
|
||||
throws IOException {
|
||||
super();
|
||||
this.accessFileName = accessFileName;
|
||||
props = propertiesFromFile(accessFileName);
|
||||
checkValues(props);
|
||||
Properties props = propertiesFromFile(accessFileName);
|
||||
parseProperties(props);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,14 +166,14 @@ public class MBeanServerFileAccessController
|
||||
* #setMBeanServer} method after doing access checks based on read and
|
||||
* write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties instance.
|
||||
* This constructor makes a copy of the properties instance using its
|
||||
* <code>clone</code> method and it is the copy that is consulted to check
|
||||
* the username and access level of an incoming connection. The original
|
||||
* properties object can be modified without affecting the copy. If the
|
||||
* {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new copy of the
|
||||
* properties object at that time.</p>
|
||||
* <p>This instance is initialized from the specified properties
|
||||
* instance. This constructor makes a copy of the properties
|
||||
* instance and it is the copy that is consulted to check the
|
||||
* username and access level of an incoming connection. The
|
||||
* original properties object can be modified without affecting
|
||||
* the copy. If the {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new
|
||||
* copy of the properties object at that time.</p>
|
||||
*
|
||||
* @param accessFileProps properties list containing the username/access
|
||||
* level entries.
|
||||
@ -145,8 +188,7 @@ public class MBeanServerFileAccessController
|
||||
if (accessFileProps == null)
|
||||
throw new IllegalArgumentException("Null properties");
|
||||
originalProps = accessFileProps;
|
||||
props = (Properties) accessFileProps.clone();
|
||||
checkValues(props);
|
||||
parseProperties(accessFileProps);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,14 +197,14 @@ public class MBeanServerFileAccessController
|
||||
* #setMBeanServer} method after doing access checks based on read and
|
||||
* write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties instance.
|
||||
* This constructor makes a copy of the properties instance using its
|
||||
* <code>clone</code> method and it is the copy that is consulted to check
|
||||
* the username and access level of an incoming connection. The original
|
||||
* properties object can be modified without affecting the copy. If the
|
||||
* {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new copy of the
|
||||
* properties object at that time.</p>
|
||||
* <p>This instance is initialized from the specified properties
|
||||
* instance. This constructor makes a copy of the properties
|
||||
* instance and it is the copy that is consulted to check the
|
||||
* username and access level of an incoming connection. The
|
||||
* original properties object can be modified without affecting
|
||||
* the copy. If the {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new
|
||||
* copy of the properties object at that time.</p>
|
||||
*
|
||||
* @param accessFileProps properties list containing the username/access
|
||||
* level entries.
|
||||
@ -184,16 +226,36 @@ public class MBeanServerFileAccessController
|
||||
* Check if the caller can do read operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkRead() {
|
||||
checkAccessLevel(READONLY);
|
||||
checkAccess(AccessType.READ, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do write operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkWrite() {
|
||||
checkAccessLevel(READWRITE);
|
||||
checkAccess(AccessType.WRITE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can create MBeans or instances of the given class.
|
||||
* This method does nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkCreate(String className) {
|
||||
checkAccess(AccessType.CREATE, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do unregister operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkUnregister(ObjectName name) {
|
||||
checkAccess(AccessType.UNREGISTER, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,14 +280,13 @@ public class MBeanServerFileAccessController
|
||||
* @exception IllegalArgumentException if any of the supplied access
|
||||
* level values differs from "readonly" or "readwrite".
|
||||
*/
|
||||
public void refresh() throws IOException {
|
||||
synchronized (props) {
|
||||
if (accessFileName == null)
|
||||
props = (Properties) originalProps.clone();
|
||||
else
|
||||
props = propertiesFromFile(accessFileName);
|
||||
checkValues(props);
|
||||
}
|
||||
public synchronized void refresh() throws IOException {
|
||||
Properties props;
|
||||
if (accessFileName == null)
|
||||
props = (Properties) originalProps;
|
||||
else
|
||||
props = propertiesFromFile(accessFileName);
|
||||
parseProperties(props);
|
||||
}
|
||||
|
||||
private static Properties propertiesFromFile(String fname)
|
||||
@ -240,7 +301,7 @@ public class MBeanServerFileAccessController
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAccessLevel(String accessLevel) {
|
||||
private synchronized void checkAccess(AccessType requiredAccess, String arg) {
|
||||
final AccessControlContext acc = AccessController.getContext();
|
||||
final Subject s =
|
||||
AccessController.doPrivileged(new PrivilegedAction<Subject>() {
|
||||
@ -249,39 +310,235 @@ public class MBeanServerFileAccessController
|
||||
}
|
||||
});
|
||||
if (s == null) return; /* security has not been enabled */
|
||||
final Set<Principal> principals = s.getPrincipals();
|
||||
for (Principal p : principals) {
|
||||
String grantedAccessLevel;
|
||||
synchronized (props) {
|
||||
grantedAccessLevel = props.getProperty(p.getName());
|
||||
}
|
||||
if (grantedAccessLevel != null) {
|
||||
if (accessLevel.equals(READONLY) &&
|
||||
(grantedAccessLevel.equals(READONLY) ||
|
||||
grantedAccessLevel.equals(READWRITE)))
|
||||
return;
|
||||
if (accessLevel.equals(READWRITE) &&
|
||||
grantedAccessLevel.equals(READWRITE))
|
||||
final Set principals = s.getPrincipals();
|
||||
String newPropertyValue = null;
|
||||
for (Iterator i = principals.iterator(); i.hasNext(); ) {
|
||||
final Principal p = (Principal) i.next();
|
||||
Access access = accessMap.get(p.getName());
|
||||
if (access != null) {
|
||||
boolean ok;
|
||||
switch (requiredAccess) {
|
||||
case READ:
|
||||
ok = true; // all access entries imply read
|
||||
break;
|
||||
case WRITE:
|
||||
ok = access.write;
|
||||
break;
|
||||
case UNREGISTER:
|
||||
ok = access.unregister;
|
||||
if (!ok && access.write)
|
||||
newPropertyValue = "unregister";
|
||||
break;
|
||||
case CREATE:
|
||||
ok = checkCreateAccess(access, arg);
|
||||
if (!ok && access.write)
|
||||
newPropertyValue = "create " + arg;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
if (ok)
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new SecurityException("Access denied! Invalid access level for " +
|
||||
"requested MBeanServer operation.");
|
||||
SecurityException se = new SecurityException("Access denied! Invalid " +
|
||||
"access level for requested MBeanServer operation.");
|
||||
// Add some more information to help people with deployments that
|
||||
// worked before we required explicit create clauses. We're not giving
|
||||
// any information to the bad guys, other than that the access control
|
||||
// is based on a file, which they could have worked out from the stack
|
||||
// trace anyway.
|
||||
if (newPropertyValue != null) {
|
||||
SecurityException se2 = new SecurityException("Access property " +
|
||||
"for this identity should be similar to: " + READWRITE +
|
||||
" " + newPropertyValue);
|
||||
se.initCause(se2);
|
||||
}
|
||||
throw se;
|
||||
}
|
||||
|
||||
private void checkValues(Properties props) {
|
||||
Collection<?> c = props.values();
|
||||
for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
|
||||
final String accessLevel = (String) i.next();
|
||||
if (!accessLevel.equals(READONLY) &&
|
||||
!accessLevel.equals(READWRITE)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Syntax error in access level entry [" + accessLevel + "]");
|
||||
}
|
||||
private static boolean checkCreateAccess(Access access, String className) {
|
||||
for (String classNamePattern : access.createPatterns) {
|
||||
if (classNameMatch(classNamePattern, className))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean classNameMatch(String pattern, String className) {
|
||||
// We studiously avoided regexes when parsing the properties file,
|
||||
// because that is done whenever the VM is started with the
|
||||
// appropriate -Dcom.sun.management options, even if nobody ever
|
||||
// creates an MBean. We don't want to incur the overhead of loading
|
||||
// all the regex code whenever those options are specified, but if we
|
||||
// get as far as here then the VM is already running and somebody is
|
||||
// doing the very unusual operation of remotely creating an MBean.
|
||||
// Because that operation is so unusual, we don't try to optimize
|
||||
// by hand-matching or by caching compiled Pattern objects.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringTokenizer stok = new StringTokenizer(pattern, "*", true);
|
||||
while (stok.hasMoreTokens()) {
|
||||
String tok = stok.nextToken();
|
||||
if (tok.equals("*"))
|
||||
sb.append("[^.]*");
|
||||
else
|
||||
sb.append(Pattern.quote(tok));
|
||||
}
|
||||
return className.matches(sb.toString());
|
||||
}
|
||||
|
||||
private void parseProperties(Properties props) {
|
||||
this.accessMap = new HashMap<String, Access>();
|
||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||
String identity = (String) entry.getKey();
|
||||
String accessString = (String) entry.getValue();
|
||||
Access access = Parser.parseAccess(identity, accessString);
|
||||
accessMap.put(identity, access);
|
||||
}
|
||||
}
|
||||
|
||||
private Properties props;
|
||||
private static class Parser {
|
||||
private final static int EOS = -1; // pseudo-codepoint "end of string"
|
||||
static {
|
||||
assert !Character.isWhitespace(EOS);
|
||||
}
|
||||
|
||||
private final String identity; // just for better error messages
|
||||
private final String s; // the string we're parsing
|
||||
private final int len; // s.length()
|
||||
private int i;
|
||||
private int c;
|
||||
// At any point, either c is s.codePointAt(i), or i == len and
|
||||
// c is EOS. We use int rather than char because it is conceivable
|
||||
// (if unlikely) that a classname in a create clause might contain
|
||||
// "supplementary characters", the ones that don't fit in the original
|
||||
// 16 bits for Unicode.
|
||||
|
||||
private Parser(String identity, String s) {
|
||||
this.identity = identity;
|
||||
this.s = s;
|
||||
this.len = s.length();
|
||||
this.i = 0;
|
||||
if (i < len)
|
||||
this.c = s.codePointAt(i);
|
||||
else
|
||||
this.c = EOS;
|
||||
}
|
||||
|
||||
static Access parseAccess(String identity, String s) {
|
||||
return new Parser(identity, s).parseAccess();
|
||||
}
|
||||
|
||||
private Access parseAccess() {
|
||||
skipSpace();
|
||||
String type = parseWord();
|
||||
Access access;
|
||||
if (type.equals(READONLY))
|
||||
access = new Access(false, false, null);
|
||||
else if (type.equals(READWRITE))
|
||||
access = parseReadWrite();
|
||||
else {
|
||||
throw syntax("Expected " + READONLY + " or " + READWRITE +
|
||||
": " + type);
|
||||
}
|
||||
if (c != EOS)
|
||||
throw syntax("Extra text at end of line");
|
||||
return access;
|
||||
}
|
||||
|
||||
private Access parseReadWrite() {
|
||||
List<String> createClasses = new ArrayList<String>();
|
||||
boolean unregister = false;
|
||||
while (true) {
|
||||
skipSpace();
|
||||
if (c == EOS)
|
||||
break;
|
||||
String type = parseWord();
|
||||
if (type.equals(UNREGISTER))
|
||||
unregister = true;
|
||||
else if (type.equals(CREATE))
|
||||
parseCreate(createClasses);
|
||||
else
|
||||
throw syntax("Unrecognized keyword " + type);
|
||||
}
|
||||
return new Access(true, unregister, createClasses);
|
||||
}
|
||||
|
||||
private void parseCreate(List<String> createClasses) {
|
||||
while (true) {
|
||||
skipSpace();
|
||||
createClasses.add(parseClassName());
|
||||
skipSpace();
|
||||
if (c == ',')
|
||||
next();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String parseClassName() {
|
||||
// We don't check that classname components begin with suitable
|
||||
// characters (so we accept 1.2.3 for example). This means that
|
||||
// there are only two states, which we can call dotOK and !dotOK
|
||||
// according as a dot (.) is legal or not. Initially we're in
|
||||
// !dotOK since a classname can't start with a dot; after a dot
|
||||
// we're in !dotOK again; and after any other characters we're in
|
||||
// dotOK. The classname is only accepted if we end in dotOK,
|
||||
// so we reject an empty name or a name that ends with a dot.
|
||||
final int start = i;
|
||||
boolean dotOK = false;
|
||||
while (true) {
|
||||
if (c == '.') {
|
||||
if (!dotOK)
|
||||
throw syntax("Bad . in class name");
|
||||
dotOK = false;
|
||||
} else if (c == '*' || Character.isJavaIdentifierPart(c))
|
||||
dotOK = true;
|
||||
else
|
||||
break;
|
||||
next();
|
||||
}
|
||||
String className = s.substring(start, i);
|
||||
if (!dotOK)
|
||||
throw syntax("Bad class name " + className);
|
||||
return className;
|
||||
}
|
||||
|
||||
// Advance c and i to the next character, unless already at EOS.
|
||||
private void next() {
|
||||
if (c != EOS) {
|
||||
i += Character.charCount(c);
|
||||
if (i < len)
|
||||
c = s.codePointAt(i);
|
||||
else
|
||||
c = EOS;
|
||||
}
|
||||
}
|
||||
|
||||
private void skipSpace() {
|
||||
while (Character.isWhitespace(c))
|
||||
next();
|
||||
}
|
||||
|
||||
private String parseWord() {
|
||||
skipSpace();
|
||||
if (c == EOS)
|
||||
throw syntax("Expected word at end of line");
|
||||
final int start = i;
|
||||
while (c != EOS && !Character.isWhitespace(c))
|
||||
next();
|
||||
String word = s.substring(start, i);
|
||||
skipSpace();
|
||||
return word;
|
||||
}
|
||||
|
||||
private IllegalArgumentException syntax(String msg) {
|
||||
return new IllegalArgumentException(
|
||||
msg + " [" + identity + " " + s + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Access> accessMap;
|
||||
private Properties originalProps;
|
||||
private String accessFileName;
|
||||
}
|
||||
|
@ -302,7 +302,16 @@ final public class LdapCtx extends ComponentDirContext
|
||||
|
||||
schemaTrees = new Hashtable(11, 0.75f);
|
||||
initEnv();
|
||||
connect(false);
|
||||
try {
|
||||
connect(false);
|
||||
} catch (NamingException e) {
|
||||
try {
|
||||
close();
|
||||
} catch (Exception e2) {
|
||||
// Nothing
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
LdapCtx(LdapCtx existing, String newDN) throws NamingException {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,12 +33,33 @@ import java.security.PrivilegedAction;
|
||||
|
||||
final class VersionHelper12 extends VersionHelper {
|
||||
|
||||
// System property to control whether classes may be loaded from an
|
||||
// arbitrary URL code base.
|
||||
private static final String TRUST_URL_CODEBASE_PROPERTY =
|
||||
"com.sun.jndi.ldap.object.trustURLCodebase";
|
||||
|
||||
// Determine whether classes may be loaded from an arbitrary URL code base.
|
||||
private static final String trustURLCodebase =
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
|
||||
"false");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
VersionHelper12() {} // Disallow external from creating one of these.
|
||||
|
||||
ClassLoader getURLClassLoader(String[] url)
|
||||
throws MalformedURLException {
|
||||
ClassLoader parent = getContextClassLoader();
|
||||
if (url != null) {
|
||||
/*
|
||||
* Classes may only be loaded from an arbitrary URL code base when
|
||||
* the system property com.sun.jndi.ldap.object.trustURLCodebase
|
||||
* has been set to "true".
|
||||
*/
|
||||
if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) {
|
||||
return URLClassLoader.newInstance(getUrlArray(url), parent);
|
||||
} else {
|
||||
return parent;
|
||||
|
@ -37,6 +37,8 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.awt.peer.FontPeer;
|
||||
import java.io.*;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
@ -51,6 +53,7 @@ import sun.font.AttributeMap;
|
||||
import sun.font.AttributeValues;
|
||||
import sun.font.EAttribute;
|
||||
import sun.font.CompositeFont;
|
||||
import sun.font.CreatedFontTracker;
|
||||
import sun.font.Font2D;
|
||||
import sun.font.Font2DHandle;
|
||||
import sun.font.FontManager;
|
||||
@ -575,14 +578,16 @@ public class Font implements java.io.Serializable
|
||||
}
|
||||
|
||||
/* used to implement Font.createFont */
|
||||
private Font(File fontFile, int fontFormat, boolean isCopy)
|
||||
private Font(File fontFile, int fontFormat,
|
||||
boolean isCopy, CreatedFontTracker tracker)
|
||||
throws FontFormatException {
|
||||
this.createdFont = true;
|
||||
/* Font2D instances created by this method track their font file
|
||||
* so that when the Font2D is GC'd it can also remove the file.
|
||||
*/
|
||||
this.font2DHandle =
|
||||
FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
|
||||
FontManager.createFont2D(fontFile, fontFormat,
|
||||
isCopy, tracker).handle;
|
||||
this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
|
||||
this.style = Font.PLAIN;
|
||||
this.size = 1;
|
||||
@ -787,6 +792,29 @@ public class Font implements java.io.Serializable
|
||||
return new Font(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used with the byte count tracker for fonts created from streams.
|
||||
* If a thread can create temp files anyway, no point in counting
|
||||
* font bytes.
|
||||
*/
|
||||
private static boolean hasTempPermission() {
|
||||
|
||||
if (System.getSecurityManager() == null) {
|
||||
return true;
|
||||
}
|
||||
File f = null;
|
||||
boolean hasPerm = false;
|
||||
try {
|
||||
f = File.createTempFile("+~JT", ".tmp", null);
|
||||
f.delete();
|
||||
f = null;
|
||||
hasPerm = true;
|
||||
} catch (Throwable t) {
|
||||
/* inc. any kind of SecurityException */
|
||||
}
|
||||
return hasPerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>Font</code> using the specified font type
|
||||
* and input data. The new <code>Font</code> is
|
||||
@ -822,58 +850,96 @@ public class Font implements java.io.Serializable
|
||||
fontFormat != Font.TYPE1_FONT) {
|
||||
throw new IllegalArgumentException ("font format not recognized");
|
||||
}
|
||||
final InputStream fStream = fontStream;
|
||||
Object ret = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
File tFile = null;
|
||||
FileOutputStream outStream = null;
|
||||
try {
|
||||
tFile = File.createTempFile("+~JF", ".tmp", null);
|
||||
/* Temp file deleted by font shutdown hook */
|
||||
BufferedInputStream inStream =
|
||||
new BufferedInputStream(fStream);
|
||||
outStream = new FileOutputStream(tFile);
|
||||
int bytesRead = 0;
|
||||
int bufSize = 8192;
|
||||
byte [] buf = new byte[bufSize];
|
||||
while (bytesRead != -1) {
|
||||
try {
|
||||
bytesRead = inStream.read(buf, 0, bufSize);
|
||||
} catch (Throwable t) {
|
||||
throw new IOException();
|
||||
}
|
||||
if (bytesRead != -1) {
|
||||
outStream.write(buf, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
/* don't close the input stream */
|
||||
outStream.close();
|
||||
} catch (IOException e) {
|
||||
if (outStream != null) {
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (Exception e1) {
|
||||
}
|
||||
}
|
||||
if (tFile != null) {
|
||||
try {
|
||||
tFile.delete();
|
||||
} catch (Exception e2) {
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
return tFile;
|
||||
}
|
||||
});
|
||||
boolean copiedFontData = false;
|
||||
|
||||
if (ret instanceof File) {
|
||||
return new Font((File)ret, fontFormat, true);
|
||||
} else if (ret instanceof IOException) {
|
||||
throw (IOException)ret;
|
||||
} else {
|
||||
throw new FontFormatException("Couldn't access font stream");
|
||||
try {
|
||||
final File tFile = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<File>() {
|
||||
public File run() throws IOException {
|
||||
return File.createTempFile("+~JF", ".tmp", null);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
int totalSize = 0;
|
||||
CreatedFontTracker tracker = null;
|
||||
try {
|
||||
final OutputStream outStream =
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<OutputStream>() {
|
||||
public OutputStream run() throws IOException {
|
||||
return new FileOutputStream(tFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (!hasTempPermission()) {
|
||||
tracker = CreatedFontTracker.getTracker();
|
||||
}
|
||||
try {
|
||||
byte[] buf = new byte[8192];
|
||||
for (;;) {
|
||||
int bytesRead = fontStream.read(buf);
|
||||
if (bytesRead < 0) {
|
||||
break;
|
||||
}
|
||||
if (tracker != null) {
|
||||
if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
|
||||
throw new IOException("File too big.");
|
||||
}
|
||||
if (totalSize+tracker.getNumBytes() >
|
||||
tracker.MAX_TOTAL_BYTES)
|
||||
{
|
||||
throw new IOException("Total files too big.");
|
||||
}
|
||||
totalSize += bytesRead;
|
||||
tracker.addBytes(bytesRead);
|
||||
}
|
||||
outStream.write(buf, 0, bytesRead);
|
||||
}
|
||||
/* don't close the input stream */
|
||||
} finally {
|
||||
outStream.close();
|
||||
}
|
||||
/* After all references to a Font2D are dropped, the file
|
||||
* will be removed. To support long-lived AppContexts,
|
||||
* we need to then decrement the byte count by the size
|
||||
* of the file.
|
||||
* If the data isn't a valid font, the implementation will
|
||||
* delete the tmp file and decrement the byte count
|
||||
* in the tracker object before returning from the
|
||||
* constructor, so we can set 'copiedFontData' to true here
|
||||
* without waiting for the results of that constructor.
|
||||
*/
|
||||
copiedFontData = true;
|
||||
Font font = new Font(tFile, fontFormat, true, tracker);
|
||||
return font;
|
||||
} finally {
|
||||
if (!copiedFontData) {
|
||||
if (tracker != null) {
|
||||
tracker.subBytes(totalSize);
|
||||
}
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() {
|
||||
tFile.delete();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof FontFormatException) {
|
||||
throw (FontFormatException)t;
|
||||
}
|
||||
if (t instanceof IOException) {
|
||||
throw (IOException)t;
|
||||
}
|
||||
Throwable cause = t.getCause();
|
||||
if (cause instanceof FontFormatException) {
|
||||
throw (FontFormatException)cause;
|
||||
}
|
||||
throw new IOException("Problem reading font data.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,6 +979,9 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
public static Font createFont(int fontFormat, File fontFile)
|
||||
throws java.awt.FontFormatException, java.io.IOException {
|
||||
|
||||
fontFile = new File(fontFile.getPath());
|
||||
|
||||
if (fontFormat != Font.TRUETYPE_FONT &&
|
||||
fontFormat != Font.TYPE1_FONT) {
|
||||
throw new IllegalArgumentException ("font format not recognized");
|
||||
@ -926,7 +995,7 @@ public class Font implements java.io.Serializable
|
||||
if (!fontFile.canRead()) {
|
||||
throw new IOException("Can't read " + fontFile);
|
||||
}
|
||||
return new Font(fontFile, fontFormat, false);
|
||||
return new Font(fontFile, fontFormat, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,14 +41,14 @@ class NoSuchFieldError extends IncompatibleClassChangeError {
|
||||
private static final long serialVersionUID = -3456430195886129035L;
|
||||
|
||||
/**
|
||||
* Constructs a <code>NoSuchFieldException</code> with no detail message.
|
||||
* Constructs a <code>NoSuchFieldError</code> with no detail message.
|
||||
*/
|
||||
public NoSuchFieldError() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>NoSuchFieldException</code> with the specified
|
||||
* Constructs a <code>NoSuchFieldError</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param s the detail message.
|
||||
|
@ -196,10 +196,12 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
||||
|
||||
if ((start < 0) || (end > len) || (start > end))
|
||||
throw new IndexOutOfBoundsException();
|
||||
int sublen = end - start;
|
||||
int off = offset + ((pos + start) << $LG_BYTES_PER_VALUE$);
|
||||
assert (off >= 0);
|
||||
return new ByteBufferAsCharBuffer$RW$$BO$(bb, -1, 0, sublen, sublen, off);
|
||||
return new ByteBufferAsCharBuffer$RW$$BO$(bb,
|
||||
-1,
|
||||
pos + start,
|
||||
pos + end,
|
||||
capacity(),
|
||||
offset);
|
||||
}
|
||||
|
||||
#end[char]
|
||||
|
@ -412,10 +412,12 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
|
||||
if ((start < 0) || (end > len) || (start > end))
|
||||
throw new IndexOutOfBoundsException();
|
||||
int sublen = end - start;
|
||||
int off = (pos + start) << $LG_BYTES_PER_VALUE$;
|
||||
assert (off >= 0);
|
||||
return new DirectCharBuffer$RW$$BO$(this, -1, 0, sublen, sublen, off);
|
||||
return new DirectCharBuffer$RW$$BO$(this,
|
||||
-1,
|
||||
pos + start,
|
||||
pos + end,
|
||||
capacity(),
|
||||
offset);
|
||||
}
|
||||
|
||||
#end[char]
|
||||
|
@ -572,10 +572,13 @@ class Heap$Type$Buffer$RW$
|
||||
|| (end > length())
|
||||
|| (start > end))
|
||||
throw new IndexOutOfBoundsException();
|
||||
int len = end - start;
|
||||
int pos = position();
|
||||
return new HeapCharBuffer$RW$(hb,
|
||||
-1, 0, len, len,
|
||||
offset + position() + start);
|
||||
-1,
|
||||
pos + start,
|
||||
pos + end,
|
||||
capacity(),
|
||||
offset);
|
||||
}
|
||||
|
||||
#end[char]
|
||||
|
@ -102,10 +102,12 @@ class StringCharBuffer // package-private
|
||||
public final CharBuffer subSequence(int start, int end) {
|
||||
try {
|
||||
int pos = position();
|
||||
return new StringCharBuffer(str, -1,
|
||||
return new StringCharBuffer(str,
|
||||
-1,
|
||||
pos + checkIndex(start, pos),
|
||||
pos + checkIndex(end, pos),
|
||||
remaining(), offset);
|
||||
capacity(),
|
||||
offset);
|
||||
} catch (IllegalArgumentException x) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ public abstract class AsynchronousDatagramChannel
|
||||
* at least care must be taken to ensure that the buffer is not accessed
|
||||
* while the channel remains open.
|
||||
*
|
||||
* <p> If there is a security manager installed and the the channel is not
|
||||
* <p> If there is a security manager installed and the channel is not
|
||||
* connected then this method verifies that the target address and port number
|
||||
* are permitted by the security manager's {@link SecurityManager#checkConnect
|
||||
* checkConnect} method. The overhead of this security check can be avoided
|
||||
|
@ -494,7 +494,7 @@ public abstract class Path
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it denies {@link LinkPermission}<tt>("symbolic")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to the path of the symbolic link.
|
||||
@ -531,7 +531,7 @@ public abstract class Path
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it denies {@link LinkPermission}<tt>("hard")</tt>
|
||||
* or its {@link SecurityManager#checkWrite(String) checkWrite}
|
||||
* method denies write access to both this path and the path of the
|
||||
@ -560,7 +560,7 @@ public abstract class Path
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, it checks that {@code FilePermission} has been
|
||||
* granted with the "{@code readlink}" action to read the link.
|
||||
*/
|
||||
@ -615,7 +615,7 @@ public abstract class Path
|
||||
* obtained
|
||||
*
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, the {@link #toAbsolutePath toAbsolutePath} method
|
||||
* throws a security exception.
|
||||
*/
|
||||
@ -636,7 +636,7 @@ public abstract class Path
|
||||
* @throws IOError
|
||||
* if an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, its {@link SecurityManager#checkPropertyAccess(String)
|
||||
* checkPropertyAccess} method is invoked to check access to the
|
||||
* system property {@code user.dir}
|
||||
@ -677,7 +677,7 @@ public abstract class Path
|
||||
* @throws IOException
|
||||
* if the file does not exist or an I/O error occurs
|
||||
* @throws SecurityException
|
||||
* In the case of the the default provider, and a security manager
|
||||
* In the case of the default provider, and a security manager
|
||||
* is installed, its {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file, and where
|
||||
* this path is not absolute, its {@link SecurityManager#checkPropertyAccess(String)
|
||||
|
@ -208,7 +208,7 @@ public abstract class SecureDirectoryStream
|
||||
* @throws ClosedDirectoryStreamException
|
||||
* if the directory stream is closed
|
||||
* @throws NoSuchFileException
|
||||
* if the the directory does not exist <i>(optional specific exception)</i>
|
||||
* if the directory does not exist <i>(optional specific exception)</i>
|
||||
* @throws DirectoryNotEmptyException
|
||||
* if the directory could not otherwise be deleted because it is
|
||||
* not empty <i>(optional specific exception)</i>
|
||||
|
@ -425,7 +425,7 @@ public final class AccessController {
|
||||
* Performs the specified <code>PrivilegedExceptionAction</code> with
|
||||
* privileges enabled and restricted by the specified
|
||||
* <code>AccessControlContext</code>. The action is performed with the
|
||||
* intersection of the the permissions possessed by the caller's
|
||||
* intersection of the permissions possessed by the caller's
|
||||
* protection domain, and those possessed by the domains represented by the
|
||||
* specified <code>AccessControlContext</code>.
|
||||
* <p>
|
||||
|
@ -102,7 +102,7 @@ public abstract class AlgorithmParametersSpi {
|
||||
* parameters should be returned in an instance of the
|
||||
* <code>DSAParameterSpec</code> class.
|
||||
*
|
||||
* @param paramSpec the the specification class in which
|
||||
* @param paramSpec the specification class in which
|
||||
* the parameters should be returned.
|
||||
*
|
||||
* @return the parameter specification.
|
||||
|
@ -87,7 +87,7 @@ public class PrivilegedActionException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the cause of this exception (the exception thrown by
|
||||
* Returns the cause of this exception (the exception thrown by
|
||||
* the privileged computation that resulted in this
|
||||
* <code>PrivilegedActionException</code>).
|
||||
*
|
||||
|
@ -501,7 +501,7 @@ public final class Security {
|
||||
* <li> <i><crypto_service>.<algorithm_or_type>
|
||||
* <attribute_name>:< attribute_value></i>
|
||||
* <p> The cryptographic service name must not contain any dots. There
|
||||
* must be one or more space charaters between the the
|
||||
* must be one or more space charaters between the
|
||||
* <i><algorithm_or_type></i> and the <i><attribute_name></i>.
|
||||
* <p> A provider satisfies this selection criterion iff the
|
||||
* provider implements the specified algorithm or type for the specified
|
||||
|
@ -118,7 +118,7 @@ import java.util.StringTokenizer;
|
||||
* <td>setProperty.{key}</td>
|
||||
* <td>Setting of the security property with the specified key</td>
|
||||
* <td>This could include setting a security provider or defining
|
||||
* the location of the the system-wide security policy. Malicious
|
||||
* the location of the system-wide security policy. Malicious
|
||||
* code that has permission to set a new security provider may
|
||||
* set a rogue provider that steals confidential information such
|
||||
* as cryptographic private keys. In addition, malicious code with
|
||||
|
@ -316,7 +316,7 @@ public abstract class SignatureSpi {
|
||||
* overridden by a provider
|
||||
*
|
||||
* @exception InvalidAlgorithmParameterException if this method is
|
||||
* overridden by a provider and the the given parameters
|
||||
* overridden by a provider and the given parameters
|
||||
* are inappropriate for this signature engine
|
||||
*/
|
||||
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||
|
@ -460,7 +460,7 @@ public class CertificateFactory {
|
||||
* {@link java.io.InputStream#reset() reset}, this method will
|
||||
* consume the entire input stream. Otherwise, each call to this
|
||||
* method consumes one CRL and the read position of the input stream
|
||||
* is positioned to the next available byte after the the inherent
|
||||
* is positioned to the next available byte after the inherent
|
||||
* end-of-CRL marker. If the data in the
|
||||
* input stream does not contain an inherent end-of-CRL marker (other
|
||||
* than EOF) and there is trailing data after the CRL is parsed, a
|
||||
|
@ -88,7 +88,7 @@ public abstract class CertificateFactorySpi {
|
||||
* {@link java.io.InputStream#reset() reset}, this method will
|
||||
* consume the entire input stream. Otherwise, each call to this
|
||||
* method consumes one certificate and the read position of the input stream
|
||||
* is positioned to the next available byte after the the inherent
|
||||
* is positioned to the next available byte after the inherent
|
||||
* end-of-certificate marker. If the data in the
|
||||
* input stream does not contain an inherent end-of-certificate marker (other
|
||||
* than EOF) and there is trailing data after the certificate is parsed, a
|
||||
@ -261,7 +261,7 @@ public abstract class CertificateFactorySpi {
|
||||
* {@link java.io.InputStream#reset() reset}, this method will
|
||||
* consume the entire input stream. Otherwise, each call to this
|
||||
* method consumes one CRL and the read position of the input stream
|
||||
* is positioned to the next available byte after the the inherent
|
||||
* is positioned to the next available byte after the inherent
|
||||
* end-of-CRL marker. If the data in the
|
||||
* input stream does not contain an inherent end-of-CRL marker (other
|
||||
* than EOF) and there is trailing data after the CRL is parsed, a
|
||||
|
@ -41,9 +41,14 @@ package java.util;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serializable;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.text.DateFormat;
|
||||
import java.text.DateFormatSymbols;
|
||||
import sun.util.BuddhistCalendar;
|
||||
@ -2628,6 +2633,18 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
}
|
||||
}
|
||||
|
||||
private static class CalendarAccessControlContext {
|
||||
private static final AccessControlContext INSTANCE;
|
||||
static {
|
||||
RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar");
|
||||
PermissionCollection perms = perm.newPermissionCollection();
|
||||
perms.add(perm);
|
||||
INSTANCE = new AccessControlContext(new ProtectionDomain[] {
|
||||
new ProtectionDomain(null, perms)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes this object from a stream (i.e., deserialize it).
|
||||
*/
|
||||
@ -2657,17 +2674,30 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
serialVersionOnStream = currentSerialVersion;
|
||||
|
||||
// If there's a ZoneInfo object, use it for zone.
|
||||
ZoneInfo zi = null;
|
||||
try {
|
||||
ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
return input.readObject();
|
||||
}
|
||||
});
|
||||
if (zi != null) {
|
||||
zone = zi;
|
||||
zi = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<ZoneInfo>() {
|
||||
public ZoneInfo run() throws Exception {
|
||||
return (ZoneInfo) input.readObject();
|
||||
}
|
||||
},
|
||||
CalendarAccessControlContext.INSTANCE);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
Exception e = pae.getException();
|
||||
if (!(e instanceof OptionalDataException)) {
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
} else if (e instanceof IOException) {
|
||||
throw (IOException) e;
|
||||
} else if (e instanceof ClassNotFoundException) {
|
||||
throw (ClassNotFoundException) e;
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (zi != null) {
|
||||
zone = zi;
|
||||
}
|
||||
|
||||
// If the deserialized object has a SimpleTimeZone, try to
|
||||
@ -2676,9 +2706,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
|
||||
// implementation as much as possible.
|
||||
if (zone instanceof SimpleTimeZone) {
|
||||
String id = zone.getID();
|
||||
TimeZone zi = TimeZone.getTimeZone(id);
|
||||
if (zi != null && zi.hasSameRules(zone) && zi.getID().equals(id)) {
|
||||
zone = zi;
|
||||
TimeZone tz = TimeZone.getTimeZone(id);
|
||||
if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {
|
||||
zone = tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
139
jdk/src/share/classes/java/util/zip/ZipCoder.java
Normal file
139
jdk/src/share/classes/java/util/zip/ZipCoder.java
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package java.util.zip;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Utility class for zipfile name and comment decoding and encoding
|
||||
*/
|
||||
|
||||
final class ZipCoder {
|
||||
|
||||
String toString(byte[] ba, int length) {
|
||||
CharsetDecoder cd = decoder().reset();
|
||||
int len = (int)(length * cd.maxCharsPerByte());
|
||||
char[] ca = new char[len];
|
||||
if (len == 0)
|
||||
return new String(ca);
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
return new String(ca, 0, cb.position());
|
||||
}
|
||||
|
||||
String toString(byte[] ba) {
|
||||
return toString(ba, ba.length);
|
||||
}
|
||||
|
||||
byte[] getBytes(String s) {
|
||||
CharsetEncoder ce = encoder().reset();
|
||||
char[] ca = s.toCharArray();
|
||||
int len = (int)(ca.length * ce.maxBytesPerChar());
|
||||
byte[] ba = new byte[len];
|
||||
if (len == 0)
|
||||
return ba;
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
if (bb.position() == ba.length) // defensive copy?
|
||||
return ba;
|
||||
else
|
||||
return Arrays.copyOf(ba, bb.position());
|
||||
}
|
||||
|
||||
// assume invoked only if "this" is not utf8
|
||||
byte[] getBytesUTF8(String s) {
|
||||
if (isutf8)
|
||||
return getBytes(s);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.getBytes(s);
|
||||
}
|
||||
|
||||
|
||||
String toStringUTF8(byte[] ba, int len) {
|
||||
if (isutf8)
|
||||
return toString(ba, len);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.toString(ba, len);
|
||||
}
|
||||
|
||||
boolean isUTF8() {
|
||||
return isutf8;
|
||||
}
|
||||
|
||||
private Charset cs;
|
||||
private CharsetDecoder dec;
|
||||
private CharsetEncoder enc;
|
||||
private boolean isutf8;
|
||||
private ZipCoder utf8;
|
||||
|
||||
private ZipCoder(Charset cs) {
|
||||
this.cs = cs;
|
||||
this.isutf8 = cs.name().equals("UTF-8");
|
||||
}
|
||||
|
||||
static ZipCoder get(Charset charset) {
|
||||
return new ZipCoder(charset);
|
||||
}
|
||||
|
||||
private CharsetDecoder decoder() {
|
||||
if (dec == null) {
|
||||
dec = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
}
|
||||
return dec;
|
||||
}
|
||||
|
||||
private CharsetEncoder encoder() {
|
||||
if (enc == null) {
|
||||
enc = cs.newEncoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
}
|
@ -73,5 +73,12 @@ class ZipConstants64 {
|
||||
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
|
||||
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
|
||||
|
||||
/*
|
||||
* Language encoding flag EFS
|
||||
*/
|
||||
static final int EFS = 0x800; // If this bit is set the filename and
|
||||
// comment fields for this file must be
|
||||
// encoded using UTF-8.
|
||||
|
||||
private ZipConstants64() {}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
long size = -1; // uncompressed size of entry data
|
||||
long csize = -1; // compressed size of entry data
|
||||
int method = -1; // compression method
|
||||
int flag = 0; // general purpose flag
|
||||
byte[] extra; // optional extra field data for entry
|
||||
String comment; // optional comment string for entry
|
||||
|
||||
@ -53,13 +54,6 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
*/
|
||||
public static final int DEFLATED = 8;
|
||||
|
||||
static {
|
||||
/* Zip library is loaded from System.initializeSystemClass */
|
||||
initIDs();
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
/**
|
||||
* Creates a new zip entry with the specified name.
|
||||
*
|
||||
@ -90,28 +84,15 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
size = e.size;
|
||||
csize = e.csize;
|
||||
method = e.method;
|
||||
flag = e.flag;
|
||||
extra = e.extra;
|
||||
comment = e.comment;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new zip entry for the given name with fields initialized
|
||||
* from the specified jzentry data.
|
||||
* Creates a new un-initialized zip entry
|
||||
*/
|
||||
ZipEntry(String name, long jzentry) {
|
||||
this.name = name;
|
||||
initFields(jzentry);
|
||||
}
|
||||
|
||||
private native void initFields(long jzentry);
|
||||
|
||||
/*
|
||||
* Creates a new zip entry with fields initialized from the specified
|
||||
* jzentry data.
|
||||
*/
|
||||
ZipEntry(long jzentry) {
|
||||
initFields(jzentry);
|
||||
}
|
||||
ZipEntry() {}
|
||||
|
||||
/**
|
||||
* Returns the name of the entry.
|
||||
@ -258,16 +239,16 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the optional comment string for the entry.
|
||||
*
|
||||
* <p>ZIP entry comments have maximum length of 0xffff. If the length of the
|
||||
* specified comment string is greater than 0xFFFF bytes after encoding, only
|
||||
* the first 0xFFFF bytes are output to the ZIP file entry.
|
||||
*
|
||||
* @param comment the comment string
|
||||
* @exception IllegalArgumentException if the length of the specified
|
||||
* comment string is greater than 0xFFFF bytes
|
||||
*
|
||||
* @see #getComment()
|
||||
*/
|
||||
public void setComment(String comment) {
|
||||
if (comment != null && comment.length() > 0xffff/3
|
||||
&& ZipOutputStream.getUTF8Length(comment) > 0xffff) {
|
||||
throw new IllegalArgumentException("invalid entry comment length");
|
||||
}
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,11 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
|
||||
/**
|
||||
* This class is used to read entries from a zip file.
|
||||
@ -76,16 +78,19 @@ class ZipFile implements ZipConstants {
|
||||
/**
|
||||
* Opens a zip file for reading.
|
||||
*
|
||||
* <p>First, if there is a security
|
||||
* manager, its <code>checkRead</code> method
|
||||
* is called with the <code>name</code> argument
|
||||
* as its argument to ensure the read is allowed.
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument
|
||||
* to ensure the read is allowed.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments.
|
||||
*
|
||||
* @param name the name of the zip file
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
* @throws SecurityException if a security manager exists and its
|
||||
* <code>checkRead</code> method doesn't allow read access to the file.
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*/
|
||||
public ZipFile(String name) throws IOException {
|
||||
@ -101,6 +106,9 @@ class ZipFile implements ZipConstants {
|
||||
* method is called with the <code>name</code> argument as its argument to
|
||||
* ensure the read is allowed.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @param mode the mode in which the file is to be opened
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
@ -115,6 +123,59 @@ class ZipFile implements ZipConstants {
|
||||
* @since 1.3
|
||||
*/
|
||||
public ZipFile(File file, int mode) throws IOException {
|
||||
this(file, mode, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a ZIP file for reading given the specified File object.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments.
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*/
|
||||
public ZipFile(File file) throws ZipException, IOException {
|
||||
this(file, OPEN_READ);
|
||||
}
|
||||
|
||||
private ZipCoder zc;
|
||||
|
||||
/**
|
||||
* Opens a new <code>ZipFile</code> to read from the specified
|
||||
* <code>File</code> object in the specified mode. The mode argument
|
||||
* must be either <tt>OPEN_READ</tt> or <tt>OPEN_READ | OPEN_DELETE</tt>.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument to
|
||||
* ensure the read is allowed.
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @param mode the mode in which the file is to be opened
|
||||
* @param charset
|
||||
* the {@link java.nio.charset.Charset {@code charset}} to
|
||||
* be used to decode the ZIP entry name and comment that are not
|
||||
* encoded by using UTF-8 encoding (indicated by entry's general
|
||||
* purpose flag).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkRead</code>
|
||||
* method doesn't allow read access to the file,or its
|
||||
* <code>checkDelete</code> method doesn't allow deleting the
|
||||
* file when the <tt>OPEN_DELETE</tt> flag is set
|
||||
*
|
||||
* @throws IllegalArgumentException if the <tt>mode</tt> argument is invalid
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(File file, int mode, Charset charset) throws IOException
|
||||
{
|
||||
if (((mode & OPEN_READ) == 0) ||
|
||||
((mode & ~(OPEN_READ | OPEN_DELETE)) != 0)) {
|
||||
throw new IllegalArgumentException("Illegal mode: 0x"+
|
||||
@ -128,24 +189,61 @@ class ZipFile implements ZipConstants {
|
||||
sm.checkDelete(name);
|
||||
}
|
||||
}
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
jzfile = open(name, mode, file.lastModified());
|
||||
|
||||
this.name = name;
|
||||
this.total = getTotal(jzfile);
|
||||
}
|
||||
|
||||
private static native long open(String name, int mode, long lastModified);
|
||||
private static native int getTotal(long jzfile);
|
||||
|
||||
/**
|
||||
* Opens a zip file for reading.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument
|
||||
* to ensure the read is allowed.
|
||||
*
|
||||
* @param name the name of the zip file
|
||||
* @param charset
|
||||
* the {@link java.nio.charset.Charset {@code charset}} to
|
||||
* be used to decode the ZIP entry name and comment that are not
|
||||
* encoded by using UTF-8 encoding (indicated by entry's general
|
||||
* purpose flag).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkRead</code>
|
||||
* method doesn't allow read access to the file
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(String name, Charset charset) throws IOException
|
||||
{
|
||||
this(new File(name), OPEN_READ, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a ZIP file for reading given the specified File object.
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @throws ZipException if a ZIP error has occurred
|
||||
* @param charset
|
||||
* The {@link java.nio.charset.Charset {@code charset}} to be
|
||||
* used to decode the ZIP entry name and comment (ignored if
|
||||
* the <a href="package-summary.html#lang_encoding"> language
|
||||
* encoding bit</a> of the ZIP entry's general purpose bit
|
||||
* flag is set).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(File file) throws ZipException, IOException {
|
||||
this(file, OPEN_READ);
|
||||
public ZipFile(File file, Charset charset) throws IOException
|
||||
{
|
||||
this(file, OPEN_READ, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,9 +261,9 @@ class ZipFile implements ZipConstants {
|
||||
long jzentry = 0;
|
||||
synchronized (this) {
|
||||
ensureOpen();
|
||||
jzentry = getEntry(jzfile, name, true);
|
||||
jzentry = getEntry(jzfile, zc.getBytes(name), true);
|
||||
if (jzentry != 0) {
|
||||
ZipEntry ze = new ZipEntry(name, jzentry);
|
||||
ZipEntry ze = getZipEntry(name, jzentry);
|
||||
freeEntry(jzfile, jzentry);
|
||||
return ze;
|
||||
}
|
||||
@ -173,7 +271,7 @@ class ZipFile implements ZipConstants {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static native long getEntry(long jzfile, String name,
|
||||
private static native long getEntry(long jzfile, byte[] name,
|
||||
boolean addSlash);
|
||||
|
||||
// freeEntry releases the C jzentry struct.
|
||||
@ -194,36 +292,30 @@ class ZipFile implements ZipConstants {
|
||||
* @throws IllegalStateException if the zip file has been closed
|
||||
*/
|
||||
public InputStream getInputStream(ZipEntry entry) throws IOException {
|
||||
return getInputStream(entry.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input stream for reading the contents of the specified
|
||||
* entry, or null if the entry was not found.
|
||||
*/
|
||||
private InputStream getInputStream(String name) throws IOException {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
if (entry == null) {
|
||||
throw new NullPointerException("entry");
|
||||
}
|
||||
long jzentry = 0;
|
||||
ZipFileInputStream in = null;
|
||||
synchronized (this) {
|
||||
ensureOpen();
|
||||
jzentry = getEntry(jzfile, name, false);
|
||||
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
|
||||
jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
|
||||
} else {
|
||||
jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
|
||||
}
|
||||
if (jzentry == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
in = new ZipFileInputStream(jzentry);
|
||||
|
||||
}
|
||||
final ZipFileInputStream zfin = in;
|
||||
switch (getMethod(jzentry)) {
|
||||
switch (getEntryMethod(jzentry)) {
|
||||
case STORED:
|
||||
return zfin;
|
||||
case DEFLATED:
|
||||
// MORE: Compute good size for inflater stream:
|
||||
long size = getSize(jzentry) + 2; // Inflater likes a bit of slack
|
||||
long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
|
||||
if (size > 65536) size = 8192;
|
||||
if (size <= 0) size = 4096;
|
||||
return new InflaterInputStream(zfin, getInflater(), (int)size) {
|
||||
@ -267,8 +359,6 @@ class ZipFile implements ZipConstants {
|
||||
}
|
||||
}
|
||||
|
||||
private static native int getMethod(long jzentry);
|
||||
|
||||
/*
|
||||
* Gets an inflater from the list of available inflaters or allocates
|
||||
* a new one.
|
||||
@ -343,7 +433,7 @@ class ZipFile implements ZipConstants {
|
||||
",\n message = " + message
|
||||
);
|
||||
}
|
||||
ZipEntry ze = new ZipEntry(jzentry);
|
||||
ZipEntry ze = getZipEntry(null, jzentry);
|
||||
freeEntry(jzfile, jzentry);
|
||||
return ze;
|
||||
}
|
||||
@ -351,6 +441,38 @@ class ZipFile implements ZipConstants {
|
||||
};
|
||||
}
|
||||
|
||||
private ZipEntry getZipEntry(String name, long jzentry) {
|
||||
ZipEntry e = new ZipEntry();
|
||||
e.flag = getEntryFlag(jzentry); // get the flag first
|
||||
if (name != null) {
|
||||
e.name = name;
|
||||
} else {
|
||||
byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
|
||||
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
|
||||
e.name = zc.toStringUTF8(bname, bname.length);
|
||||
} else {
|
||||
e.name = zc.toString(bname, bname.length);
|
||||
}
|
||||
}
|
||||
e.time = getEntryTime(jzentry);
|
||||
e.crc = getEntryCrc(jzentry);
|
||||
e.size = getEntrySize(jzentry);
|
||||
e. csize = getEntryCSize(jzentry);
|
||||
e.method = getEntryMethod(jzentry);
|
||||
e.extra = getEntryBytes(jzentry, JZENTRY_EXTRA);
|
||||
byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
|
||||
if (bcomm == null) {
|
||||
e.comment = null;
|
||||
} else {
|
||||
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
|
||||
e.comment = zc.toStringUTF8(bcomm, bcomm.length);
|
||||
} else {
|
||||
e.comment = zc.toString(bcomm, bcomm.length);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static native long getNextEntry(long jzfile, int i);
|
||||
|
||||
/**
|
||||
@ -443,8 +565,8 @@ class ZipFile implements ZipConstants {
|
||||
|
||||
ZipFileInputStream(long jzentry) {
|
||||
pos = 0;
|
||||
rem = getCSize(jzentry);
|
||||
size = getSize(jzentry);
|
||||
rem = getEntryCSize(jzentry);
|
||||
size = getEntrySize(jzentry);
|
||||
this.jzentry = jzentry;
|
||||
}
|
||||
|
||||
@ -514,13 +636,25 @@ class ZipFile implements ZipConstants {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static native long open(String name, int mode, long lastModified)
|
||||
throws IOException;
|
||||
private static native int getTotal(long jzfile);
|
||||
private static native int read(long jzfile, long jzentry,
|
||||
long pos, byte[] b, int off, int len);
|
||||
|
||||
private static native long getCSize(long jzentry);
|
||||
// access to the native zentry object
|
||||
private static native long getEntryTime(long jzentry);
|
||||
private static native long getEntryCrc(long jzentry);
|
||||
private static native long getEntryCSize(long jzentry);
|
||||
private static native long getEntrySize(long jzentry);
|
||||
private static native int getEntryMethod(long jzentry);
|
||||
private static native int getEntryFlag(long jzentry);
|
||||
|
||||
private static native long getSize(long jzentry);
|
||||
private static final int JZENTRY_NAME = 0;
|
||||
private static final int JZENTRY_EXTRA = 1;
|
||||
private static final int JZENTRY_COMMENT = 2;
|
||||
private static native byte[] getEntryBytes(long jzentry, int type);
|
||||
|
||||
// Temporary add on for bug troubleshooting
|
||||
private static native String getZipMessage(long jzfile);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
|
||||
/**
|
||||
@ -54,6 +55,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
// one entry
|
||||
private boolean entryEOF = false;
|
||||
|
||||
private ZipCoder zc;
|
||||
|
||||
/**
|
||||
* Check to make sure that this stream has not been closed
|
||||
*/
|
||||
@ -65,14 +68,39 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
|
||||
/**
|
||||
* Creates a new ZIP input stream.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names.
|
||||
*
|
||||
* @param in the actual input stream
|
||||
*/
|
||||
public ZipInputStream(InputStream in) {
|
||||
this(in, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ZIP input stream.
|
||||
*
|
||||
* @param in the actual input stream
|
||||
*
|
||||
* @param charset
|
||||
* The {@link java.nio.charset.Charset {@code charset}} to be
|
||||
* used to decode the ZIP entry name (ignored if the
|
||||
* <a href="package-summary.html#lang_encoding"> language
|
||||
* encoding bit</a> of the ZIP entry's general purpose bit
|
||||
* flag is set).
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipInputStream(InputStream in, Charset charset) {
|
||||
super(new PushbackInputStream(in, 512), new Inflater(true), 512);
|
||||
usesDefaultInflater = true;
|
||||
if(in == null) {
|
||||
throw new NullPointerException("in is null");
|
||||
}
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,8 +169,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
* @param len the maximum number of bytes read
|
||||
* @return the actual number of bytes read, or -1 if the end of the
|
||||
* entry is reached
|
||||
* @exception NullPointerException If <code>b</code> is <code>null</code>.
|
||||
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
|
||||
* @exception NullPointerException if <code>b</code> is <code>null</code>.
|
||||
* @exception IndexOutOfBoundsException if <code>off</code> is negative,
|
||||
* <code>len</code> is negative, or <code>len</code> is greater than
|
||||
* <code>b.length - off</code>
|
||||
* @exception ZipException if a ZIP file error has occurred
|
||||
@ -252,6 +280,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
if (get32(tmpbuf, 0) != LOCSIG) {
|
||||
return null;
|
||||
}
|
||||
// get flag first, we need check EFS.
|
||||
flag = get16(tmpbuf, LOCFLG);
|
||||
// get the entry name and create the ZipEntry first
|
||||
int len = get16(tmpbuf, LOCNAM);
|
||||
int blen = b.length;
|
||||
@ -262,9 +292,11 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
b = new byte[blen];
|
||||
}
|
||||
readFully(b, 0, len);
|
||||
ZipEntry e = createZipEntry(getUTF8String(b, 0, len));
|
||||
// Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
|
||||
ZipEntry e = createZipEntry(((flag & EFS) != 0)
|
||||
? zc.toStringUTF8(b, len)
|
||||
: zc.toString(b, len));
|
||||
// now get the remaining fields for the entry
|
||||
flag = get16(tmpbuf, LOCFLG);
|
||||
if ((flag & 1) == 1) {
|
||||
throw new ZipException("encrypted ZIP entry not supported");
|
||||
}
|
||||
@ -313,71 +345,6 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetches a UTF8-encoded String from the specified byte array.
|
||||
*/
|
||||
private static String getUTF8String(byte[] b, int off, int len) {
|
||||
// First, count the number of characters in the sequence
|
||||
int count = 0;
|
||||
int max = off + len;
|
||||
int i = off;
|
||||
while (i < max) {
|
||||
int c = b[i++] & 0xff;
|
||||
switch (c >> 4) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
count++;
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110xxxxx 10xxxxxx
|
||||
if ((b[i++] & 0xc0) != 0x80) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
case 14:
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
if (((b[i++] & 0xc0) != 0x80) ||
|
||||
((b[i++] & 0xc0) != 0x80)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
// 10xxxxxx, 1111xxxx
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
if (i != max) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// Now decode the characters...
|
||||
char[] cs = new char[count];
|
||||
i = 0;
|
||||
while (off < max) {
|
||||
int c = b[off++] & 0xff;
|
||||
switch (c >> 4) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
cs[i++] = (char)c;
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110xxxxx 10xxxxxx
|
||||
cs[i++] = (char)(((c & 0x1f) << 6) | (b[off++] & 0x3f));
|
||||
break;
|
||||
case 14:
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
int t = (b[off++] & 0x3f) << 6;
|
||||
cs[i++] = (char)(((c & 0x0f) << 12) | t | (b[off++] & 0x3f));
|
||||
break;
|
||||
default:
|
||||
// 10xxxxxx, 1111xxxx
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
return new String(cs, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ZipEntry</code> object for the specified
|
||||
* entry name.
|
||||
|
@ -27,6 +27,7 @@ package java.util.zip;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Vector;
|
||||
import java.util.HashSet;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
@ -44,19 +45,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
private static class XEntry {
|
||||
public final ZipEntry entry;
|
||||
public final long offset;
|
||||
public final int flag;
|
||||
public XEntry(ZipEntry entry, long offset) {
|
||||
this.entry = entry;
|
||||
this.offset = offset;
|
||||
this.flag = (entry.method == DEFLATED &&
|
||||
(entry.size == -1 ||
|
||||
entry.csize == -1 ||
|
||||
entry.crc == -1))
|
||||
// store size, compressed size, and crc-32 in data descriptor
|
||||
// immediately following the compressed entry data
|
||||
? 8
|
||||
// store size, compressed size, and crc-32 in LOC header
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,12 +57,14 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
private CRC32 crc = new CRC32();
|
||||
private long written = 0;
|
||||
private long locoff = 0;
|
||||
private String comment;
|
||||
private byte[] comment;
|
||||
private int method = DEFLATED;
|
||||
private boolean finished;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private final ZipCoder zc;
|
||||
|
||||
private static int version(ZipEntry e) throws ZipException {
|
||||
switch (e.method) {
|
||||
case DEFLATED: return 20;
|
||||
@ -100,10 +93,31 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
|
||||
/**
|
||||
* Creates a new ZIP output stream.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used
|
||||
* to encode the entry names and comments.
|
||||
*
|
||||
* @param out the actual output stream
|
||||
*/
|
||||
public ZipOutputStream(OutputStream out) {
|
||||
this(out, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ZIP output stream.
|
||||
*
|
||||
* @param out the actual output stream
|
||||
*
|
||||
* @param charset the {@link java.nio.charset.Charset </code>charset<code>}
|
||||
* to be used to encode the entry names and comments
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipOutputStream(OutputStream out, Charset charset) {
|
||||
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
usesDefaultDeflater = true;
|
||||
}
|
||||
|
||||
@ -114,11 +128,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
* ZIP file comment is greater than 0xFFFF bytes
|
||||
*/
|
||||
public void setComment(String comment) {
|
||||
if (comment != null && comment.length() > 0xffff/3
|
||||
&& getUTF8Length(comment) > 0xffff) {
|
||||
throw new IllegalArgumentException("ZIP file comment too long.");
|
||||
if (comment != null) {
|
||||
this.comment = zc.getBytes(comment);
|
||||
if (this.comment.length > 0xffff)
|
||||
throw new IllegalArgumentException("ZIP file comment too long.");
|
||||
}
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,8 +181,15 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (e.method == -1) {
|
||||
e.method = method; // use default method
|
||||
}
|
||||
// store size, compressed size, and crc-32 in LOC header
|
||||
e.flag = 0;
|
||||
switch (e.method) {
|
||||
case DEFLATED:
|
||||
// store size, compressed size, and crc-32 in data descriptor
|
||||
// immediately following the compressed entry data
|
||||
if (e.size == -1 || e.csize == -1 || e.crc == -1)
|
||||
e.flag = 8;
|
||||
|
||||
break;
|
||||
case STORED:
|
||||
// compressed size, uncompressed size, and crc-32 must all be
|
||||
@ -192,6 +213,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (! names.add(e.name)) {
|
||||
throw new ZipException("duplicate entry: " + e.name);
|
||||
}
|
||||
if (zc.isUTF8())
|
||||
e.flag |= EFS;
|
||||
current = new XEntry(e, written);
|
||||
xentries.add(current);
|
||||
writeLOC(current);
|
||||
@ -213,7 +236,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
while (!def.finished()) {
|
||||
deflate();
|
||||
}
|
||||
if ((current.flag & 8) == 0) {
|
||||
if ((e.flag & 8) == 0) {
|
||||
// verify size, compressed size, and crc-32 settings
|
||||
if (e.size != def.getBytesRead()) {
|
||||
throw new ZipException(
|
||||
@ -343,11 +366,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
*/
|
||||
private void writeLOC(XEntry xentry) throws IOException {
|
||||
ZipEntry e = xentry.entry;
|
||||
int flag = xentry.flag;
|
||||
int flag = e.flag;
|
||||
int elen = (e.extra != null) ? e.extra.length : 0;
|
||||
boolean hasZip64 = false;
|
||||
|
||||
writeInt(LOCSIG); // LOC header signature
|
||||
writeInt(LOCSIG); // LOC header signature
|
||||
|
||||
if ((flag & 8) == 8) {
|
||||
writeShort(version(e)); // version needed to extract
|
||||
@ -380,7 +403,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(e.size); // uncompressed size
|
||||
}
|
||||
}
|
||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
writeShort(elen);
|
||||
writeBytes(nameBytes, 0, nameBytes.length);
|
||||
@ -417,7 +440,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
*/
|
||||
private void writeCEN(XEntry xentry) throws IOException {
|
||||
ZipEntry e = xentry.entry;
|
||||
int flag = xentry.flag;
|
||||
int flag = e.flag;
|
||||
int version = version(e);
|
||||
|
||||
long csize = e.csize;
|
||||
@ -454,7 +477,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(e.crc); // crc-32
|
||||
writeInt(csize); // compressed size
|
||||
writeInt(size); // uncompressed size
|
||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
if (hasZip64) {
|
||||
// + headid(2) + datasize(2)
|
||||
@ -464,8 +487,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
byte[] commentBytes;
|
||||
if (e.comment != null) {
|
||||
commentBytes = getUTF8Bytes(e.comment);
|
||||
writeShort(commentBytes.length);
|
||||
commentBytes = zc.getBytes(e.comment);
|
||||
writeShort(Math.min(commentBytes.length, 0xffff));
|
||||
} else {
|
||||
commentBytes = null;
|
||||
writeShort(0);
|
||||
@ -489,7 +512,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeBytes(e.extra, 0, e.extra.length);
|
||||
}
|
||||
if (commentBytes != null) {
|
||||
writeBytes(commentBytes, 0, commentBytes.length);
|
||||
writeBytes(commentBytes, 0, Math.min(commentBytes.length, 0xffff));
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,9 +564,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(xlen); // length of central directory
|
||||
writeInt(xoff); // offset of central directory
|
||||
if (comment != null) { // zip file comment
|
||||
byte[] b = getUTF8Bytes(comment);
|
||||
writeShort(b.length);
|
||||
writeBytes(b, 0, b.length);
|
||||
writeShort(comment.length);
|
||||
writeBytes(comment, 0, comment.length);
|
||||
} else {
|
||||
writeShort(0);
|
||||
}
|
||||
@ -594,60 +616,4 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
super.out.write(b, off, len);
|
||||
written += len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of String's UTF8 encoding.
|
||||
*/
|
||||
static int getUTF8Length(String s) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
if (ch <= 0x7f) {
|
||||
count++;
|
||||
} else if (ch <= 0x7ff) {
|
||||
count += 2;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an array of bytes representing the UTF8 encoding
|
||||
* of the specified String.
|
||||
*/
|
||||
private static byte[] getUTF8Bytes(String s) {
|
||||
char[] c = s.toCharArray();
|
||||
int len = c.length;
|
||||
// Count the number of encoded bytes...
|
||||
int count = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ch = c[i];
|
||||
if (ch <= 0x7f) {
|
||||
count++;
|
||||
} else if (ch <= 0x7ff) {
|
||||
count += 2;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
// Now return the encoded bytes...
|
||||
byte[] b = new byte[count];
|
||||
int off = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ch = c[i];
|
||||
if (ch <= 0x7f) {
|
||||
b[off++] = (byte)ch;
|
||||
} else if (ch <= 0x7ff) {
|
||||
b[off++] = (byte)((ch >> 6) | 0xc0);
|
||||
b[off++] = (byte)((ch & 0x3f) | 0x80);
|
||||
} else {
|
||||
b[off++] = (byte)((ch >> 12) | 0xe0);
|
||||
b[off++] = (byte)(((ch >> 6) & 0x3f) | 0x80);
|
||||
b[off++] = (byte)((ch & 0x3f) | 0x80);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,11 @@ input streams.
|
||||
<a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
|
||||
PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
|
||||
are used to overcome the size limitations of the original ZIP format.
|
||||
<p>
|
||||
<a name="lang_encoding">
|
||||
<li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
|
||||
PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
|
||||
encode ZIP entry filename and comment fields using UTF-8.
|
||||
<p>
|
||||
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
|
||||
ZLIB Compressed Data Format Specification version 3.3</a>
|
||||
|
@ -599,7 +599,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
|
||||
*/
|
||||
@Override
|
||||
public MBeanNotificationInfo[] getNotificationInfo() {
|
||||
return notifsInfo;
|
||||
return notifsInfo.clone();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
|
||||
*/
|
||||
@Override
|
||||
public MBeanNotificationInfo[] getNotificationInfo() {
|
||||
return notifsInfo;
|
||||
return notifsInfo.clone();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,7 +32,10 @@ import java.io.IOException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
@ -163,7 +166,10 @@ public abstract class Monitor
|
||||
/**
|
||||
* AccessControlContext of the Monitor.start() caller.
|
||||
*/
|
||||
private AccessControlContext acc;
|
||||
private static final AccessControlContext noPermissionsACC =
|
||||
new AccessControlContext(
|
||||
new ProtectionDomain[] {new ProtectionDomain(null, null)});
|
||||
private volatile AccessControlContext acc = noPermissionsACC;
|
||||
|
||||
/**
|
||||
* Scheduler Service.
|
||||
@ -172,15 +178,21 @@ public abstract class Monitor
|
||||
Executors.newSingleThreadScheduledExecutor(
|
||||
new DaemonThreadFactory("Scheduler"));
|
||||
|
||||
/**
|
||||
* Map containing the thread pool executor per thread group.
|
||||
*/
|
||||
private static final Map<ThreadPoolExecutor, Void> executors =
|
||||
new WeakHashMap<ThreadPoolExecutor, Void>();
|
||||
|
||||
/**
|
||||
* Lock for executors map.
|
||||
*/
|
||||
private static final Object executorsLock = new Object();
|
||||
|
||||
/**
|
||||
* Maximum Pool Size
|
||||
*/
|
||||
private static final int maximumPoolSize;
|
||||
|
||||
/**
|
||||
* Executor Service.
|
||||
*/
|
||||
private static final ThreadPoolExecutor executor;
|
||||
static {
|
||||
final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
|
||||
final String maximumPoolSizeStr = AccessController.doPrivileged(
|
||||
@ -210,21 +222,8 @@ public abstract class Monitor
|
||||
maximumPoolSize = maximumPoolSizeTmp;
|
||||
}
|
||||
}
|
||||
executor = new ThreadPoolExecutor(
|
||||
maximumPoolSize,
|
||||
maximumPoolSize,
|
||||
60L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(),
|
||||
new DaemonThreadFactory("Executor"));
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitor task to be executed by the Executor Service.
|
||||
*/
|
||||
private final MonitorTask monitorTask = new MonitorTask();
|
||||
|
||||
/**
|
||||
* Future associated to the current monitor task.
|
||||
*/
|
||||
@ -233,7 +232,7 @@ public abstract class Monitor
|
||||
/**
|
||||
* Scheduler task to be executed by the Scheduler Service.
|
||||
*/
|
||||
private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);
|
||||
private final SchedulerTask schedulerTask = new SchedulerTask();
|
||||
|
||||
/**
|
||||
* ScheduledFuture associated to the current scheduler task.
|
||||
@ -719,6 +718,7 @@ public abstract class Monitor
|
||||
// Start the scheduler.
|
||||
//
|
||||
cleanupFutures();
|
||||
schedulerTask.setMonitorTask(new MonitorTask());
|
||||
schedulerFuture = scheduler.schedule(schedulerTask,
|
||||
getGranularityPeriod(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
@ -748,7 +748,7 @@ public abstract class Monitor
|
||||
|
||||
// Reset the AccessControlContext.
|
||||
//
|
||||
acc = null;
|
||||
acc = noPermissionsACC;
|
||||
|
||||
// Reset the complex type attribute information
|
||||
// such that it is recalculated again.
|
||||
@ -1467,7 +1467,7 @@ public abstract class Monitor
|
||||
*/
|
||||
private class SchedulerTask implements Runnable {
|
||||
|
||||
private Runnable task = null;
|
||||
private MonitorTask task;
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
@ -1475,7 +1475,16 @@ public abstract class Monitor
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
public SchedulerTask(Runnable task) {
|
||||
public SchedulerTask() {
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* GETTERS/SETTERS
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
public void setMonitorTask(MonitorTask task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
@ -1487,7 +1496,7 @@ public abstract class Monitor
|
||||
|
||||
public void run() {
|
||||
synchronized (Monitor.this) {
|
||||
Monitor.this.monitorFuture = executor.submit(task);
|
||||
Monitor.this.monitorFuture = task.submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1500,6 +1509,8 @@ public abstract class Monitor
|
||||
*/
|
||||
private class MonitorTask implements Runnable {
|
||||
|
||||
private ThreadPoolExecutor executor;
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* CONSTRUCTORS
|
||||
@ -1507,6 +1518,38 @@ public abstract class Monitor
|
||||
*/
|
||||
|
||||
public MonitorTask() {
|
||||
// Find out if there's already an existing executor for the calling
|
||||
// thread and reuse it. Otherwise, create a new one and store it in
|
||||
// the executors map. If there is a SecurityManager, the group of
|
||||
// System.getSecurityManager() is used, else the group of the thread
|
||||
// instantiating this MonitorTask, i.e. the group of the thread that
|
||||
// calls "Monitor.start()".
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
ThreadGroup group = (s != null) ? s.getThreadGroup() :
|
||||
Thread.currentThread().getThreadGroup();
|
||||
synchronized (executorsLock) {
|
||||
for (ThreadPoolExecutor e : executors.keySet()) {
|
||||
DaemonThreadFactory tf =
|
||||
(DaemonThreadFactory) e.getThreadFactory();
|
||||
ThreadGroup tg = tf.getThreadGroup();
|
||||
if (tg == group) {
|
||||
executor = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (executor == null) {
|
||||
executor = new ThreadPoolExecutor(
|
||||
maximumPoolSize,
|
||||
maximumPoolSize,
|
||||
60L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(),
|
||||
new DaemonThreadFactory("ThreadGroup<" +
|
||||
group.getName() + "> Executor", group));
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
executors.put(executor, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1515,12 +1558,18 @@ public abstract class Monitor
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
public Future<?> submit() {
|
||||
return executor.submit(this);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final ScheduledFuture<?> sf;
|
||||
final AccessControlContext ac;
|
||||
synchronized (Monitor.this) {
|
||||
sf = Monitor.this.schedulerFuture;
|
||||
ac = Monitor.this.acc;
|
||||
}
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
if (Monitor.this.isActive()) {
|
||||
final int an[] = alreadyNotifieds;
|
||||
@ -1533,7 +1582,11 @@ public abstract class Monitor
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, Monitor.this.acc);
|
||||
};
|
||||
if (ac == null) {
|
||||
throw new SecurityException("AccessControlContext cannot be null");
|
||||
}
|
||||
AccessController.doPrivileged(action, ac);
|
||||
synchronized (Monitor.this) {
|
||||
if (Monitor.this.isActive() &&
|
||||
Monitor.this.schedulerFuture == sf) {
|
||||
@ -1573,6 +1626,15 @@ public abstract class Monitor
|
||||
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
|
||||
}
|
||||
|
||||
public DaemonThreadFactory(String poolName, ThreadGroup threadGroup) {
|
||||
group = threadGroup;
|
||||
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
|
||||
}
|
||||
|
||||
public ThreadGroup getThreadGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(group,
|
||||
r,
|
||||
|
@ -184,6 +184,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
|
||||
* @return The derived gauge of the specified object.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public synchronized String getDerivedGauge(ObjectName object) {
|
||||
return (String) super.getDerivedGauge(object);
|
||||
}
|
||||
@ -199,6 +200,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
|
||||
* @return The derived gauge timestamp of the specified object.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
|
||||
return super.getDerivedGaugeTimeStamp(object);
|
||||
}
|
||||
@ -341,8 +343,9 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
|
||||
* the Java class of the notification and the notification types sent by
|
||||
* the string monitor.
|
||||
*/
|
||||
@Override
|
||||
public MBeanNotificationInfo[] getNotificationInfo() {
|
||||
return notifsInfo;
|
||||
return notifsInfo.clone();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -123,8 +123,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
|
||||
if (x > y) {
|
||||
throw new IllegalArgumentException("X dimension > Y dimension");
|
||||
}
|
||||
mediaName = media;
|
||||
mediaMap.put(mediaName, this);
|
||||
if (media != null && mediaMap.get(media) == null) {
|
||||
mediaName = media;
|
||||
mediaMap.put(mediaName, this);
|
||||
}
|
||||
sizeVector.add(this);
|
||||
}
|
||||
|
||||
@ -147,8 +149,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
|
||||
if (x > y) {
|
||||
throw new IllegalArgumentException("X dimension > Y dimension");
|
||||
}
|
||||
mediaName = media;
|
||||
mediaMap.put(mediaName, this);
|
||||
if (media != null && mediaMap.get(media) == null) {
|
||||
mediaName = media;
|
||||
mediaMap.put(mediaName, this);
|
||||
}
|
||||
sizeVector.add(this);
|
||||
}
|
||||
|
||||
|
@ -585,9 +585,16 @@ public class GifImageDecoder extends ImageDecoder {
|
||||
System.out.print("Reading a " + width + " by " + height + " " +
|
||||
(interlace ? "" : "non-") + "interlaced image...");
|
||||
}
|
||||
|
||||
int initCodeSize = ExtractByte(block, 9);
|
||||
if (initCodeSize >= 12) {
|
||||
if (verbose) {
|
||||
System.out.println("Invalid initial code size: " +
|
||||
initCodeSize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean ret = parseImage(x, y, width, height,
|
||||
interlace, ExtractByte(block, 9),
|
||||
interlace, initCodeSize,
|
||||
block, rasline, model);
|
||||
|
||||
if (!ret) {
|
||||
|
54
jdk/src/share/classes/sun/font/CreatedFontTracker.java
Normal file
54
jdk/src/share/classes/sun/font/CreatedFontTracker.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.font;
|
||||
|
||||
public class CreatedFontTracker {
|
||||
|
||||
public static final int MAX_FILE_SIZE = 32 * 1024 * 1024;
|
||||
public static final int MAX_TOTAL_BYTES = 10 * MAX_FILE_SIZE;
|
||||
|
||||
static int numBytes;
|
||||
static CreatedFontTracker tracker;
|
||||
|
||||
public static synchronized CreatedFontTracker getTracker() {
|
||||
if (tracker == null) {
|
||||
tracker = new CreatedFontTracker();
|
||||
}
|
||||
return tracker;
|
||||
}
|
||||
|
||||
public synchronized int getNumBytes() {
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
public synchronized void addBytes(int sz) {
|
||||
numBytes += sz;
|
||||
}
|
||||
|
||||
public synchronized void subBytes(int sz) {
|
||||
numBytes -= sz;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -125,9 +125,9 @@ public abstract class FileFont extends PhysicalFont {
|
||||
return true;
|
||||
}
|
||||
|
||||
void setFileToRemove(File file) {
|
||||
void setFileToRemove(File file, CreatedFontTracker tracker) {
|
||||
Disposer.addObjectRecord(this,
|
||||
new CreatedFontFileDisposerRecord(file));
|
||||
new CreatedFontFileDisposerRecord(file, tracker));
|
||||
}
|
||||
|
||||
/* This is called when a font scaler is determined to
|
||||
@ -246,12 +246,16 @@ public abstract class FileFont extends PhysicalFont {
|
||||
return getScaler().getUnitsPerEm();
|
||||
}
|
||||
|
||||
private static class CreatedFontFileDisposerRecord implements DisposerRecord {
|
||||
private static class CreatedFontFileDisposerRecord
|
||||
implements DisposerRecord {
|
||||
|
||||
File fontFile = null;
|
||||
CreatedFontTracker tracker;
|
||||
|
||||
private CreatedFontFileDisposerRecord(File file) {
|
||||
private CreatedFontFileDisposerRecord(File file,
|
||||
CreatedFontTracker tracker) {
|
||||
fontFile = file;
|
||||
this.tracker = tracker;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
@ -260,6 +264,9 @@ public abstract class FileFont extends PhysicalFont {
|
||||
public Object run() {
|
||||
if (fontFile != null) {
|
||||
try {
|
||||
if (tracker != null) {
|
||||
tracker.subBytes((int)fontFile.length());
|
||||
}
|
||||
/* REMIND: is it possible that the file is
|
||||
* still open? It will be closed when the
|
||||
* font2D is disposed but could this code
|
||||
|
@ -2357,19 +2357,21 @@ public final class FontManager {
|
||||
static Vector<File> tmpFontFiles = null;
|
||||
|
||||
public static Font2D createFont2D(File fontFile, int fontFormat,
|
||||
boolean isCopy)
|
||||
boolean isCopy,
|
||||
CreatedFontTracker tracker)
|
||||
throws FontFormatException {
|
||||
|
||||
String fontFilePath = fontFile.getPath();
|
||||
FileFont font2D = null;
|
||||
final File fFile = fontFile;
|
||||
final CreatedFontTracker _tracker = tracker;
|
||||
try {
|
||||
switch (fontFormat) {
|
||||
case Font.TRUETYPE_FONT:
|
||||
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
|
||||
break;
|
||||
case Font.TYPE1_FONT:
|
||||
font2D = new Type1Font(fontFilePath, null);
|
||||
font2D = new Type1Font(fontFilePath, null, isCopy);
|
||||
break;
|
||||
default:
|
||||
throw new FontFormatException("Unrecognised Font Format");
|
||||
@ -2379,6 +2381,9 @@ public final class FontManager {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
if (_tracker != null) {
|
||||
_tracker.subBytes((int)fFile.length());
|
||||
}
|
||||
fFile.delete();
|
||||
return null;
|
||||
}
|
||||
@ -2387,7 +2392,7 @@ public final class FontManager {
|
||||
throw(e);
|
||||
}
|
||||
if (isCopy) {
|
||||
font2D.setFileToRemove(fontFile);
|
||||
font2D.setFileToRemove(fontFile, tracker);
|
||||
synchronized (FontManager.class) {
|
||||
|
||||
if (tmpFontFiles == null) {
|
||||
|
@ -175,8 +175,17 @@ public class TrueTypeFont extends FileFont {
|
||||
super(platname, nativeNames);
|
||||
useJavaRasterizer = javaRasterizer;
|
||||
fontRank = Font2D.TTF_RANK;
|
||||
verify();
|
||||
init(fIndex);
|
||||
try {
|
||||
verify();
|
||||
init(fIndex);
|
||||
} catch (Throwable t) {
|
||||
close();
|
||||
if (t instanceof FontFormatException) {
|
||||
throw (FontFormatException)t;
|
||||
} else {
|
||||
throw new FontFormatException("Unexpected runtime exception.");
|
||||
}
|
||||
}
|
||||
Disposer.addObjectRecord(this, disposerRecord);
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ import java.nio.BufferUnderflowException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.awt.Font;
|
||||
@ -76,6 +77,27 @@ import java.awt.Font;
|
||||
*/
|
||||
public class Type1Font extends FileFont {
|
||||
|
||||
private static class T1DisposerRecord implements DisposerRecord {
|
||||
String fileName = null;
|
||||
|
||||
T1DisposerRecord(String name) {
|
||||
fileName = name;
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
|
||||
if (fileName != null) {
|
||||
(new java.io.File(fileName)).delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
WeakReference bufferRef = new WeakReference(null);
|
||||
|
||||
private String psName = null;
|
||||
@ -124,6 +146,17 @@ public class Type1Font extends FileFont {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Type1 Font.
|
||||
* @param platname - Platform identifier of the font. Typically file name.
|
||||
* @param nativeNames - Native names - typically XLFDs on Unix.
|
||||
*/
|
||||
public Type1Font(String platname, Object nativeNames)
|
||||
throws FontFormatException {
|
||||
|
||||
this(platname, nativeNames, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* - does basic verification of the file
|
||||
* - reads the names (full, family).
|
||||
@ -131,12 +164,25 @@ public class Type1Font extends FileFont {
|
||||
* @throws FontFormatException - if the font can't be opened
|
||||
* or fails verification, or there's no usable cmap
|
||||
*/
|
||||
public Type1Font(String platname, Object nativeNames)
|
||||
public Type1Font(String platname, Object nativeNames, boolean createdCopy)
|
||||
throws FontFormatException {
|
||||
super(platname, nativeNames);
|
||||
fontRank = Font2D.TYPE1_RANK;
|
||||
checkedNatives = true;
|
||||
verify();
|
||||
try {
|
||||
verify();
|
||||
} catch (Throwable t) {
|
||||
if (createdCopy) {
|
||||
T1DisposerRecord ref = new T1DisposerRecord(platname);
|
||||
Disposer.addObjectRecord(bufferRef, ref);
|
||||
bufferRef = null;
|
||||
}
|
||||
if (t instanceof FontFormatException) {
|
||||
throw (FontFormatException)t;
|
||||
} else {
|
||||
throw new FontFormatException("Unexpected runtime exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized ByteBuffer getBuffer() throws FontFormatException {
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -52,6 +52,9 @@ class Request {
|
||||
os = rawout;
|
||||
do {
|
||||
startLine = readLine();
|
||||
if (startLine == null) {
|
||||
return;
|
||||
}
|
||||
/* skip blank lines */
|
||||
} while (startLine == null ? false : startLine.equals (""));
|
||||
}
|
||||
|
@ -433,6 +433,7 @@ class ServerImpl implements TimeSource {
|
||||
rawin = sslStreams.getInputStream();
|
||||
rawout = sslStreams.getOutputStream();
|
||||
engine = sslStreams.getSSLEngine();
|
||||
connection.sslStreams = sslStreams;
|
||||
} else {
|
||||
rawin = new BufferedInputStream(
|
||||
new Request.ReadStream (
|
||||
@ -442,6 +443,8 @@ class ServerImpl implements TimeSource {
|
||||
ServerImpl.this, chan
|
||||
);
|
||||
}
|
||||
connection.raw = rawin;
|
||||
connection.rawout = rawout;
|
||||
}
|
||||
Request req = new Request (rawin, rawout);
|
||||
requestLine = req.requestLine();
|
||||
|
@ -113,16 +113,16 @@ abstract class AsynchronousFileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
final void invalidateAllLocks() {
|
||||
final void invalidateAllLocks() throws IOException {
|
||||
if (fileLockTable != null) {
|
||||
try {
|
||||
fileLockTable.removeAll( new FileLockTable.Releaser() {
|
||||
public void release(FileLock fl) {
|
||||
((FileLockImpl)fl).invalidate();
|
||||
for (FileLock fl: fileLockTable.removeAll()) {
|
||||
synchronized (fl) {
|
||||
if (fl.isValid()) {
|
||||
FileLockImpl fli = (FileLockImpl)fl;
|
||||
implRelease(fli);
|
||||
fli.invalidate();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,7 +158,21 @@ abstract class AsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by FileLockImpl to release lock acquired by this channel.
|
||||
* Releases the given file lock.
|
||||
*/
|
||||
abstract void release(FileLockImpl fli) throws IOException;
|
||||
protected abstract void implRelease(FileLockImpl fli) throws IOException;
|
||||
|
||||
/**
|
||||
* Invoked by FileLockImpl to release the given file lock and remove it
|
||||
* from the lock table.
|
||||
*/
|
||||
final void release(FileLockImpl fli) throws IOException {
|
||||
try {
|
||||
begin();
|
||||
implRelease(fli);
|
||||
removeFromFileLockTable(fli);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ import java.nio.BufferPoolMXBean;
|
||||
import java.nio.channels.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.AccessController;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
@ -95,14 +93,16 @@ public class FileChannelImpl
|
||||
// -- Standard channel operations --
|
||||
|
||||
protected void implCloseChannel() throws IOException {
|
||||
// Invalidate and release any locks that we still hold
|
||||
// Release and invalidate any locks that we still hold
|
||||
if (fileLockTable != null) {
|
||||
fileLockTable.removeAll( new FileLockTable.Releaser() {
|
||||
public void release(FileLock fl) throws IOException {
|
||||
((FileLockImpl)fl).invalidate();
|
||||
nd.release(fd, fl.position(), fl.size());
|
||||
for (FileLock fl: fileLockTable.removeAll()) {
|
||||
synchronized (fl) {
|
||||
if (fl.isValid()) {
|
||||
nd.release(fd, fl.position(), fl.size());
|
||||
((FileLockImpl)fl).invalidate();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
nd.preClose(fd);
|
||||
@ -912,32 +912,33 @@ public class FileChannelImpl
|
||||
FileLockImpl fli = new FileLockImpl(this, position, size, shared);
|
||||
FileLockTable flt = fileLockTable();
|
||||
flt.add(fli);
|
||||
boolean i = true;
|
||||
boolean completed = false;
|
||||
int ti = -1;
|
||||
try {
|
||||
begin();
|
||||
ti = threads.add();
|
||||
if (!isOpen())
|
||||
return null;
|
||||
int result = nd.lock(fd, true, position, size, shared);
|
||||
if (result == FileDispatcher.RET_EX_LOCK) {
|
||||
assert shared;
|
||||
FileLockImpl fli2 = new FileLockImpl(this, position, size,
|
||||
false);
|
||||
flt.replace(fli, fli2);
|
||||
return fli2;
|
||||
int n;
|
||||
do {
|
||||
n = nd.lock(fd, true, position, size, shared);
|
||||
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
|
||||
if (isOpen()) {
|
||||
if (n == FileDispatcher.RET_EX_LOCK) {
|
||||
assert shared;
|
||||
FileLockImpl fli2 = new FileLockImpl(this, position, size,
|
||||
false);
|
||||
flt.replace(fli, fli2);
|
||||
fli = fli2;
|
||||
}
|
||||
completed = true;
|
||||
}
|
||||
if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) {
|
||||
flt.remove(fli);
|
||||
i = false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
flt.remove(fli);
|
||||
throw e;
|
||||
} finally {
|
||||
if (!completed)
|
||||
flt.remove(fli);
|
||||
threads.remove(ti);
|
||||
try {
|
||||
end(i);
|
||||
end(completed);
|
||||
} catch (ClosedByInterruptException e) {
|
||||
throw new FileLockInterruptionException();
|
||||
}
|
||||
@ -985,7 +986,6 @@ public class FileChannelImpl
|
||||
}
|
||||
|
||||
void release(FileLockImpl fli) throws IOException {
|
||||
ensureOpen();
|
||||
int ti = threads.add();
|
||||
try {
|
||||
ensureOpen();
|
||||
@ -1005,7 +1005,7 @@ public class FileChannelImpl
|
||||
*/
|
||||
private static class SimpleFileLockTable extends FileLockTable {
|
||||
// synchronize on list for access
|
||||
private List<FileLock> lockList = new ArrayList<FileLock>(2);
|
||||
private final List<FileLock> lockList = new ArrayList<FileLock>(2);
|
||||
|
||||
public SimpleFileLockTable() {
|
||||
}
|
||||
@ -1034,14 +1034,11 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAll(Releaser releaser) throws IOException {
|
||||
public List<FileLock> removeAll() {
|
||||
synchronized(lockList) {
|
||||
Iterator<FileLock> i = lockList.iterator();
|
||||
while (i.hasNext()) {
|
||||
FileLock fl = i.next();
|
||||
releaser.release(fl);
|
||||
i.remove();
|
||||
}
|
||||
List<FileLock> result = new ArrayList<FileLock>(lockList);
|
||||
lockList.clear();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,25 +31,24 @@ import java.nio.channels.*;
|
||||
public class FileLockImpl
|
||||
extends FileLock
|
||||
{
|
||||
boolean valid;
|
||||
private volatile boolean valid = true;
|
||||
|
||||
FileLockImpl(FileChannel channel, long position, long size, boolean shared)
|
||||
{
|
||||
super(channel, position, size, shared);
|
||||
this.valid = true;
|
||||
}
|
||||
|
||||
FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared)
|
||||
{
|
||||
super(channel, position, size, shared);
|
||||
this.valid = true;
|
||||
}
|
||||
|
||||
public synchronized boolean isValid() {
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
synchronized void invalidate() {
|
||||
void invalidate() {
|
||||
assert Thread.holdsLock(this);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
@ -66,5 +65,4 @@ public class FileLockImpl
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,23 +60,12 @@ abstract class FileLockTable {
|
||||
*/
|
||||
public abstract void remove(FileLock fl);
|
||||
|
||||
/**
|
||||
* An implementation of this interface releases a given file lock.
|
||||
* Used with removeAll.
|
||||
*/
|
||||
public abstract interface Releaser {
|
||||
void release(FileLock fl) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all file locks from the table.
|
||||
* <p>
|
||||
* The Releaser#release method is invoked for each file lock before
|
||||
* it is removed.
|
||||
*
|
||||
* @throws IOException if the release method throws IOException
|
||||
* @return The list of file locks removed
|
||||
*/
|
||||
public abstract void removeAll(Releaser r) throws IOException;
|
||||
public abstract List<FileLock> removeAll();
|
||||
|
||||
/**
|
||||
* Replaces an existing file lock in the table.
|
||||
@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable {
|
||||
FileLockReference ref = list.get(index);
|
||||
FileLock lock = ref.get();
|
||||
if (lock == fl) {
|
||||
assert (lock != null) && (lock.channel() == channel);
|
||||
assert (lock != null) && (lock.acquiredBy() == channel);
|
||||
ref.clear();
|
||||
list.remove(index);
|
||||
break;
|
||||
@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll(Releaser releaser) throws IOException {
|
||||
public List<FileLock> removeAll() {
|
||||
List<FileLock> result = new ArrayList<FileLock>();
|
||||
List<FileLockReference> list = lockMap.get(fileKey);
|
||||
if (list != null) {
|
||||
synchronized (list) {
|
||||
@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable {
|
||||
FileLock lock = ref.get();
|
||||
|
||||
// remove locks obtained by this channel
|
||||
if (lock != null && lock.channel() == channel) {
|
||||
// invoke the releaser to invalidate/release the lock
|
||||
releaser.release(lock);
|
||||
|
||||
if (lock != null && lock.acquiredBy() == channel) {
|
||||
// remove the lock from the list
|
||||
ref.clear();
|
||||
list.remove(index);
|
||||
|
||||
// add to result
|
||||
result.add(lock);
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable {
|
||||
removeKeyIfEmpty(fileKey, list);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,6 +97,9 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
// then it will throw ClosedChannelException
|
||||
}
|
||||
|
||||
// Invalidate and release any locks that we still hold
|
||||
invalidateAllLocks();
|
||||
|
||||
// signal any threads blocked on this channel
|
||||
nd.preClose(fdObj);
|
||||
threads.signalAndWait();
|
||||
@ -109,9 +112,6 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
closeLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
// Invalidate and release any locks that we still hold
|
||||
invalidateAllLocks();
|
||||
|
||||
// close file
|
||||
nd.close(fdObj);
|
||||
|
||||
@ -226,11 +226,9 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
do {
|
||||
n = nd.lock(fdObj, true, position, size, shared);
|
||||
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
|
||||
if (n == FileDispatcher.LOCKED) {
|
||||
if (n == FileDispatcher.LOCKED && isOpen()) {
|
||||
result.setResult(fli);
|
||||
} else {
|
||||
if (n != FileDispatcher.INTERRUPTED)
|
||||
throw new AssertionError();
|
||||
throw new AsynchronousCloseException();
|
||||
}
|
||||
} catch (IOException x) {
|
||||
@ -279,16 +277,16 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
do {
|
||||
n = nd.lock(fdObj, false, position, size, shared);
|
||||
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
|
||||
if (n != FileDispatcher.LOCKED) {
|
||||
if (n == FileDispatcher.NO_LOCK)
|
||||
return null; // locked by someone else
|
||||
if (n == FileDispatcher.INTERRUPTED)
|
||||
throw new AsynchronousCloseException();
|
||||
// should not get here
|
||||
throw new AssertionError();
|
||||
if (n == FileDispatcher.LOCKED && isOpen()) {
|
||||
gotLock = true;
|
||||
return fli; // lock acquired
|
||||
}
|
||||
gotLock = true;
|
||||
return fli;
|
||||
if (n == FileDispatcher.NO_LOCK)
|
||||
return null; // locked by someone else
|
||||
if (n == FileDispatcher.INTERRUPTED)
|
||||
throw new AsynchronousCloseException();
|
||||
// should not get here
|
||||
throw new AssertionError();
|
||||
} finally {
|
||||
if (!gotLock)
|
||||
removeFromFileLockTable(fli);
|
||||
@ -298,14 +296,8 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
void release(FileLockImpl fli) throws IOException {
|
||||
try {
|
||||
begin();
|
||||
nd.release(fdObj, fli.position(), fli.size());
|
||||
removeFromFileLockTable(fli);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
protected void implRelease(FileLockImpl fli) throws IOException {
|
||||
nd.release(fdObj, fli.position(), fli.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -736,6 +736,14 @@ public class Config {
|
||||
return name;
|
||||
}
|
||||
|
||||
private static String trimmed(String s) {
|
||||
s = s.trim();
|
||||
if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
|
||||
s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
|
||||
s = s.substring(1, s.length()-1).trim();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
/**
|
||||
* Parses key-value pairs under a stanza name.
|
||||
*/
|
||||
@ -747,7 +755,7 @@ public class Config {
|
||||
for (int j = 0; j < line.length(); j++) {
|
||||
if (line.charAt(j) == '=') {
|
||||
String key = (line.substring(0, j)).trim();
|
||||
String value = (line.substring(j + 1)).trim();
|
||||
String value = trimmed(line.substring(j + 1));
|
||||
table.put(key, value);
|
||||
break;
|
||||
}
|
||||
@ -820,7 +828,7 @@ public class Config {
|
||||
} else {
|
||||
nameVector = table.get(key);
|
||||
}
|
||||
nameVector.addElement((line.substring(j + 1)).trim());
|
||||
nameVector.addElement(trimmed(line.substring(j + 1)));
|
||||
table.put(key, nameVector);
|
||||
break;
|
||||
}
|
||||
@ -1263,4 +1271,32 @@ public class Config {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
toStringIndented("", stanzaTable, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
private static void toStringIndented(String prefix, Object obj,
|
||||
StringBuffer sb) {
|
||||
if (obj instanceof String) {
|
||||
sb.append(prefix);
|
||||
sb.append(obj);
|
||||
sb.append('\n');
|
||||
} else if (obj instanceof Hashtable) {
|
||||
Hashtable tab = (Hashtable)obj;
|
||||
for (Object o: tab.keySet()) {
|
||||
sb.append(prefix);
|
||||
sb.append(o);
|
||||
sb.append(" = {\n");
|
||||
toStringIndented(prefix + " ", tab.get(o), sb);
|
||||
sb.append(prefix + "}\n");
|
||||
}
|
||||
} else if (obj instanceof Vector) {
|
||||
Vector v = (Vector)obj;
|
||||
for (Object o: v.toArray()) {
|
||||
toStringIndented(prefix + " ", o, sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,27 +274,31 @@ public abstract class KrbKdcReq {
|
||||
+ ",Attempt =" + i
|
||||
+ ", #bytes=" + obuf.length);
|
||||
}
|
||||
/*
|
||||
* Send the data to the kdc.
|
||||
*/
|
||||
try {
|
||||
/*
|
||||
* Send the data to the kdc.
|
||||
*/
|
||||
|
||||
kdcClient.send(obuf);
|
||||
|
||||
/*
|
||||
* And get a response.
|
||||
*/
|
||||
try {
|
||||
ibuf = kdcClient.receive();
|
||||
break;
|
||||
} catch (SocketTimeoutException se) {
|
||||
if (DEBUG) {
|
||||
System.out.println ("SocketTimeOutException with " +
|
||||
"attempt: " + i);
|
||||
}
|
||||
if (i == DEFAULT_KDC_RETRY_LIMIT) {
|
||||
ibuf = null;
|
||||
throw se;
|
||||
/*
|
||||
* And get a response.
|
||||
*/
|
||||
try {
|
||||
ibuf = kdcClient.receive();
|
||||
break;
|
||||
} catch (SocketTimeoutException se) {
|
||||
if (DEBUG) {
|
||||
System.out.println ("SocketTimeOutException with " +
|
||||
"attempt: " + i);
|
||||
}
|
||||
if (i == DEFAULT_KDC_RETRY_LIMIT) {
|
||||
ibuf = null;
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
kdcClient.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,4 +93,7 @@ public class UDPClient {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
dgSocket.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,6 +38,8 @@ import static sun.security.pkcs11.TemplateManager.*;
|
||||
import sun.security.pkcs11.wrapper.*;
|
||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||
|
||||
import sun.security.rsa.RSAKeyFactory;
|
||||
|
||||
/**
|
||||
* KeyPairGenerator implementation class. This class currently supports
|
||||
* RSA, DSA, DH, and EC.
|
||||
@ -66,7 +68,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
private AlgorithmParameterSpec params;
|
||||
|
||||
// for RSA, selected or default value of public exponent, always valid
|
||||
private BigInteger rsaPublicExponent;
|
||||
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
|
||||
|
||||
// SecureRandom instance, if specified in init
|
||||
private SecureRandom random;
|
||||
@ -88,19 +90,19 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
public void initialize(int keySize, SecureRandom random) {
|
||||
token.ensureValid();
|
||||
try {
|
||||
checkKeySize(keySize);
|
||||
checkKeySize(keySize, null);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
throw new InvalidParameterException(e.getMessage());
|
||||
}
|
||||
this.keySize = keySize;
|
||||
this.params = null;
|
||||
this.random = random;
|
||||
this.rsaPublicExponent = RSAKeyGenParameterSpec.F4;
|
||||
if (algorithm.equals("EC")) {
|
||||
params = P11ECKeyFactory.getECParameterSpec(keySize);
|
||||
if (params == null) {
|
||||
throw new InvalidParameterException
|
||||
("No EC parameters available for key size " + keySize + " bits");
|
||||
throw new InvalidParameterException(
|
||||
"No EC parameters available for key size "
|
||||
+ keySize + " bits");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,8 +117,10 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
("DHParameterSpec required for Diffie-Hellman");
|
||||
}
|
||||
DHParameterSpec dhParams = (DHParameterSpec)params;
|
||||
this.keySize = dhParams.getP().bitLength();
|
||||
this.params = params;
|
||||
int tmpKeySize = dhParams.getP().bitLength();
|
||||
checkKeySize(tmpKeySize, dhParams);
|
||||
this.keySize = tmpKeySize;
|
||||
this.params = dhParams;
|
||||
// XXX sanity check params
|
||||
} else if (algorithm.equals("RSA")) {
|
||||
if (params instanceof RSAKeyGenParameterSpec == false) {
|
||||
@ -124,7 +128,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
("RSAKeyGenParameterSpec required for RSA");
|
||||
}
|
||||
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
|
||||
this.keySize = rsaParams.getKeysize();
|
||||
int tmpKeySize = rsaParams.getKeysize();
|
||||
checkKeySize(tmpKeySize, rsaParams);
|
||||
this.keySize = tmpKeySize;
|
||||
this.params = null;
|
||||
this.rsaPublicExponent = rsaParams.getPublicExponent();
|
||||
// XXX sanity check params
|
||||
@ -134,13 +140,16 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
("DSAParameterSpec required for DSA");
|
||||
}
|
||||
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
|
||||
this.keySize = dsaParams.getP().bitLength();
|
||||
this.params = params;
|
||||
int tmpKeySize = dsaParams.getP().bitLength();
|
||||
checkKeySize(tmpKeySize, dsaParams);
|
||||
this.keySize = tmpKeySize;
|
||||
this.params = dsaParams;
|
||||
// XXX sanity check params
|
||||
} else if (algorithm.equals("EC")) {
|
||||
ECParameterSpec ecParams;
|
||||
if (params instanceof ECParameterSpec) {
|
||||
ecParams = P11ECKeyFactory.getECParameterSpec((ECParameterSpec)params);
|
||||
ecParams = P11ECKeyFactory.getECParameterSpec(
|
||||
(ECParameterSpec)params);
|
||||
if (ecParams == null) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Unsupported curve: " + params);
|
||||
@ -156,16 +165,17 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("ECParameterSpec or ECGenParameterSpec required for EC");
|
||||
}
|
||||
this.keySize = ecParams.getCurve().getField().getFieldSize();
|
||||
int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
|
||||
checkKeySize(tmpKeySize, ecParams);
|
||||
this.keySize = tmpKeySize;
|
||||
this.params = ecParams;
|
||||
} else {
|
||||
throw new ProviderException("Unknown algorithm: " + algorithm);
|
||||
}
|
||||
this.random = random;
|
||||
checkKeySize(keySize);
|
||||
}
|
||||
|
||||
private void checkKeySize(int keySize)
|
||||
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (algorithm.equals("EC")) {
|
||||
if (keySize < 112) {
|
||||
@ -178,13 +188,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
("Key size must be at most 2048 bit");
|
||||
}
|
||||
return;
|
||||
} else if (algorithm.equals("RSA")) {
|
||||
BigInteger tmpExponent = rsaPublicExponent;
|
||||
if (params != null) {
|
||||
// Already tested for instanceof RSAKeyGenParameterSpec above
|
||||
tmpExponent =
|
||||
((RSAKeyGenParameterSpec)params).getPublicExponent();
|
||||
}
|
||||
try {
|
||||
// This provider supports 64K or less.
|
||||
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
|
||||
512, 64 * 1024);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidAlgorithmParameterException(e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (keySize < 512) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Key size must be at least 512 bit");
|
||||
}
|
||||
if (algorithm.equals("RSA") ||
|
||||
(algorithm.equals("DH") && (params != null))) {
|
||||
if (algorithm.equals("DH") && (params != null)) {
|
||||
// sanity check, nobody really wants keys this large
|
||||
if (keySize > 64 * 1024) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
|
@ -80,6 +80,8 @@ import static sun.security.pkcs11.P11Util.*;
|
||||
import sun.security.pkcs11.wrapper.*;
|
||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||
|
||||
import sun.security.rsa.RSAKeyFactory;
|
||||
|
||||
final class P11KeyStore extends KeyStoreSpi {
|
||||
|
||||
private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
|
||||
@ -1328,6 +1330,15 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||
BigInteger modulus = attrs[0].getBigInteger();
|
||||
keyLength = modulus.bitLength();
|
||||
|
||||
// This check will combine our "don't care" values here
|
||||
// with the system-wide min/max values.
|
||||
try {
|
||||
RSAKeyFactory.checkKeyLengths(keyLength, null,
|
||||
-1, Integer.MAX_VALUE);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new KeyStoreException(e.getMessage());
|
||||
}
|
||||
|
||||
return P11Key.privateKey(session,
|
||||
oHandle,
|
||||
keyType,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,8 @@ import static sun.security.pkcs11.TemplateManager.*;
|
||||
import sun.security.pkcs11.wrapper.*;
|
||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||
|
||||
import sun.security.rsa.RSAKeyFactory;
|
||||
|
||||
/**
|
||||
* RSA KeyFactory implemenation.
|
||||
*
|
||||
@ -131,6 +133,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
||||
} catch (PKCS11Exception e) {
|
||||
throw new InvalidKeySpecException
|
||||
("Could not create RSA public key", e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidKeySpecException
|
||||
("Could not create RSA public key", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,11 +180,15 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
||||
} catch (PKCS11Exception e) {
|
||||
throw new InvalidKeySpecException
|
||||
("Could not create RSA private key", e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidKeySpecException
|
||||
("Could not create RSA private key", e);
|
||||
}
|
||||
}
|
||||
|
||||
private PublicKey generatePublic(BigInteger n, BigInteger e)
|
||||
throws PKCS11Exception {
|
||||
throws PKCS11Exception, InvalidKeyException {
|
||||
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
|
||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
|
||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||
@ -200,7 +209,8 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
||||
}
|
||||
|
||||
private PrivateKey generatePrivate(BigInteger n, BigInteger d)
|
||||
throws PKCS11Exception {
|
||||
throws PKCS11Exception, InvalidKeyException {
|
||||
RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);
|
||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||
@ -222,7 +232,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
||||
|
||||
private PrivateKey generatePrivate(BigInteger n, BigInteger e,
|
||||
BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
|
||||
BigInteger qe, BigInteger coeff) throws PKCS11Exception {
|
||||
BigInteger qe, BigInteger coeff) throws PKCS11Exception,
|
||||
InvalidKeyException {
|
||||
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
|
||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||
|
@ -120,11 +120,13 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream) instead
|
||||
* @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
public SunPKCS11(String configName, InputStream configStream) {
|
||||
super("SunPKCS11-" + Config.getConfig(configName, configStream).getName(),
|
||||
super("SunPKCS11-" +
|
||||
Config.getConfig(configName, configStream).getName(),
|
||||
1.7d, Config.getConfig(configName, configStream).getDescription());
|
||||
this.configName = configName;
|
||||
this.config = Config.removeConfig(configName);
|
||||
@ -153,7 +155,8 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
//
|
||||
// If we are in Secmod mode and configured to use either the
|
||||
// nssKeyStore or the nssTrustAnchors module, we automatically
|
||||
// switch to using the NSS trust attributes for trusted certs (KeyStore).
|
||||
// switch to using the NSS trust attributes for trusted certs
|
||||
// (KeyStore).
|
||||
//
|
||||
|
||||
if (useSecmod) {
|
||||
@ -168,33 +171,40 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
if (secmod.isInitialized()) {
|
||||
if (nssSecmodDirectory != null) {
|
||||
String s = secmod.getConfigDir();
|
||||
if ((s != null) && (s.equals(nssSecmodDirectory) == false)) {
|
||||
if ((s != null) &&
|
||||
(s.equals(nssSecmodDirectory) == false)) {
|
||||
throw new ProviderException("Secmod directory "
|
||||
+ nssSecmodDirectory
|
||||
+ " invalid, NSS already initialized with " + s);
|
||||
+ " invalid, NSS already initialized with "
|
||||
+ s);
|
||||
}
|
||||
}
|
||||
if (nssLibraryDirectory != null) {
|
||||
String s = secmod.getLibDir();
|
||||
if ((s != null) && (s.equals(nssLibraryDirectory) == false)) {
|
||||
if ((s != null) &&
|
||||
(s.equals(nssLibraryDirectory) == false)) {
|
||||
throw new ProviderException("NSS library directory "
|
||||
+ nssLibraryDirectory
|
||||
+ " invalid, NSS already initialized with " + s);
|
||||
+ " invalid, NSS already initialized with "
|
||||
+ s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nssDbMode != DbMode.NO_DB) {
|
||||
if (nssSecmodDirectory == null) {
|
||||
throw new ProviderException("Secmod not initialized and "
|
||||
+ "nssSecmodDirectory not specified");
|
||||
throw new ProviderException(
|
||||
"Secmod not initialized and "
|
||||
+ "nssSecmodDirectory not specified");
|
||||
}
|
||||
} else {
|
||||
if (nssSecmodDirectory != null) {
|
||||
throw new ProviderException
|
||||
("nssSecmodDirectory must not be specified in noDb mode");
|
||||
throw new ProviderException(
|
||||
"nssSecmodDirectory must not be "
|
||||
+ "specified in noDb mode");
|
||||
}
|
||||
}
|
||||
secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory);
|
||||
secmod.initialize(nssDbMode, nssSecmodDirectory,
|
||||
nssLibraryDirectory);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// XXX which exception to throw
|
||||
@ -211,7 +221,8 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
if (nssModule != null) {
|
||||
moduleName = "fips";
|
||||
} else {
|
||||
moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore";
|
||||
moduleName = (nssDbMode == DbMode.NO_DB) ?
|
||||
"crypto" : "keystore";
|
||||
}
|
||||
}
|
||||
if (moduleName.equals("fips")) {
|
||||
@ -253,10 +264,12 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
+ ": only " + k + " external NSS modules available");
|
||||
}
|
||||
} else {
|
||||
throw new ProviderException("Unknown NSS module: " + moduleName);
|
||||
throw new ProviderException(
|
||||
"Unknown NSS module: " + moduleName);
|
||||
}
|
||||
if (nssModule == null) {
|
||||
throw new ProviderException("NSS module not available: " + moduleName);
|
||||
throw new ProviderException(
|
||||
"NSS module not available: " + moduleName);
|
||||
}
|
||||
if (nssModule.hasInitializedProvider()) {
|
||||
throw new ProviderException("Secmod module already configured");
|
||||
@ -296,8 +309,9 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
initArgs.flags = CKF_OS_LOCKING_OK;
|
||||
PKCS11 tmpPKCS11;
|
||||
try {
|
||||
tmpPKCS11 = PKCS11.getInstance
|
||||
(library, functionList, initArgs, config.getOmitInitialize());
|
||||
tmpPKCS11 = PKCS11.getInstance(
|
||||
library, functionList, initArgs,
|
||||
config.getOmitInitialize());
|
||||
} catch (PKCS11Exception e) {
|
||||
if (debug != null) {
|
||||
debug.println("Multi-threaded initialization failed: " + e);
|
||||
@ -312,8 +326,8 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
} else {
|
||||
initArgs.flags = 0;
|
||||
}
|
||||
tmpPKCS11 = PKCS11.getInstance
|
||||
(library, functionList, initArgs, config.getOmitInitialize());
|
||||
tmpPKCS11 = PKCS11.getInstance(library,
|
||||
functionList, initArgs, config.getOmitInitialize());
|
||||
}
|
||||
p11 = tmpPKCS11;
|
||||
|
||||
@ -336,8 +350,10 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
System.out.println("Slots with tokens: " + toString(slots));
|
||||
}
|
||||
if (slotID < 0) {
|
||||
if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
|
||||
throw new ProviderException("slotListIndex is " + slotListIndex
|
||||
if ((slotListIndex < 0)
|
||||
|| (slotListIndex >= slots.length)) {
|
||||
throw new ProviderException("slotListIndex is "
|
||||
+ slotListIndex
|
||||
+ " but token only has " + slots.length + " slots");
|
||||
}
|
||||
slotID = slots[slotListIndex];
|
||||
@ -575,12 +591,15 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
|
||||
m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
|
||||
d(KF, "EC", P11DHKeyFactory,
|
||||
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
|
||||
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
|
||||
CKM_ECDSA, CKM_ECDSA_SHA1));
|
||||
|
||||
// AlgorithmParameters for EC.
|
||||
// Only needed until we have an EC implementation in the SUN provider.
|
||||
d(AGP, "EC", "sun.security.ec.ECParameters", s("1.2.840.10045.2.1"),
|
||||
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
|
||||
d(AGP, "EC", "sun.security.ec.ECParameters",
|
||||
s("1.2.840.10045.2.1"),
|
||||
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
|
||||
CKM_ECDSA, CKM_ECDSA_SHA1));
|
||||
|
||||
d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
|
||||
m(CKM_DH_PKCS_DERIVE));
|
||||
@ -654,12 +673,16 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
d(SIG, "SHA512withRSA", P11Signature,
|
||||
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
|
||||
|
||||
d(KG, "SunTlsRsaPremasterSecret", "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
|
||||
d(KG, "SunTlsRsaPremasterSecret",
|
||||
"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
|
||||
m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
|
||||
d(KG, "SunTlsMasterSecret", "sun.security.pkcs11.P11TlsMasterSecretGenerator",
|
||||
d(KG, "SunTlsMasterSecret",
|
||||
"sun.security.pkcs11.P11TlsMasterSecretGenerator",
|
||||
m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
|
||||
CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_MASTER_KEY_DERIVE_DH));
|
||||
d(KG, "SunTlsKeyMaterial", "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
|
||||
CKM_SSL3_MASTER_KEY_DERIVE_DH,
|
||||
CKM_TLS_MASTER_KEY_DERIVE_DH));
|
||||
d(KG, "SunTlsKeyMaterial",
|
||||
"sun.security.pkcs11.P11TlsKeyMaterialGenerator",
|
||||
m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
|
||||
d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
|
||||
m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
|
||||
@ -773,6 +796,13 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
System.out.println(token.tokenInfo);
|
||||
}
|
||||
long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
|
||||
|
||||
// Create a map from the various Descriptors to the "most
|
||||
// preferred" mechanism that was defined during the
|
||||
// static initialization. For example, DES/CBC/PKCS5Padding
|
||||
// could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer
|
||||
// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
|
||||
// return a CKM_DES_CBC_PAD.
|
||||
final Map<Descriptor,Integer> supportedAlgs =
|
||||
new HashMap<Descriptor,Integer>();
|
||||
for (int i = 0; i < supportedMechanisms.length; i++) {
|
||||
@ -807,6 +837,9 @@ public final class SunPKCS11 extends AuthProvider {
|
||||
supportedAlgs.put(d, integerMech);
|
||||
continue;
|
||||
}
|
||||
// See if there is something "more preferred"
|
||||
// than what we currently have in the supportedAlgs
|
||||
// map.
|
||||
int intOldMech = oldMech.intValue();
|
||||
for (int j = 0; j < d.mechanisms.length; j++) {
|
||||
int nextMech = d.mechanisms[j];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,6 +31,8 @@ import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
|
||||
* and getAlgorithm() must return "RSA". For such keys, it supports conversion
|
||||
@ -68,6 +70,24 @@ public final class RSAKeyFactory extends KeyFactorySpi {
|
||||
private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
|
||||
private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
|
||||
|
||||
public final static int MIN_MODLEN = 512;
|
||||
public final static int MAX_MODLEN = 16384;
|
||||
|
||||
/*
|
||||
* If the modulus length is above this value, restrict the size of
|
||||
* the exponent to something that can be reasonably computed. We
|
||||
* could simply hardcode the exp len to something like 64 bits, but
|
||||
* this approach allows flexibility in case impls would like to use
|
||||
* larger module and exponent values.
|
||||
*/
|
||||
public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
|
||||
public final static int MAX_RESTRICTED_EXPLEN = 64;
|
||||
|
||||
private static final boolean restrictExpLen =
|
||||
"true".equalsIgnoreCase(AccessController.doPrivileged(
|
||||
new GetPropertyAction(
|
||||
"sun.security.rsa.restrictRSAExponent", "true")));
|
||||
|
||||
// instance used for static translateKey();
|
||||
private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
|
||||
|
||||
@ -76,74 +96,79 @@ public final class RSAKeyFactory extends KeyFactorySpi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to convert Key into a useable instance of
|
||||
* RSAPublicKey or RSAPrivate(Crt)Key. Check the key and convert it
|
||||
* to a SunRsaSign key if necessary. If the key is not an RSA key
|
||||
* or cannot be used, throw an InvalidKeyException.
|
||||
*
|
||||
* The difference between this method and engineTranslateKey() is that
|
||||
* we do not convert keys of other providers that are already an
|
||||
* instance of RSAPublicKey or RSAPrivate(Crt)Key.
|
||||
* Static method to convert Key into an instance of RSAPublicKeyImpl
|
||||
* or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
|
||||
* used, throw an InvalidKeyException.
|
||||
*
|
||||
* Used by RSASignature and RSACipher.
|
||||
*/
|
||||
public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
|
||||
if (key instanceof RSAKey) {
|
||||
RSAKey rsaKey = (RSAKey)key;
|
||||
checkKey(rsaKey);
|
||||
return rsaKey;
|
||||
if ((key instanceof RSAPrivateKeyImpl) ||
|
||||
(key instanceof RSAPrivateCrtKeyImpl) ||
|
||||
(key instanceof RSAPublicKeyImpl)) {
|
||||
return (RSAKey)key;
|
||||
} else {
|
||||
return (RSAKey)INSTANCE.engineTranslateKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given RSA key is valid.
|
||||
/*
|
||||
* Single test entry point for all of the mechanisms in the SunRsaSign
|
||||
* provider (RSA*KeyImpls). All of the tests are the same.
|
||||
*
|
||||
* For compatibility, we round up to the nearest byte here:
|
||||
* some Key impls might pass in a value within a byte of the
|
||||
* real value.
|
||||
*/
|
||||
private static void checkKey(RSAKey key) throws InvalidKeyException {
|
||||
// check for subinterfaces, omit additional checks for our keys
|
||||
if (key instanceof RSAPublicKey) {
|
||||
if (key instanceof RSAPublicKeyImpl) {
|
||||
return;
|
||||
}
|
||||
} else if (key instanceof RSAPrivateKey) {
|
||||
if ((key instanceof RSAPrivateCrtKeyImpl)
|
||||
|| (key instanceof RSAPrivateKeyImpl)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
throw new InvalidKeyException("Neither a public nor a private key");
|
||||
}
|
||||
// RSAKey does not extend Key, so we need to do a cast
|
||||
String keyAlg = ((Key)key).getAlgorithm();
|
||||
if (keyAlg.equals("RSA") == false) {
|
||||
throw new InvalidKeyException("Not an RSA key: " + keyAlg);
|
||||
}
|
||||
BigInteger modulus;
|
||||
// some providers implement RSAKey for keys where the values are
|
||||
// not accessible (although they should). Detect those here
|
||||
// for a more graceful failure.
|
||||
try {
|
||||
modulus = key.getModulus();
|
||||
if (modulus == null) {
|
||||
throw new InvalidKeyException("Modulus is missing");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new InvalidKeyException(e);
|
||||
}
|
||||
checkKeyLength(modulus);
|
||||
static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
|
||||
throws InvalidKeyException {
|
||||
checkKeyLengths(((modulusLen + 7) & ~7), exponent,
|
||||
RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the length of the modulus of an RSA key. We only support keys
|
||||
* at least 505 bits long.
|
||||
* Check the length of an RSA key modulus/exponent to make sure it
|
||||
* is not too short or long. Some impls have their own min and
|
||||
* max key sizes that may or may not match with a system defined value.
|
||||
*
|
||||
* @param modulusLen the bit length of the RSA modulus.
|
||||
* @param exponent the RSA exponent
|
||||
* @param minModulusLen if > 0, check to see if modulusLen is at
|
||||
* least this long, otherwise unused.
|
||||
* @param maxModulusLen caller will allow this max number of bits.
|
||||
* Allow the smaller of the system-defined maximum and this param.
|
||||
*
|
||||
* @throws InvalidKeyException if any of the values are unacceptable.
|
||||
*/
|
||||
static void checkKeyLength(BigInteger modulus) throws InvalidKeyException {
|
||||
if (modulus.bitLength() < 505) {
|
||||
// some providers may generate slightly shorter keys
|
||||
// accept them if the encoding is at least 64 bytes long
|
||||
throw new InvalidKeyException
|
||||
("RSA keys must be at least 512 bits long");
|
||||
public static void checkKeyLengths(int modulusLen, BigInteger exponent,
|
||||
int minModulusLen, int maxModulusLen) throws InvalidKeyException {
|
||||
|
||||
if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
|
||||
throw new InvalidKeyException( "RSA keys must be at least " +
|
||||
minModulusLen + " bits long");
|
||||
}
|
||||
|
||||
// Even though our policy file may allow this, we don't want
|
||||
// either value (mod/exp) to be too big.
|
||||
|
||||
int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
|
||||
|
||||
// If a RSAPrivateKey/RSAPublicKey, make sure the
|
||||
// modulus len isn't too big.
|
||||
if (modulusLen > maxLen) {
|
||||
throw new InvalidKeyException(
|
||||
"RSA keys must be no longer than " + maxLen + " bits");
|
||||
}
|
||||
|
||||
// If a RSAPublicKey, make sure the exponent isn't too big.
|
||||
if (restrictExpLen && (exponent != null) &&
|
||||
(modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
|
||||
(exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
|
||||
throw new InvalidKeyException(
|
||||
"RSA exponents can be no longer than " +
|
||||
MAX_RESTRICTED_EXPLEN + " bits " +
|
||||
" if modulus is greater than " +
|
||||
MAX_MODLEN_RESTRICT_EXP + " bits");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,7 +47,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
// public exponent to use
|
||||
private BigInteger publicExponent;
|
||||
|
||||
// size of the key to generate, >= 512
|
||||
// size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
|
||||
private int keySize;
|
||||
|
||||
// PRNG to use
|
||||
@ -60,15 +60,16 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
|
||||
// initialize the generator. See JCA doc
|
||||
public void initialize(int keySize, SecureRandom random) {
|
||||
if (keySize < 512) {
|
||||
throw new InvalidParameterException
|
||||
("Key size must be at least 512 bits");
|
||||
}
|
||||
if (keySize > 64 * 1024) {
|
||||
// do not allow unreasonably large key sizes, probably user error
|
||||
throw new InvalidParameterException
|
||||
("Key size must be 65536 bits or less");
|
||||
|
||||
// do not allow unreasonably small or large key sizes,
|
||||
// probably user error
|
||||
try {
|
||||
RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
|
||||
512, 64 * 1024);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidParameterException(e.getMessage());
|
||||
}
|
||||
|
||||
this.keySize = keySize;
|
||||
this.random = random;
|
||||
this.publicExponent = RSAKeyGenParameterSpec.F4;
|
||||
@ -77,35 +78,41 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
// second initialize method. See JCA doc.
|
||||
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
|
||||
if (params instanceof RSAKeyGenParameterSpec == false) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Params must be instance of RSAKeyGenParameterSpec");
|
||||
}
|
||||
|
||||
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
|
||||
keySize = rsaSpec.getKeysize();
|
||||
publicExponent = rsaSpec.getPublicExponent();
|
||||
this.random = random;
|
||||
if (keySize < 512) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Key size must be at least 512 bits");
|
||||
}
|
||||
if (keySize > 64 * 1024) {
|
||||
// do not allow unreasonably large key sizes, probably user error
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Key size must be 65536 bits or less");
|
||||
}
|
||||
if (publicExponent == null) {
|
||||
publicExponent = RSAKeyGenParameterSpec.F4;
|
||||
int tmpKeySize = rsaSpec.getKeysize();
|
||||
BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
|
||||
|
||||
if (tmpPublicExponent == null) {
|
||||
tmpPublicExponent = RSAKeyGenParameterSpec.F4;
|
||||
} else {
|
||||
if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
|
||||
if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Public exponent must be 3 or larger");
|
||||
}
|
||||
if (publicExponent.bitLength() > keySize) {
|
||||
if (tmpPublicExponent.bitLength() > tmpKeySize) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Public exponent must be smaller than key size");
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow unreasonably large key sizes, probably user error
|
||||
try {
|
||||
RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
|
||||
512, 64 * 1024);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Invalid key sizes", e);
|
||||
}
|
||||
|
||||
this.keySize = tmpKeySize;
|
||||
this.publicExponent = tmpPublicExponent;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
// generate the keypair. See JCA doc
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -89,7 +89,7 @@ public final class RSAPrivateCrtKeyImpl
|
||||
*/
|
||||
RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
|
||||
decode(encoded);
|
||||
RSAKeyFactory.checkKeyLength(n);
|
||||
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +107,8 @@ public final class RSAPrivateCrtKeyImpl
|
||||
this.pe = pe;
|
||||
this.qe = qe;
|
||||
this.coeff = coeff;
|
||||
RSAKeyFactory.checkKeyLength(n);
|
||||
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
|
||||
|
||||
// generate the encoding
|
||||
algid = rsaId;
|
||||
try {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,7 +61,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
|
||||
RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException {
|
||||
this.n = n;
|
||||
this.d = d;
|
||||
RSAKeyFactory.checkKeyLength(n);
|
||||
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
|
||||
// generate the encoding
|
||||
algid = RSAPrivateCrtKeyImpl.rsaId;
|
||||
try {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -56,10 +56,11 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
|
||||
* Construct a key from its components. Used by the
|
||||
* RSAKeyFactory and the RSAKeyPairGenerator.
|
||||
*/
|
||||
public RSAPublicKeyImpl(BigInteger n, BigInteger e) throws InvalidKeyException {
|
||||
public RSAPublicKeyImpl(BigInteger n, BigInteger e)
|
||||
throws InvalidKeyException {
|
||||
this.n = n;
|
||||
this.e = e;
|
||||
RSAKeyFactory.checkKeyLength(n);
|
||||
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
|
||||
// generate the encoding
|
||||
algid = RSAPrivateCrtKeyImpl.rsaId;
|
||||
try {
|
||||
@ -80,7 +81,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
|
||||
*/
|
||||
public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
|
||||
decode(encoded);
|
||||
RSAKeyFactory.checkKeyLength(n);
|
||||
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
|
||||
}
|
||||
|
||||
// see JCA doc
|
||||
|
@ -26,7 +26,8 @@
|
||||
package sun.security.util;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represent an ISO Object Identifier.
|
||||
@ -44,105 +45,186 @@ import java.io.*;
|
||||
* hierarchy, and other organizations can easily acquire the ability
|
||||
* to assign such unique identifiers.
|
||||
*
|
||||
*
|
||||
* @author David Brownell
|
||||
* @author Amit Kapoor
|
||||
* @author Hemma Prafullchandra
|
||||
*/
|
||||
|
||||
final public
|
||||
class ObjectIdentifier implements Serializable
|
||||
{
|
||||
/** use serialVersionUID from JDK 1.1. for interoperability */
|
||||
/**
|
||||
* We use the DER value (no tag, no length) as the internal format
|
||||
* @serial
|
||||
*/
|
||||
private byte[] encoding = null;
|
||||
|
||||
private transient volatile String stringForm;
|
||||
|
||||
/*
|
||||
* IMPORTANT NOTES FOR CODE CHANGES (bug 4811968) IN JDK 1.7.0
|
||||
* ===========================================================
|
||||
*
|
||||
* (Almost) serialization compatibility with old versions:
|
||||
*
|
||||
* serialVersionUID is unchanged. Old field "component" is changed to
|
||||
* type Object so that "poison" (unknown object type for old versions)
|
||||
* can be put inside if there are huge components that cannot be saved
|
||||
* as integers.
|
||||
*
|
||||
* New version use the new filed "encoding" only.
|
||||
*
|
||||
* Below are all 4 cases in a serialization/deserialization process:
|
||||
*
|
||||
* 1. old -> old: Not covered here
|
||||
* 2. old -> new: There's no "encoding" field, new readObject() reads
|
||||
* "components" and "componentLen" instead and inits correctly.
|
||||
* 3. new -> new: "encoding" field exists, new readObject() uses it
|
||||
* (ignoring the other 2 fields) and inits correctly.
|
||||
* 4. new -> old: old readObject() only recognizes "components" and
|
||||
* "componentLen" fields. If no huge components are involved, they
|
||||
* are serialized as legal values and old object can init correctly.
|
||||
* Otherwise, old object cannot recognize the form (component not int[])
|
||||
* and throw a ClassNotFoundException at deserialization time.
|
||||
*
|
||||
* Therfore, for the first 3 cases, exact compatibility is preserved. In
|
||||
* the 4th case, non-huge OID is still supportable in old versions, while
|
||||
* huge OID is not.
|
||||
*/
|
||||
private static final long serialVersionUID = 8697030238860181294L;
|
||||
private static final int maxFirstComponent = 2;
|
||||
private static final int maxSecondComponent = 39;
|
||||
|
||||
/**
|
||||
* Constructs an object identifier from a string. This string
|
||||
* should be of the form 1.23.34.45.56 etc.
|
||||
* Changed to Object
|
||||
* @serial
|
||||
*/
|
||||
private Object components = null; // path from root
|
||||
/**
|
||||
* @serial
|
||||
*/
|
||||
private int componentLen = -1; // how much is used.
|
||||
|
||||
// Is the components field calculated?
|
||||
transient private boolean componentsCalculated = false;
|
||||
|
||||
private void readObject(ObjectInputStream is)
|
||||
throws IOException, ClassNotFoundException {
|
||||
is.defaultReadObject();
|
||||
|
||||
if (encoding == null) { // from an old version
|
||||
init((int[])components, componentLen);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream os)
|
||||
throws IOException {
|
||||
if (!componentsCalculated) {
|
||||
int[] comps = toIntArray();
|
||||
if (comps != null) { // every one understands this
|
||||
components = comps;
|
||||
componentLen = comps.length;
|
||||
} else {
|
||||
components = HugeOidNotSupportedByOldJDK.theOne;
|
||||
}
|
||||
componentsCalculated = true;
|
||||
}
|
||||
os.defaultWriteObject();
|
||||
}
|
||||
|
||||
static class HugeOidNotSupportedByOldJDK implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs, from a string. This string should be of the form 1.23.56.
|
||||
* Validity check included.
|
||||
*/
|
||||
public ObjectIdentifier (String oid) throws IOException
|
||||
{
|
||||
int ch = '.';
|
||||
int start = 0;
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
|
||||
// Calculate length of oid
|
||||
componentLen = 0;
|
||||
while ((end = oid.indexOf(ch,start)) != -1) {
|
||||
start = end + 1;
|
||||
componentLen += 1;
|
||||
}
|
||||
componentLen += 1;
|
||||
components = new int[componentLen];
|
||||
int pos = 0;
|
||||
byte[] tmp = new byte[oid.length()];
|
||||
int first = 0, second;
|
||||
int count = 0;
|
||||
|
||||
start = 0;
|
||||
int i = 0;
|
||||
String comp = null;
|
||||
try {
|
||||
while ((end = oid.indexOf(ch,start)) != -1) {
|
||||
comp = oid.substring(start,end);
|
||||
components[i++] = Integer.valueOf(comp).intValue();
|
||||
String comp = null;
|
||||
do {
|
||||
int length = 0; // length of one section
|
||||
end = oid.indexOf(ch,start);
|
||||
if (end == -1) {
|
||||
comp = oid.substring(start);
|
||||
length = oid.length() - start;
|
||||
} else {
|
||||
comp = oid.substring(start,end);
|
||||
length = end - start;
|
||||
}
|
||||
|
||||
if (length > 9) {
|
||||
BigInteger bignum = new BigInteger(comp);
|
||||
if (count == 0) {
|
||||
checkFirstComponent(bignum);
|
||||
first = bignum.intValue();
|
||||
} else {
|
||||
if (count == 1) {
|
||||
checkSecondComponent(first, bignum);
|
||||
bignum = bignum.add(BigInteger.valueOf(40*first));
|
||||
} else {
|
||||
checkOtherComponent(count, bignum);
|
||||
}
|
||||
pos += pack7Oid(bignum, tmp, pos);
|
||||
}
|
||||
} else {
|
||||
int num = Integer.parseInt(comp);
|
||||
if (count == 0) {
|
||||
checkFirstComponent(num);
|
||||
first = num;
|
||||
} else {
|
||||
if (count == 1) {
|
||||
checkSecondComponent(first, num);
|
||||
num += 40 * first;
|
||||
} else {
|
||||
checkOtherComponent(count, num);
|
||||
}
|
||||
pos += pack7Oid(num, tmp, pos);
|
||||
}
|
||||
}
|
||||
start = end + 1;
|
||||
}
|
||||
comp = oid.substring(start);
|
||||
components[i] = Integer.valueOf(comp).intValue();
|
||||
count++;
|
||||
} while (end != -1);
|
||||
|
||||
checkCount(count);
|
||||
encoding = new byte[pos];
|
||||
System.arraycopy(tmp, 0, encoding, 0, pos);
|
||||
this.stringForm = oid;
|
||||
} catch (IOException ioe) { // already detected by checkXXX
|
||||
throw ioe;
|
||||
} catch (Exception e) {
|
||||
throw new IOException("ObjectIdentifier() -- Invalid format: "
|
||||
+ e.toString(), e);
|
||||
}
|
||||
checkValidOid(components, componentLen);
|
||||
this.stringForm = oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the values make a legal OID. There must be at least 2
|
||||
* components and they must be all non-negative. The first component
|
||||
* should be 0,1 or 2. When the first component is 0 or 1, the
|
||||
* second component should be less than or equal to 39
|
||||
*
|
||||
* @param values the components that will make the OID
|
||||
* @param len the number of components to check. Note that the allocation
|
||||
* size of <code>values</code> may be longer than <code>len</code>.
|
||||
* In this case, only the first <code>len</code> items are checked.
|
||||
* @exception IOException if this is not a legal OID
|
||||
*/
|
||||
private void checkValidOid(int[] values, int len) throws IOException {
|
||||
if (values == null || len < 2) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Must be at least two oid components ");
|
||||
}
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
if (values[i] < 0) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"oid component #" + (i+1) + " must be non-negative ");
|
||||
}
|
||||
}
|
||||
|
||||
if (values[0] > maxFirstComponent) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"First oid component is invalid ");
|
||||
}
|
||||
|
||||
if (values[0] < 2 && values[1] > maxSecondComponent) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Second oid component is invalid ");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Constructs an object ID from an array of integers. This
|
||||
* is used to construct constant object IDs.
|
||||
* Constructor, from an array of integers.
|
||||
* Validity check included.
|
||||
*/
|
||||
public ObjectIdentifier (int values []) throws IOException
|
||||
{
|
||||
checkValidOid(values, values.length);
|
||||
components = values.clone();
|
||||
componentLen = values.length;
|
||||
checkCount(values.length);
|
||||
checkFirstComponent(values[0]);
|
||||
checkSecondComponent(values[0], values[1]);
|
||||
for (int i=2; i<values.length; i++)
|
||||
checkOtherComponent(i, values[i]);
|
||||
init(values, values.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object ID from an ASN.1 encoded input stream.
|
||||
* Constructor, from an ASN.1 encoded input stream.
|
||||
* Validity check NOT included.
|
||||
* The encoding of the ID in the stream uses "DER", a BER/1 subset.
|
||||
* In this case, that means a triple { typeId, length, data }.
|
||||
*
|
||||
@ -152,8 +234,7 @@ class ObjectIdentifier implements Serializable
|
||||
* @param in DER-encoded data holding an object ID
|
||||
* @exception IOException indicates a decoding error
|
||||
*/
|
||||
public ObjectIdentifier (DerInputStream in)
|
||||
throws IOException
|
||||
public ObjectIdentifier (DerInputStream in) throws IOException
|
||||
{
|
||||
byte type_id;
|
||||
int bufferEnd;
|
||||
@ -174,215 +255,67 @@ class ObjectIdentifier implements Serializable
|
||||
+ " (tag = " + type_id + ")"
|
||||
);
|
||||
|
||||
bufferEnd = in.available () - in.getLength () - 1;
|
||||
if (bufferEnd < 0)
|
||||
throw new IOException (
|
||||
"ObjectIdentifier() -- not enough data");
|
||||
|
||||
initFromEncoding (in, bufferEnd);
|
||||
encoding = new byte[in.getLength()];
|
||||
in.getBytes(encoding);
|
||||
check(encoding);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the OID from the rest of a DER input buffer; the tag
|
||||
* and length have been removed/verified
|
||||
* Constructor, from the rest of a DER input buffer;
|
||||
* the tag and length have been removed/verified
|
||||
* Validity check NOT included.
|
||||
*/
|
||||
ObjectIdentifier (DerInputBuffer buf) throws IOException
|
||||
{
|
||||
initFromEncoding (new DerInputStream (buf), 0);
|
||||
DerInputStream in = new DerInputStream(buf);
|
||||
encoding = new byte[in.available()];
|
||||
in.getBytes(encoding);
|
||||
check(encoding);
|
||||
}
|
||||
|
||||
private void init(int[] components, int length) {
|
||||
int pos = 0;
|
||||
byte[] tmp = new byte[length*5+1]; // +1 for empty input
|
||||
|
||||
if (components[1] < Integer.MAX_VALUE - components[0]*40)
|
||||
pos += pack7Oid(components[0]*40+components[1], tmp, pos);
|
||||
else {
|
||||
BigInteger big = BigInteger.valueOf(components[1]);
|
||||
big = big.add(BigInteger.valueOf(components[0]*40));
|
||||
pos += pack7Oid(big, tmp, pos);
|
||||
}
|
||||
|
||||
for (int i=2; i<length; i++) {
|
||||
pos += pack7Oid(components[i], tmp, pos);
|
||||
}
|
||||
encoding = new byte[pos];
|
||||
System.arraycopy(tmp, 0, encoding, 0, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for use by newInternal(). Dummy argument
|
||||
* to avoid clash with the public constructor.
|
||||
*/
|
||||
private ObjectIdentifier(int[] components, boolean dummy) {
|
||||
this.components = components;
|
||||
this.componentLen = components.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ObjectIdentifier for internal use. The values are
|
||||
* This method is kept for compatibility reasons. The new implementation
|
||||
* does the check and conversion. All around the JDK, the method is called
|
||||
* in static blocks to initialize pre-defined ObjectIdentifieies. No
|
||||
* obvious performance hurt will be made after this change.
|
||||
*
|
||||
* Old doc: Create a new ObjectIdentifier for internal use. The values are
|
||||
* neither checked nor cloned.
|
||||
*/
|
||||
public static ObjectIdentifier newInternal(int[] values) {
|
||||
return new ObjectIdentifier(values, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function -- get the OID from a stream, after tag and
|
||||
* length are verified.
|
||||
*/
|
||||
private void initFromEncoding (DerInputStream in, int bufferEnd)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
/*
|
||||
* Now get the components ("sub IDs") one at a time. We fill a
|
||||
* temporary buffer, resizing it as needed.
|
||||
*/
|
||||
int component;
|
||||
boolean first_subid = true;
|
||||
|
||||
for (components = new int [allocationQuantum], componentLen = 0;
|
||||
in.available () > bufferEnd;
|
||||
) {
|
||||
component = getComponent (in);
|
||||
if (component < 0) {
|
||||
throw new IOException(
|
||||
"ObjectIdentifier() -- " +
|
||||
"component values must be nonnegative");
|
||||
}
|
||||
if (first_subid) {
|
||||
int X, Y;
|
||||
|
||||
/*
|
||||
* NOTE: the allocation quantum is large enough that we know
|
||||
* we don't have to reallocate here!
|
||||
*/
|
||||
if (component < 40)
|
||||
X = 0;
|
||||
else if (component < 80)
|
||||
X = 1;
|
||||
else
|
||||
X = 2;
|
||||
Y = component - ( X * 40);
|
||||
components [0] = X;
|
||||
components [1] = Y;
|
||||
componentLen = 2;
|
||||
|
||||
first_subid = false;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Other components are encoded less exotically. The only
|
||||
* potential trouble is the need to grow the array.
|
||||
*/
|
||||
if (componentLen >= components.length) {
|
||||
int tmp_components [];
|
||||
|
||||
tmp_components = new int [components.length
|
||||
+ allocationQuantum];
|
||||
System.arraycopy (components, 0, tmp_components, 0,
|
||||
components.length);
|
||||
components = tmp_components;
|
||||
}
|
||||
components [componentLen++] = component;
|
||||
}
|
||||
}
|
||||
|
||||
checkValidOid(components, componentLen);
|
||||
|
||||
/*
|
||||
* Final sanity check -- if we didn't use exactly the number of bytes
|
||||
* specified, something's quite wrong.
|
||||
*/
|
||||
if (in.available () != bufferEnd) {
|
||||
throw new IOException (
|
||||
"ObjectIdentifier() -- malformed input data");
|
||||
try {
|
||||
return new ObjectIdentifier(values);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
// Should not happen, internal calls always uses legal values.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* n.b. the only public interface is DerOutputStream.putOID()
|
||||
*/
|
||||
void encode (DerOutputStream out) throws IOException
|
||||
{
|
||||
DerOutputStream bytes = new DerOutputStream ();
|
||||
int i;
|
||||
|
||||
// According to ISO X.660, when the 1st component is 0 or 1, the 2nd
|
||||
// component is restricted to be less than or equal to 39, thus make
|
||||
// it small enough to be encoded into one single byte.
|
||||
if (components[0] < 2) {
|
||||
bytes.write ((components [0] * 40) + components [1]);
|
||||
} else {
|
||||
putComponent(bytes, (components [0] * 40) + components [1]);
|
||||
}
|
||||
for (i = 2; i < componentLen; i++)
|
||||
putComponent (bytes, components [i]);
|
||||
|
||||
/*
|
||||
* Now that we've constructed the component, encode
|
||||
* it in the stream we were given.
|
||||
*/
|
||||
out.write (DerValue.tag_ObjectId, bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tricky OID component parsing technique ... note that one bit
|
||||
* per octet is lost, this returns at most 28 bits of component.
|
||||
* Also, notice this parses in big-endian format.
|
||||
*/
|
||||
private static int getComponent (DerInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
int retval, i, tmp;
|
||||
|
||||
for (i = 0, retval = 0; i < 4; i++) {
|
||||
retval <<= 7;
|
||||
tmp = in.getByte ();
|
||||
retval |= (tmp & 0x07f);
|
||||
if ((tmp & 0x080) == 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
throw new IOException ("ObjectIdentifier() -- component value too big");
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse of the above routine. Notice it needs to emit in
|
||||
* big-endian form, so it buffers the output until it's ready.
|
||||
* (Minimum length encoding is a DER requirement.)
|
||||
*/
|
||||
private static void putComponent (DerOutputStream out, int val)
|
||||
throws IOException
|
||||
{
|
||||
int i;
|
||||
// TODO: val must be <128*128*128*128 here, otherwise, 4 bytes is not
|
||||
// enough to hold it. Will address this later.
|
||||
byte buf [] = new byte [4] ;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
buf [i] = (byte) (val & 0x07f);
|
||||
val >>>= 7;
|
||||
if (val == 0)
|
||||
break;
|
||||
}
|
||||
for ( ; i > 0; --i)
|
||||
out.write (buf [i] | 0x080);
|
||||
out.write (buf [0]);
|
||||
}
|
||||
|
||||
// XXX this API should probably facilitate the JDK sort utility
|
||||
|
||||
/**
|
||||
* Compares this identifier with another, for sorting purposes.
|
||||
* An identifier does not precede itself.
|
||||
*
|
||||
* @param other identifer that may precede this one.
|
||||
* @return true iff <em>other</em> precedes this one
|
||||
* in a particular sorting order.
|
||||
*/
|
||||
public boolean precedes (ObjectIdentifier other)
|
||||
{
|
||||
int i;
|
||||
|
||||
// shorter IDs go first
|
||||
if (other == this || componentLen < other.componentLen)
|
||||
return false;
|
||||
if (other.componentLen < componentLen)
|
||||
return true;
|
||||
|
||||
// for each component, the lesser component goes first
|
||||
for (i = 0; i < componentLen; i++) {
|
||||
if (other.components [i] < components [i])
|
||||
return true;
|
||||
}
|
||||
|
||||
// identical IDs don't precede each other
|
||||
return false;
|
||||
out.write (DerValue.tag_ObjectId, encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
|
||||
*
|
||||
* @return true iff the names are identical.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
|
||||
return false;
|
||||
}
|
||||
ObjectIdentifier other = (ObjectIdentifier)obj;
|
||||
if (componentLen != other.componentLen) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < componentLen; i++) {
|
||||
if (components[i] != other.components[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return Arrays.equals(encoding, other.encoding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = componentLen;
|
||||
for (int i = 0; i < componentLen; i++) {
|
||||
h += components[i] * 37;
|
||||
return Arrays.hashCode(encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method for serialization. To be compatible with old
|
||||
* versions of JDK.
|
||||
* @return components in an int array, if all the components are less than
|
||||
* Integer.MAX_VALUE. Otherwise, null.
|
||||
*/
|
||||
private int[] toIntArray() {
|
||||
int length = encoding.length;
|
||||
int[] result = new int[20];
|
||||
int which = 0;
|
||||
int fromPos = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if ((encoding[i] & 0x80) == 0) {
|
||||
// one section [fromPos..i]
|
||||
if (i - fromPos + 1 > 4) {
|
||||
BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
|
||||
if (fromPos == 0) {
|
||||
result[which++] = 2;
|
||||
BigInteger second = big.subtract(BigInteger.valueOf(80));
|
||||
if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
|
||||
return null;
|
||||
} else {
|
||||
result[which++] = second.intValue();
|
||||
}
|
||||
} else {
|
||||
if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
|
||||
return null;
|
||||
} else {
|
||||
result[which++] = big.intValue();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int retval = 0;
|
||||
for (int j = fromPos; j <= i; j++) {
|
||||
retval <<= 7;
|
||||
byte tmp = encoding[j];
|
||||
retval |= (tmp & 0x07f);
|
||||
}
|
||||
if (fromPos == 0) {
|
||||
if (retval < 80) {
|
||||
result[which++] = retval / 40;
|
||||
result[which++] = retval % 40;
|
||||
} else {
|
||||
result[which++] = 2;
|
||||
result[which++] = retval - 80;
|
||||
}
|
||||
} else {
|
||||
result[which++] = retval;
|
||||
}
|
||||
}
|
||||
fromPos = i+1;
|
||||
}
|
||||
if (which >= result.length) {
|
||||
result = Arrays.copyOf(result, which + 10);
|
||||
}
|
||||
}
|
||||
return h;
|
||||
return Arrays.copyOf(result, which);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,15 +413,52 @@ class ObjectIdentifier implements Serializable
|
||||
* user-friendly descriptive strings, since those strings
|
||||
* will not be understood everywhere.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String s = stringForm;
|
||||
if (s == null) {
|
||||
StringBuffer sb = new StringBuffer(componentLen * 4);
|
||||
for (int i = 0; i < componentLen; i++) {
|
||||
if (i != 0) {
|
||||
sb.append('.');
|
||||
int length = encoding.length;
|
||||
StringBuffer sb = new StringBuffer(length * 4);
|
||||
|
||||
int fromPos = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if ((encoding[i] & 0x80) == 0) {
|
||||
// one section [fromPos..i]
|
||||
if (fromPos != 0) { // not the first segment
|
||||
sb.append('.');
|
||||
}
|
||||
if (i - fromPos + 1 > 4) { // maybe big integer
|
||||
BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
|
||||
if (fromPos == 0) {
|
||||
// first section encoded with more than 4 bytes,
|
||||
// must be 2.something
|
||||
sb.append("2.");
|
||||
sb.append(big.subtract(BigInteger.valueOf(80)));
|
||||
} else {
|
||||
sb.append(big);
|
||||
}
|
||||
} else { // small integer
|
||||
int retval = 0;
|
||||
for (int j = fromPos; j <= i; j++) {
|
||||
retval <<= 7;
|
||||
byte tmp = encoding[j];
|
||||
retval |= (tmp & 0x07f);
|
||||
}
|
||||
if (fromPos == 0) {
|
||||
if (retval < 80) {
|
||||
sb.append(retval/40);
|
||||
sb.append('.');
|
||||
sb.append(retval%40);
|
||||
} else {
|
||||
sb.append("2.");
|
||||
sb.append(retval - 80);
|
||||
}
|
||||
} else {
|
||||
sb.append(retval);
|
||||
}
|
||||
}
|
||||
fromPos = i+1;
|
||||
}
|
||||
sb.append(components[i]);
|
||||
}
|
||||
s = sb.toString();
|
||||
stringForm = s;
|
||||
@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* To simplify, we assume no individual component of an object ID is
|
||||
* larger than 32 bits. Then we represent the path from the root as
|
||||
* an array that's (usually) only filled at the beginning.
|
||||
/**
|
||||
* Repack all bits from input to output. On the both sides, only a portion
|
||||
* (from the least significant bit) of the 8 bits in a byte is used. This
|
||||
* number is defined as the number of useful bits (NUB) for the array. All the
|
||||
* used bits from the input byte array and repacked into the output in the
|
||||
* exactly same order. The output bits are aligned so that the final bit of
|
||||
* the input (the least significant bit in the last byte), when repacked as
|
||||
* the final bit of the output, is still at the least significant position.
|
||||
* Zeroes will be padded on the left side of the first output byte if
|
||||
* necessary. All unused bits in the output are also zeroed.
|
||||
*
|
||||
* For example: if the input is 01001100 with NUB 8, the output which
|
||||
* has a NUB 6 will look like:
|
||||
* 00000001 00001100
|
||||
* The first 2 bits of the output bytes are unused bits. The other bits
|
||||
* turn out to be 000001 001100. While the 8 bits on the right are from
|
||||
* the input, the left 4 zeroes are padded to fill the 6 bits space.
|
||||
*
|
||||
* @param in the input byte array
|
||||
* @param ioffset start point inside <code>in</code>
|
||||
* @param ilength number of bytes to repack
|
||||
* @param iw NUB for input
|
||||
* @param ow NUB for output
|
||||
* @return the repacked bytes
|
||||
*/
|
||||
private int components []; // path from root
|
||||
private int componentLen; // how much is used.
|
||||
private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) {
|
||||
assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8";
|
||||
assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8";
|
||||
|
||||
private transient volatile String stringForm;
|
||||
if (iw == ow) {
|
||||
return in.clone();
|
||||
}
|
||||
|
||||
private static final int allocationQuantum = 5; // >= 2
|
||||
int bits = ilength * iw; // number of all used bits
|
||||
byte[] out = new byte[(bits+ow-1)/ow];
|
||||
|
||||
// starting from the 0th bit in the input
|
||||
int ipos = 0;
|
||||
|
||||
// the number of padding 0's needed in the output, skip them
|
||||
int opos = (bits+ow-1)/ow*ow-bits;
|
||||
|
||||
while(ipos < bits) {
|
||||
int count = iw - ipos%iw; // unpacked bits in current input byte
|
||||
if (count > ow - opos%ow) { // free space available in output byte
|
||||
count = ow - opos%ow; // choose the smaller number
|
||||
}
|
||||
// and move them!
|
||||
out[opos/ow] |= // paste!
|
||||
(((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative)
|
||||
>> (iw-ipos%iw-count)) // move to the end of a byte
|
||||
& ((1 << (count))-1)) // zero out all other bits
|
||||
<< (ow-opos%ow-count); // move to the output position
|
||||
ipos += count; // advance
|
||||
opos += count; // advance
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all
|
||||
* unnecessary 0 headings, set the first bit of all non-tail
|
||||
* output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and
|
||||
* paste it into an existing byte array.
|
||||
* @param out the existing array to be pasted into
|
||||
* @param ooffset the starting position to paste
|
||||
* @return the number of bytes pasted
|
||||
*/
|
||||
private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
|
||||
byte[] pack = pack(in, ioffset, ilength, 8, 7);
|
||||
int firstNonZero = pack.length-1; // paste at least one byte
|
||||
for (int i=pack.length-2; i>=0; i--) {
|
||||
if (pack[i] != 0) {
|
||||
firstNonZero = i;
|
||||
}
|
||||
pack[i] |= 0x80;
|
||||
}
|
||||
System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
|
||||
return pack.length-firstNonZero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repack from NUB 7 to NUB 8, remove all unnecessary 0
|
||||
* headings, and paste it into an existing byte array.
|
||||
* @param out the existing array to be pasted into
|
||||
* @param ooffset the starting position to paste
|
||||
* @return the number of bytes pasted
|
||||
*/
|
||||
private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
|
||||
byte[] pack = pack(in, ioffset, ilength, 7, 8);
|
||||
int firstNonZero = pack.length-1; // paste at least one byte
|
||||
for (int i=pack.length-2; i>=0; i--) {
|
||||
if (pack[i] != 0) {
|
||||
firstNonZero = i;
|
||||
}
|
||||
}
|
||||
System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
|
||||
return pack.length-firstNonZero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack the int into a OID sub-identifier DER encoding
|
||||
*/
|
||||
private static int pack7Oid(int input, byte[] out, int ooffset) {
|
||||
byte[] b = new byte[4];
|
||||
b[0] = (byte)(input >> 24);
|
||||
b[1] = (byte)(input >> 16);
|
||||
b[2] = (byte)(input >> 8);
|
||||
b[3] = (byte)(input);
|
||||
return pack7Oid(b, 0, 4, out, ooffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack the BigInteger into a OID subidentifier DER encoding
|
||||
*/
|
||||
private static int pack7Oid(BigInteger input, byte[] out, int ooffset) {
|
||||
byte[] b = input.toByteArray();
|
||||
return pack7Oid(b, 0, b.length, out, ooffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private methods to check validity of OID. They must be --
|
||||
* 1. at least 2 components
|
||||
* 2. all components must be non-negative
|
||||
* 3. the first must be 0, 1 or 2
|
||||
* 4. if the first is 0 or 1, the second must be <40
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check the DER encoding. Since DER encoding defines that the integer bits
|
||||
* are unsigned, so there's no need to check the MSB.
|
||||
*/
|
||||
private static void check(byte[] encoding) throws IOException {
|
||||
int length = encoding.length;
|
||||
if (length < 1 || // too short
|
||||
(encoding[length - 1] & 0x80) != 0) { // not ended
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Invalid DER encoding, not ended");
|
||||
}
|
||||
for (int i=0; i<length; i++) {
|
||||
// 0x80 at the beginning of a subidentifier
|
||||
if (encoding[i] == (byte)0x80 &&
|
||||
(i==0 || (encoding[i-1] & 0x80) == 0)) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Invalid DER encoding, useless extra octet detected");
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void checkCount(int count) throws IOException {
|
||||
if (count < 2) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Must be at least two oid components ");
|
||||
}
|
||||
}
|
||||
private static void checkFirstComponent(int first) throws IOException {
|
||||
if (first < 0 || first > 2) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"First oid component is invalid ");
|
||||
}
|
||||
}
|
||||
private static void checkFirstComponent(BigInteger first) throws IOException {
|
||||
if (first.signum() == -1 ||
|
||||
first.compareTo(BigInteger.valueOf(2)) == 1) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"First oid component is invalid ");
|
||||
}
|
||||
}
|
||||
private static void checkSecondComponent(int first, int second) throws IOException {
|
||||
if (second < 0 || first != 2 && second > 39) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Second oid component is invalid ");
|
||||
}
|
||||
}
|
||||
private static void checkSecondComponent(int first, BigInteger second) throws IOException {
|
||||
if (second.signum() == -1 ||
|
||||
first != 2 &&
|
||||
second.compareTo(BigInteger.valueOf(39)) == 1) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"Second oid component is invalid ");
|
||||
}
|
||||
}
|
||||
private static void checkOtherComponent(int i, int num) throws IOException {
|
||||
if (num < 0) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"oid component #" + (i+1) + " must be non-negative ");
|
||||
}
|
||||
}
|
||||
private static void checkOtherComponent(int i, BigInteger num) throws IOException {
|
||||
if (num.signum() == -1) {
|
||||
throw new IOException("ObjectIdentifier() -- " +
|
||||
"oid component #" + (i+1) + " must be non-negative ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
# passwords. To be functional, a role must have an entry in
|
||||
# both the password and the access files.
|
||||
#
|
||||
# Default location of this file is $JRE/lib/management/jmxremote.access
|
||||
# The default location of this file is $JRE/lib/management/jmxremote.access
|
||||
# You can specify an alternate location by specifying a property in
|
||||
# the management config file $JRE/lib/management/management.properties
|
||||
# (See that file for details)
|
||||
@ -16,7 +16,7 @@
|
||||
# The file format for password and access files is syntactically the same
|
||||
# as the Properties file format. The syntax is described in the Javadoc
|
||||
# for java.util.Properties.load.
|
||||
# Typical access file has multiple lines, where each line is blank,
|
||||
# A typical access file has multiple lines, where each line is blank,
|
||||
# a comment (like this one), or an access control entry.
|
||||
#
|
||||
# An access control entry consists of a role name, and an
|
||||
@ -29,10 +29,38 @@
|
||||
# role can read measurements but cannot perform any action
|
||||
# that changes the environment of the running program.
|
||||
# "readwrite" grants access to read and write attributes of MBeans,
|
||||
# to invoke operations on them, and to create or remove them.
|
||||
# This access should be granted to only trusted clients,
|
||||
# since they can potentially interfere with the smooth
|
||||
# operation of a running program
|
||||
# to invoke operations on them, and optionally
|
||||
# to create or remove them. This access should be granted
|
||||
# only to trusted clients, since they can potentially
|
||||
# interfere with the smooth operation of a running program.
|
||||
#
|
||||
# The "readwrite" access level can optionally be followed by the "create" and/or
|
||||
# "unregister" keywords. The "unregister" keyword grants access to unregister
|
||||
# (delete) MBeans. The "create" keyword grants access to create MBeans of a
|
||||
# particular class or of any class matching a particular pattern. Access
|
||||
# should only be granted to create MBeans of known and trusted classes.
|
||||
#
|
||||
# For example, the following entry would grant readwrite access
|
||||
# to "controlRole", as well as access to create MBeans of the class
|
||||
# javax.management.monitor.CounterMonitor and to unregister any MBean:
|
||||
# controlRole readwrite \
|
||||
# create javax.management.monitor.CounterMonitorMBean \
|
||||
# unregister
|
||||
# or equivalently:
|
||||
# controlRole readwrite unregister create javax.management.monitor.CounterMBean
|
||||
#
|
||||
# The following entry would grant readwrite access as well as access to create
|
||||
# MBeans of any class in the packages javax.management.monitor and
|
||||
# javax.management.timer:
|
||||
# controlRole readwrite \
|
||||
# create javax.management.monitor.*,javax.management.timer.* \
|
||||
# unregister
|
||||
#
|
||||
# The \ character is defined in the Properties file syntax to allow continuation
|
||||
# lines as shown here. A * in a class pattern matches a sequence of characters
|
||||
# other than dot (.), so javax.management.monitor.* matches
|
||||
# javax.management.monitor.CounterMonitor but not
|
||||
# javax.management.monitor.foo.Bar.
|
||||
#
|
||||
# A given role should have at most one entry in this file. If a role
|
||||
# has no entry, it has no access.
|
||||
@ -42,7 +70,10 @@
|
||||
#
|
||||
# Default access control entries:
|
||||
# o The "monitorRole" role has readonly access.
|
||||
# o The "controlRole" role has readwrite access.
|
||||
# o The "controlRole" role has readwrite access and can create the standard
|
||||
# Timer and Monitor MBeans defined by the JMX API.
|
||||
|
||||
monitorRole readonly
|
||||
controlRole readwrite
|
||||
controlRole readwrite \
|
||||
create javax.management.monitor.*,javax.management.timer.* \
|
||||
unregister
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -94,6 +94,7 @@ void band::readData(int expectedLength) {
|
||||
assert(!valc->isMalloc);
|
||||
}
|
||||
xvs.init(u->rp, u->rplimit, valc);
|
||||
CHECK;
|
||||
int X = xvs.getInt();
|
||||
if (valc->S() != 0) {
|
||||
assert(valc->min <= -256);
|
||||
@ -117,6 +118,7 @@ void band::readData(int expectedLength) {
|
||||
byte XB_byte = (byte) XB;
|
||||
byte* XB_ptr = &XB_byte;
|
||||
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
|
||||
CHECK;
|
||||
} else {
|
||||
NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
|
||||
assert(u->meta_rp != null);
|
||||
@ -215,8 +217,19 @@ int band::getIntTotal() {
|
||||
if (length == 0) return 0;
|
||||
if (total_memo > 0) return total_memo-1;
|
||||
int total = getInt();
|
||||
// overflow checks require that none of the addends are <0,
|
||||
// and that the partial sums never overflow (wrap negative)
|
||||
if (total < 0) {
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
for (int k = length-1; k > 0; k--) {
|
||||
int prev_total = total;
|
||||
total += vs[0].getInt();
|
||||
if (total < prev_total) {
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rewind();
|
||||
total_memo = total+1;
|
||||
|
@ -56,7 +56,7 @@ void bytes::realloc(size_t len_) {
|
||||
return;
|
||||
}
|
||||
byte* oldptr = ptr;
|
||||
ptr = (byte*)::realloc(ptr, len_+1);
|
||||
ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, len_+1);
|
||||
if (ptr != null) {
|
||||
mtrace('r', oldptr, 0);
|
||||
mtrace('m', ptr, len_+1);
|
||||
@ -128,7 +128,7 @@ const char* bytes::string() {
|
||||
// Make sure there are 'o' bytes beyond the fill pointer,
|
||||
// advance the fill pointer, and return the old fill pointer.
|
||||
byte* fillbytes::grow(size_t s) {
|
||||
size_t nlen = b.len+s;
|
||||
size_t nlen = add_size(b.len, s);
|
||||
if (nlen <= allocated) {
|
||||
b.len = nlen;
|
||||
return limit()-s;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -814,6 +814,7 @@ void coding_method::init(byte* &band_rp, byte* band_limit,
|
||||
}
|
||||
band_rp = vs.rp;
|
||||
}
|
||||
CHECK;
|
||||
|
||||
// Get an accurate upper limit now.
|
||||
vs0.rplimit = band_rp;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,11 +47,13 @@
|
||||
#define NOT_PRODUCT(xxx)
|
||||
#define assert(p)
|
||||
#define PRINTCR(args)
|
||||
#define VERSION_STRING "%s version %s\n"
|
||||
#else
|
||||
#define IF_PRODUCT(xxx)
|
||||
#define NOT_PRODUCT(xxx) xxx
|
||||
#define assert(p) ((p) || assert_failed(#p))
|
||||
#define PRINTCR(args) u->verbose && u->printcr_if_verbose args
|
||||
#define VERSION_STRING "%s version non-product %s\n"
|
||||
extern "C" void breakpoint();
|
||||
extern int assert_failed(const char*);
|
||||
#define BREAK (breakpoint())
|
||||
@ -79,9 +81,9 @@ extern int assert_failed(const char*);
|
||||
|
||||
#define lengthof(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
#define NEW(T, n) (T*) must_malloc((int)(sizeof(T)*(n)))
|
||||
#define U_NEW(T, n) (T*) u->alloc(sizeof(T)*(n))
|
||||
#define T_NEW(T, n) (T*) u->temp_alloc(sizeof(T)*(n))
|
||||
#define NEW(T, n) (T*) must_malloc((int)(scale_size(n, sizeof(T))))
|
||||
#define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
|
||||
// bytes and byte arrays
|
||||
@ -153,6 +155,8 @@ enum { false, true };
|
||||
#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y)
|
||||
#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0)
|
||||
|
||||
#define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK
|
||||
|
||||
#define STR_TRUE "true"
|
||||
#define STR_FALSE "false"
|
||||
|
||||
|
@ -299,7 +299,7 @@ int unpacker::run(int argc, char **argv) {
|
||||
case 'J': argp += 1; break; // skip ignored -Jxxx parameter
|
||||
|
||||
case 'V':
|
||||
fprintf(u.errstrm, "%s version %s\n", nbasename(argv[0]), sccsver);
|
||||
fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver);
|
||||
exit(0);
|
||||
|
||||
case 'h':
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -523,15 +523,39 @@ void unpacker::read_file_header() {
|
||||
enum {
|
||||
MAGIC_BYTES = 4,
|
||||
AH_LENGTH_0 = 3, //minver, majver, options are outside of archive_size
|
||||
AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
|
||||
AH_LENGTH = 26, //maximum archive header length (w/ all fields)
|
||||
// Length contributions from optional header fields:
|
||||
AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
|
||||
AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
|
||||
AH_CP_NUMBER_LEN = 4, // int/float/long/double
|
||||
AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
|
||||
AH_LENGTH_MIN = AH_LENGTH
|
||||
-(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
|
||||
ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
|
||||
FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
|
||||
};
|
||||
|
||||
assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
|
||||
assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
|
||||
// An absolute minimum null archive is magic[4], {minver,majver,options}[3],
|
||||
// archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
|
||||
// (Note that archive_size is optional; it may be 0..10 bytes in length.)
|
||||
// The first read must capture everything up through the options field.
|
||||
// This happens to work even if {minver,majver,options} is a pathological
|
||||
// 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
|
||||
assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
|
||||
|
||||
// Up through archive_size, the largest possible archive header is
|
||||
// magic[4], {minver,majver,options}[4], archive_size[10].
|
||||
// (Note only the low 12 bits of options are allowed to be non-zero.)
|
||||
// In order to parse archive_size, we need at least this many bytes
|
||||
// in the first read. Of course, if archive_size_hi is more than
|
||||
// a byte, we probably will fail to allocate the buffer, since it
|
||||
// will be many gigabytes long. This is a practical, not an
|
||||
// architectural limit to Pack200 archive sizes.
|
||||
assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX);
|
||||
|
||||
bool foreign_buf = (read_input_fn == null);
|
||||
byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
|
||||
if (foreign_buf) {
|
||||
@ -547,7 +571,7 @@ void unpacker::read_file_header() {
|
||||
// There is no way to tell the caller that we used only part of them.
|
||||
// Therefore, the caller must use only a bare minimum of read-ahead.
|
||||
if (inbytes.len > FIRST_READ) {
|
||||
abort("too much pushback");
|
||||
abort("too much read-ahead");
|
||||
return;
|
||||
}
|
||||
input.set(initbuf, sizeof(initbuf));
|
||||
@ -557,7 +581,7 @@ void unpacker::read_file_header() {
|
||||
rplimit += inbytes.len;
|
||||
bytes_read += inbytes.len;
|
||||
}
|
||||
// Read only 19 bytes, which is certain to contain #archive_size fields,
|
||||
// Read only 19 bytes, which is certain to contain #archive_options fields,
|
||||
// but is certain not to overflow past the archive_header.
|
||||
input.b.len = FIRST_READ;
|
||||
if (!ensure_input(FIRST_READ))
|
||||
@ -629,26 +653,25 @@ void unpacker::read_file_header() {
|
||||
#undef ORBIT
|
||||
if ((archive_options & ~OPTION_LIMIT) != 0) {
|
||||
fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
|
||||
archive_options);
|
||||
// Do not abort. If the format really changes, version numbers will bump.
|
||||
//abort("illegal archive options");
|
||||
archive_options);
|
||||
abort("illegal archive options");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
|
||||
uint hi = hdr.getInt();
|
||||
uint lo = hdr.getInt();
|
||||
archive_size = band::makeLong(hi, lo);
|
||||
julong x = band::makeLong(hi, lo);
|
||||
archive_size = (size_t) x;
|
||||
if (archive_size != x) {
|
||||
// Silly size specified; force overflow.
|
||||
archive_size = PSIZE_MAX+1;
|
||||
}
|
||||
hdrVals += 2;
|
||||
} else {
|
||||
hdrValsSkipped += 2;
|
||||
}
|
||||
|
||||
if (archive_size != (size_t)archive_size) {
|
||||
// Silly size specified.
|
||||
abort("archive too large");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we can size the whole archive.
|
||||
// Read everything else into a mega-buffer.
|
||||
rp = hdr.rp;
|
||||
@ -662,9 +685,18 @@ void unpacker::read_file_header() {
|
||||
abort("EOF reading fixed input buffer");
|
||||
return;
|
||||
}
|
||||
} else if (archive_size > 0) {
|
||||
input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)),
|
||||
(size_t) header_size_0 + (size_t)archive_size);
|
||||
} else if (archive_size != 0) {
|
||||
if (archive_size < ARCHIVE_SIZE_MIN) {
|
||||
abort("impossible archive size"); // bad input data
|
||||
return;
|
||||
}
|
||||
if (archive_size < header_size_1) {
|
||||
abort("too much read-ahead"); // somehow we pre-fetched too much?
|
||||
return;
|
||||
}
|
||||
input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
|
||||
(size_t) header_size_0 + archive_size);
|
||||
CHECK;
|
||||
assert(input.limit()[0] == 0);
|
||||
// Move all the bytes we read initially into the real buffer.
|
||||
input.b.copyFrom(initbuf, header_size);
|
||||
@ -673,17 +705,17 @@ void unpacker::read_file_header() {
|
||||
} else {
|
||||
// It's more complicated and painful.
|
||||
// A zero archive_size means that we must read until EOF.
|
||||
assert(archive_size == 0);
|
||||
input.init(CHUNK*2);
|
||||
CHECK;
|
||||
input.b.len = input.allocated;
|
||||
rp = rplimit = input.base();
|
||||
// Set up input buffer as if we already read the header:
|
||||
input.b.copyFrom(initbuf, header_size);
|
||||
CHECK;
|
||||
rplimit += header_size;
|
||||
while (ensure_input(input.limit() - rp)) {
|
||||
size_t dataSoFar = input_remaining();
|
||||
size_t nextSize = dataSoFar + CHUNK;
|
||||
size_t nextSize = add_size(dataSoFar, CHUNK);
|
||||
input.ensureSize(nextSize);
|
||||
CHECK;
|
||||
input.b.len = input.allocated;
|
||||
@ -715,8 +747,10 @@ void unpacker::read_file_header() {
|
||||
|
||||
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
|
||||
archive_next_count = hdr.getInt();
|
||||
CHECK_COUNT(archive_next_count);
|
||||
archive_modtime = hdr.getInt();
|
||||
file_count = hdr.getInt();
|
||||
CHECK_COUNT(file_count);
|
||||
hdrVals += 3;
|
||||
} else {
|
||||
hdrValsSkipped += 3;
|
||||
@ -724,7 +758,9 @@ void unpacker::read_file_header() {
|
||||
|
||||
if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
|
||||
band_headers_size = hdr.getInt();
|
||||
CHECK_COUNT(band_headers_size);
|
||||
attr_definition_count = hdr.getInt();
|
||||
CHECK_COUNT(attr_definition_count);
|
||||
hdrVals += 2;
|
||||
} else {
|
||||
hdrValsSkipped += 2;
|
||||
@ -744,13 +780,16 @@ void unpacker::read_file_header() {
|
||||
}
|
||||
}
|
||||
cp_counts[k] = hdr.getInt();
|
||||
CHECK_COUNT(cp_counts[k]);
|
||||
hdrVals += 1;
|
||||
}
|
||||
|
||||
ic_count = hdr.getInt();
|
||||
CHECK_COUNT(ic_count);
|
||||
default_class_minver = hdr.getInt();
|
||||
default_class_majver = hdr.getInt();
|
||||
class_count = hdr.getInt();
|
||||
CHECK_COUNT(class_count);
|
||||
hdrVals += 4;
|
||||
|
||||
// done with archive_header
|
||||
@ -807,7 +846,6 @@ void unpacker::read_file_header() {
|
||||
bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
|
||||
}
|
||||
|
||||
|
||||
void unpacker::finish() {
|
||||
if (verbose >= 1) {
|
||||
fprintf(errstrm,
|
||||
@ -973,12 +1011,12 @@ void unpacker::read_Utf8_values(entry* cpMap, int len) {
|
||||
// First band: Read lengths of shared prefixes.
|
||||
if (len > PREFIX_SKIP_2)
|
||||
cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
|
||||
NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
|
||||
NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
|
||||
|
||||
// Second band: Read lengths of unshared suffixes:
|
||||
if (len > SUFFIX_SKIP_1)
|
||||
cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
|
||||
NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
|
||||
NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
|
||||
|
||||
bytes* allsuffixes = T_NEW(bytes, len);
|
||||
CHECK;
|
||||
@ -2117,6 +2155,7 @@ void unpacker::read_classes() {
|
||||
|
||||
field_descr.readData(field_count);
|
||||
read_attrs(ATTR_CONTEXT_FIELD, field_count);
|
||||
CHECK;
|
||||
|
||||
method_descr.readData(method_count);
|
||||
read_attrs(ATTR_CONTEXT_METHOD, method_count);
|
||||
@ -2124,6 +2163,7 @@ void unpacker::read_classes() {
|
||||
CHECK;
|
||||
|
||||
read_attrs(ATTR_CONTEXT_CLASS, class_count);
|
||||
CHECK;
|
||||
|
||||
read_code_headers();
|
||||
|
||||
@ -2150,10 +2190,12 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
|
||||
if (haveLongFlags)
|
||||
xxx_flags_hi.readData(obj_count);
|
||||
CHECK;
|
||||
|
||||
band& xxx_flags_lo = ad.xxx_flags_lo();
|
||||
assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
|
||||
xxx_flags_lo.readData(obj_count);
|
||||
CHECK;
|
||||
|
||||
// pre-scan flags, counting occurrences of each index bit
|
||||
julong indexMask = ad.flagIndexMask(); // which flag bits are index bits?
|
||||
@ -2176,11 +2218,13 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
assert(endsWith(xxx_attr_count.name, "_attr_count"));
|
||||
// There is one count element for each 1<<16 bit set in flags:
|
||||
xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
|
||||
CHECK;
|
||||
|
||||
band& xxx_attr_indexes = ad.xxx_attr_indexes();
|
||||
assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
|
||||
int overflowIndexCount = xxx_attr_count.getIntTotal();
|
||||
xxx_attr_indexes.readData(overflowIndexCount);
|
||||
CHECK;
|
||||
// pre-scan attr indexes, counting occurrences of each value
|
||||
for (i = 0; i < overflowIndexCount; i++) {
|
||||
idx = xxx_attr_indexes.getInt();
|
||||
@ -2211,6 +2255,7 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
}
|
||||
}
|
||||
ad.xxx_attr_calls().readData(backwardCounts);
|
||||
CHECK;
|
||||
|
||||
// Read built-in bands.
|
||||
// Mostly, these are hand-coded equivalents to readBandData().
|
||||
@ -2219,42 +2264,53 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
|
||||
count = ad.predefCount(CLASS_ATTR_SourceFile);
|
||||
class_SourceFile_RUN.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
|
||||
class_EnclosingMethod_RC.readData(count);
|
||||
class_EnclosingMethod_RDN.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = ad.predefCount(X_ATTR_Signature);
|
||||
class_Signature_RS.readData(count);
|
||||
CHECK;
|
||||
|
||||
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
|
||||
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
|
||||
|
||||
count = ad.predefCount(CLASS_ATTR_InnerClasses);
|
||||
class_InnerClasses_N.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = class_InnerClasses_N.getIntTotal();
|
||||
class_InnerClasses_RC.readData(count);
|
||||
class_InnerClasses_F.readData(count);
|
||||
CHECK;
|
||||
// Drop remaining columns wherever flags are zero:
|
||||
count -= class_InnerClasses_F.getIntCount(0);
|
||||
class_InnerClasses_outer_RCN.readData(count);
|
||||
class_InnerClasses_name_RUN.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = ad.predefCount(CLASS_ATTR_ClassFile_version);
|
||||
class_ClassFile_version_minor_H.readData(count);
|
||||
class_ClassFile_version_major_H.readData(count);
|
||||
CHECK;
|
||||
break;
|
||||
|
||||
case ATTR_CONTEXT_FIELD:
|
||||
|
||||
count = ad.predefCount(FIELD_ATTR_ConstantValue);
|
||||
field_ConstantValue_KQ.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = ad.predefCount(X_ATTR_Signature);
|
||||
field_Signature_RS.readData(count);
|
||||
CHECK;
|
||||
|
||||
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
|
||||
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
|
||||
CHECK;
|
||||
break;
|
||||
|
||||
case ATTR_CONTEXT_METHOD:
|
||||
@ -2266,15 +2322,18 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
method_Exceptions_N.readData(count);
|
||||
count = method_Exceptions_N.getIntTotal();
|
||||
method_Exceptions_RC.readData(count);
|
||||
CHECK;
|
||||
|
||||
count = ad.predefCount(X_ATTR_Signature);
|
||||
method_Signature_RS.readData(count);
|
||||
CHECK;
|
||||
|
||||
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
|
||||
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
|
||||
ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
|
||||
ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
|
||||
ad.readBandData(METHOD_ATTR_AnnotationDefault);
|
||||
CHECK;
|
||||
break;
|
||||
|
||||
case ATTR_CONTEXT_CODE:
|
||||
@ -2286,8 +2345,10 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
return;
|
||||
}
|
||||
code_StackMapTable_N.readData(count);
|
||||
CHECK;
|
||||
count = code_StackMapTable_N.getIntTotal();
|
||||
code_StackMapTable_frame_T.readData(count);
|
||||
CHECK;
|
||||
// the rest of it depends in a complicated way on frame tags
|
||||
{
|
||||
int fat_frame_count = 0;
|
||||
@ -2321,18 +2382,23 @@ void unpacker::read_attrs(int attrc, int obj_count) {
|
||||
// deal completely with fat frames:
|
||||
offset_count += fat_frame_count;
|
||||
code_StackMapTable_local_N.readData(fat_frame_count);
|
||||
CHECK;
|
||||
type_count += code_StackMapTable_local_N.getIntTotal();
|
||||
code_StackMapTable_stack_N.readData(fat_frame_count);
|
||||
type_count += code_StackMapTable_stack_N.getIntTotal();
|
||||
CHECK;
|
||||
// read the rest:
|
||||
code_StackMapTable_offset.readData(offset_count);
|
||||
code_StackMapTable_T.readData(type_count);
|
||||
CHECK;
|
||||
// (7) [RCH]
|
||||
count = code_StackMapTable_T.getIntCount(7);
|
||||
code_StackMapTable_RC.readData(count);
|
||||
CHECK;
|
||||
// (8) [PH]
|
||||
count = code_StackMapTable_T.getIntCount(8);
|
||||
code_StackMapTable_P.readData(count);
|
||||
CHECK;
|
||||
}
|
||||
|
||||
count = ad.predefCount(CODE_ATTR_LineNumberTable);
|
||||
@ -2654,6 +2720,7 @@ void unpacker::read_code_headers() {
|
||||
code_max_na_locals.readData();
|
||||
code_handler_count.readData();
|
||||
totalHandlerCount += code_handler_count.getIntTotal();
|
||||
CHECK;
|
||||
|
||||
// Read handler specifications.
|
||||
// Cf. PackageReader.readCodeHandlers.
|
||||
@ -2661,8 +2728,10 @@ void unpacker::read_code_headers() {
|
||||
code_handler_end_PO.readData(totalHandlerCount);
|
||||
code_handler_catch_PO.readData(totalHandlerCount);
|
||||
code_handler_class_RCN.readData(totalHandlerCount);
|
||||
CHECK;
|
||||
|
||||
read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
|
||||
CHECK;
|
||||
}
|
||||
|
||||
static inline bool is_in_range(uint n, uint min, uint max) {
|
||||
|
@ -204,7 +204,7 @@ struct unpacker {
|
||||
|
||||
// archive header fields
|
||||
int magic, minver, majver;
|
||||
julong archive_size;
|
||||
size_t archive_size;
|
||||
int archive_next_count, archive_options, archive_modtime;
|
||||
int band_headers_size;
|
||||
int file_count, attr_definition_count, ic_count, class_count;
|
||||
|
@ -46,14 +46,13 @@
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
void* must_malloc(int size) {
|
||||
int msize = size;
|
||||
assert(size >= 0);
|
||||
void* must_malloc(size_t size) {
|
||||
size_t msize = size;
|
||||
#ifdef USE_MTRACE
|
||||
if (msize < sizeof(int))
|
||||
if (msize >= 0 && msize < sizeof(int))
|
||||
msize = sizeof(int); // see 0xbaadf00d below
|
||||
#endif
|
||||
void* ptr = malloc(msize);
|
||||
void* ptr = (msize > PSIZE_MAX) ? null : malloc(msize);
|
||||
if (ptr != null) {
|
||||
memset(ptr, 0, size);
|
||||
} else {
|
||||
|
@ -25,13 +25,31 @@
|
||||
|
||||
//Definitions of our util functions
|
||||
|
||||
void* must_malloc(int size);
|
||||
void* must_malloc(size_t size);
|
||||
#ifndef USE_MTRACE
|
||||
#define mtrace(c, ptr, size)
|
||||
#else
|
||||
void mtrace(char c, void* ptr, size_t size);
|
||||
#endif
|
||||
|
||||
// overflow management
|
||||
#define OVERFLOW ((size_t)-1)
|
||||
#define PSIZE_MAX (OVERFLOW/2) /* normal size limit */
|
||||
|
||||
inline size_t scale_size(size_t size, size_t scale) {
|
||||
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2) {
|
||||
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
|
||||
? OVERFLOW
|
||||
: size1 + size2;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2, int size3) {
|
||||
return add_size(add_size(size1, size2), size3);
|
||||
}
|
||||
|
||||
// These may be expensive, because they have to go via Java TSD,
|
||||
// if the optional u argument is missing.
|
||||
struct unpacker;
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Native method support for java.util.zip.ZipEntry
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jlong.h"
|
||||
#include "jvm.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "zip_util.h"
|
||||
|
||||
#include "java_util_zip_ZipEntry.h"
|
||||
|
||||
#define DEFLATED 8
|
||||
#define STORED 0
|
||||
|
||||
static jfieldID nameID;
|
||||
static jfieldID timeID;
|
||||
static jfieldID crcID;
|
||||
static jfieldID sizeID;
|
||||
static jfieldID csizeID;
|
||||
static jfieldID methodID;
|
||||
static jfieldID extraID;
|
||||
static jfieldID commentID;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_ZipEntry_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
|
||||
timeID = (*env)->GetFieldID(env, cls, "time", "J");
|
||||
crcID = (*env)->GetFieldID(env, cls, "crc", "J");
|
||||
sizeID = (*env)->GetFieldID(env, cls, "size", "J");
|
||||
csizeID = (*env)->GetFieldID(env, cls, "csize", "J");
|
||||
methodID = (*env)->GetFieldID(env, cls, "method", "I");
|
||||
extraID = (*env)->GetFieldID(env, cls, "extra", "[B");
|
||||
commentID = (*env)->GetFieldID(env, cls, "comment", "Ljava/lang/String;");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_ZipEntry_initFields(JNIEnv *env, jobject obj, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
jstring name = (*env)->GetObjectField(env, obj, nameID);
|
||||
|
||||
if (name == 0) {
|
||||
name = (*env)->NewStringUTF(env, ze->name);
|
||||
if (name == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetObjectField(env, obj, nameID, name);
|
||||
}
|
||||
(*env)->SetLongField(env, obj, timeID, (jlong)ze->time & 0xffffffffUL);
|
||||
(*env)->SetLongField(env, obj, crcID, (jlong)ze->crc & 0xffffffffUL);
|
||||
(*env)->SetLongField(env, obj, sizeID, (jlong)ze->size);
|
||||
if (ze->csize == 0) {
|
||||
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->size);
|
||||
(*env)->SetIntField(env, obj, methodID, STORED);
|
||||
} else {
|
||||
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->csize);
|
||||
(*env)->SetIntField(env, obj, methodID, DEFLATED);
|
||||
}
|
||||
if (ze->extra != 0) {
|
||||
unsigned char *bp = (unsigned char *)&ze->extra[0];
|
||||
jsize len = (bp[0] | (bp[1] << 8));
|
||||
jbyteArray extra = (*env)->NewByteArray(env, len);
|
||||
if (extra == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, extra, 0, len, &ze->extra[2]);
|
||||
(*env)->SetObjectField(env, obj, extraID, extra);
|
||||
}
|
||||
if (ze->comment != 0) {
|
||||
jstring comment = (*env)->NewStringUTF(env, ze->comment);
|
||||
if (comment == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetObjectField(env, obj, commentID, comment);
|
||||
}
|
||||
}
|
@ -141,12 +141,11 @@ Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jstring name, jboolean addSlash)
|
||||
jbyteArray name, jboolean addSlash)
|
||||
{
|
||||
#define MAXNAME 1024
|
||||
jzfile *zip = jlong_to_ptr(zfile);
|
||||
jsize slen = (*env)->GetStringLength(env, name);
|
||||
jsize ulen = (*env)->GetStringUTFLength(env, name);
|
||||
jsize ulen = (*env)->GetArrayLength(env, name);
|
||||
char buf[MAXNAME+2], *path;
|
||||
jzentry *ze;
|
||||
|
||||
@ -159,7 +158,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
} else {
|
||||
path = buf;
|
||||
}
|
||||
(*env)->GetStringUTFRegion(env, name, 0, slen, path);
|
||||
(*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
|
||||
path[ulen] = '\0';
|
||||
if (addSlash == JNI_FALSE) {
|
||||
ze = ZIP_GetEntry(zip, path, 0);
|
||||
@ -186,34 +185,87 @@ Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jint n)
|
||||
{
|
||||
jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
|
||||
|
||||
return ptr_to_jlong(ze);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_getMethod(JNIEnv *env, jclass cls, jlong zentry)
|
||||
Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
|
||||
return ze->csize != 0 ? DEFLATED : STORED;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getCSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return ze->flag;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return ze->csize != 0 ? ze->csize : ze->size;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
|
||||
return ze->size;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return (jlong)ze->time & 0xffffffffUL;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return (jlong)ze->crc & 0xffffffffUL;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, jclass cls, jlong zentry, jint type)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
int len = 0;
|
||||
jbyteArray jba = NULL;
|
||||
switch (type) {
|
||||
case java_util_zip_ZipFile_JZENTRY_NAME:
|
||||
if (ze->name != 0) {
|
||||
len = (int)strlen(ze->name);
|
||||
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
|
||||
}
|
||||
break;
|
||||
case java_util_zip_ZipFile_JZENTRY_EXTRA:
|
||||
if (ze->extra != 0) {
|
||||
unsigned char *bp = (unsigned char *)&ze->extra[0];
|
||||
len = (bp[0] | (bp[1] << 8));
|
||||
if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
|
||||
}
|
||||
break;
|
||||
case java_util_zip_ZipFile_JZENTRY_COMMENT:
|
||||
if (ze->comment != 0) {
|
||||
len = (int)strlen(ze->comment);
|
||||
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return jba;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jlong zentry, jlong pos, jbyteArray bytes,
|
||||
|
@ -512,7 +512,6 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
|
||||
/* Clear previous zip error */
|
||||
zip->msg = NULL;
|
||||
|
||||
/* Get position of END header */
|
||||
if ((endpos = findEND(zip, endbuf)) == -1)
|
||||
return -1; /* no END header or system error */
|
||||
@ -520,7 +519,6 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
if (endpos == 0) return 0; /* only END header present */
|
||||
|
||||
freeCEN(zip);
|
||||
|
||||
/* Get position and length of central directory */
|
||||
cenlen = ENDSIZ(endbuf);
|
||||
cenoff = ENDOFF(endbuf);
|
||||
@ -935,6 +933,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
|
||||
ze->crc = CENCRC(cen);
|
||||
locoff = CENOFF(cen);
|
||||
ze->pos = -(zip->locpos + locoff);
|
||||
ze->flag = CENFLG(cen);
|
||||
|
||||
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
|
||||
memcpy(ze->name, cen + CENHDR, nlen);
|
||||
|
@ -168,6 +168,7 @@ typedef struct jzentry { /* Zip file entry */
|
||||
char *comment; /* optional zip file comment */
|
||||
jbyte *extra; /* optional extra data */
|
||||
jlong pos; /* position of LOC header or entry data */
|
||||
jint flag; /* general purpose flag */
|
||||
} jzentry;
|
||||
|
||||
/*
|
||||
|
@ -722,6 +722,10 @@ DGifSetupDecompress(GifFileType * GifFile) {
|
||||
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
|
||||
|
||||
READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
|
||||
if (CodeSize >= 12) {
|
||||
/* Invalid initial code size: report failure */
|
||||
return GIF_ERROR;
|
||||
}
|
||||
BitsPerPixel = CodeSize;
|
||||
|
||||
Private->Buf[0] = 0; /* Input Buffer empty. */
|
||||
@ -964,10 +968,13 @@ DGifDecompressInput(GifFileType * GifFile,
|
||||
|
||||
/* If code cannot fit into RunningBits bits, must raise its size. Note
|
||||
* however that codes above 4095 are used for special signaling. */
|
||||
if (++Private->RunningCode > Private->MaxCode1 &&
|
||||
Private->RunningBits < LZ_BITS) {
|
||||
Private->MaxCode1 <<= 1;
|
||||
Private->RunningBits++;
|
||||
if (++Private->RunningCode > Private->MaxCode1) {
|
||||
if (Private->RunningBits < LZ_BITS) {
|
||||
Private->MaxCode1 <<= 1;
|
||||
Private->RunningBits++;
|
||||
} else {
|
||||
Private->RunningCode = Private->MaxCode1;
|
||||
}
|
||||
}
|
||||
return GIF_OK;
|
||||
}
|
||||
|
@ -191,6 +191,11 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
|
||||
int passht = passinc;
|
||||
int len;
|
||||
|
||||
/* We have verified the initial code size on the java layer.
|
||||
* Here we just check bounds for particular indexes. */
|
||||
if (freeCode >= 4096 || maxCode >= 4096) {
|
||||
return 0;
|
||||
}
|
||||
if (blockh == 0 || raslineh == 0
|
||||
|| prefixh == 0 || suffixh == 0
|
||||
|| outCodeh == 0)
|
||||
|
@ -216,6 +216,16 @@ printMedialibError(int status) {
|
||||
|
||||
#endif /* ! DEBUG */
|
||||
|
||||
static int
|
||||
getMlibEdgeHint(jint edgeHint) {
|
||||
switch (edgeHint) {
|
||||
case java_awt_image_ConvolveOp_EDGE_NO_OP:
|
||||
return MLIB_EDGE_DST_COPY_SRC;
|
||||
case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
|
||||
default:
|
||||
return MLIB_EDGE_DST_FILL_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* External Functions *
|
||||
@ -400,22 +410,10 @@ Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,
|
||||
}
|
||||
}
|
||||
|
||||
if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
|
||||
int kw2 = kwidth>>1;
|
||||
int kh2 = kheight>>1;
|
||||
int bsize = mlib_ImageGetChannels(src)*
|
||||
(mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
|
||||
|
||||
void *dstDataP = mlib_ImageGetData(dst);
|
||||
void *srcDataP = mlib_ImageGetData(src);
|
||||
/* REMIND: Copy a smaller area */
|
||||
memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
|
||||
}
|
||||
|
||||
cmask = (1<<src->channels)-1;
|
||||
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
|
||||
(w-1)/2, (h-1)/2, scale, cmask,
|
||||
MLIB_EDGE_DST_NO_WRITE);
|
||||
getMlibEdgeHint(edgeHint));
|
||||
|
||||
if (status != MLIB_SUCCESS) {
|
||||
printMedialibError(status);
|
||||
@ -660,22 +658,10 @@ Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,
|
||||
}
|
||||
}
|
||||
|
||||
if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
|
||||
int kw2 = kwidth>>1;
|
||||
int kh2 = kheight>>1;
|
||||
int bsize = mlib_ImageGetChannels(src)*
|
||||
(mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
|
||||
|
||||
void *dstDataP = mlib_ImageGetData(dst);
|
||||
void *srcDataP = mlib_ImageGetData(src);
|
||||
/* REMIND: Copy a smaller area */
|
||||
memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
|
||||
}
|
||||
|
||||
cmask = (1<<src->channels)-1;
|
||||
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
|
||||
(w-1)/2, (h-1)/2, scale, cmask,
|
||||
MLIB_EDGE_DST_NO_WRITE);
|
||||
getMlibEdgeHint(edgeHint));
|
||||
|
||||
if (status != MLIB_SUCCESS) {
|
||||
printMedialibError(status);
|
||||
|
@ -31,7 +31,7 @@
|
||||
/* here come some very simple macros */
|
||||
|
||||
/* advance a pointer p by sizeof(type)*n bytes */
|
||||
#define INCPN(type,p,n) ((p) = (type*)(p)+n)
|
||||
#define INCPN(type,p,n) ((p) = (type*)(p)+(n))
|
||||
|
||||
/* advance a pointer by sizeof(type) */
|
||||
#define INCP(type,p) INCPN(type,(p),1)
|
||||
|
@ -62,6 +62,15 @@ SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* These macro help to ensure that we only take part of frame that fits into
|
||||
logical screen. */
|
||||
|
||||
/* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
|
||||
#define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
|
||||
/* Ensures that line starting at point p does not exceed boundary pmax.
|
||||
Returns fixed length (if fix is needed) */
|
||||
#define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
|
||||
|
||||
int
|
||||
SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
{
|
||||
@ -70,6 +79,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
byte_t *pBitmapBits, *pOldBitmapBits;
|
||||
int i, j;
|
||||
int imageIndex;
|
||||
int cx, cy, cw, ch; /* clamped coordinates */
|
||||
const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
|
||||
const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
|
||||
|
||||
@ -79,14 +89,31 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
|
||||
SplashCleanup(splash);
|
||||
|
||||
if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
|
||||
return 0;
|
||||
}
|
||||
stride = gif->SWidth * splash->imageFormat.depthBytes;
|
||||
if (splash->byteAlignment > 1)
|
||||
stride =
|
||||
(stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
|
||||
|
||||
if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
|
||||
return 0;
|
||||
}
|
||||
bufferSize = stride * gif->SHeight;
|
||||
pBitmapBits = (byte_t *) malloc(bufferSize);
|
||||
if (!pBitmapBits) {
|
||||
return 0;
|
||||
}
|
||||
pOldBitmapBits = (byte_t *) malloc(bufferSize);
|
||||
if (!pOldBitmapBits) {
|
||||
free(pBitmapBits);
|
||||
return 0;
|
||||
}
|
||||
memset(pBitmapBits, 0, bufferSize);
|
||||
|
||||
splash->width = gif->SWidth;
|
||||
@ -94,6 +121,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
splash->frameCount = gif->ImageCount;
|
||||
splash->frames = (SplashImage *)
|
||||
malloc(sizeof(SplashImage) * gif->ImageCount);
|
||||
if (!splash->frames) {
|
||||
free(pBitmapBits);
|
||||
free(pOldBitmapBits);
|
||||
return 0;
|
||||
}
|
||||
memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
|
||||
splash->loopCount = 1;
|
||||
|
||||
@ -109,6 +141,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
int colorCount = 0;
|
||||
rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
|
||||
|
||||
cx = FIX_POINT(desc->Left, 0, gif->SWidth);
|
||||
cy = FIX_POINT(desc->Top, 0, gif->SHeight);
|
||||
cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
|
||||
ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
|
||||
|
||||
if (colorMap) {
|
||||
if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
|
||||
colorCount = colorMap->ColorCount;
|
||||
@ -195,13 +232,22 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
for (; pass < npass; ++pass) {
|
||||
int jump = interlacedJumps[pass];
|
||||
int ofs = interlacedOffset[pass];
|
||||
int numLines = (desc->Height + jump - 1 - ofs) / jump;
|
||||
/* Number of source lines for current pass */
|
||||
int numPassLines = (desc->Height + jump - ofs - 1) / jump;
|
||||
/* Number of lines that fits to dest buffer */
|
||||
int numLines = (ch + jump - ofs - 1) / jump;
|
||||
|
||||
initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
|
||||
desc->Width, pSrc, &srcFormat);
|
||||
initRect(&dstRect, desc->Left, desc->Top + ofs, desc->Width,
|
||||
numLines, jump, stride, pBitmapBits, &splash->imageFormat);
|
||||
pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
|
||||
|
||||
if (numLines > 0) {
|
||||
initRect(&dstRect, cx, cy + ofs, cw,
|
||||
numLines , jump, stride, pBitmapBits, &splash->imageFormat);
|
||||
|
||||
pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
|
||||
}
|
||||
// skip extra source data
|
||||
pSrc += (numPassLines - numLines) * srcRect.stride;
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +255,12 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
|
||||
splash->frames[imageIndex].bitmapBits =
|
||||
(rgbquad_t *) malloc(bufferSize);
|
||||
if (!splash->frames[imageIndex].bitmapBits) {
|
||||
free(pBitmapBits);
|
||||
free(pOldBitmapBits);
|
||||
/* Assuming that callee will take care of splash frames we have already allocated */
|
||||
return 0;
|
||||
}
|
||||
memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
|
||||
|
||||
SplashInitFrameShape(splash, imageIndex);
|
||||
@ -224,27 +276,29 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
|
||||
{
|
||||
ImageRect dstRect;
|
||||
rgbquad_t fillColor = 0; // 0 is transparent
|
||||
if (transparentColor < 0) {
|
||||
|
||||
if (transparentColor > 0) {
|
||||
fillColor= MAKE_QUAD_GIF(
|
||||
colorMap->Colors[gif->SBackGroundColor], 0xff);
|
||||
}
|
||||
initRect(&dstRect, desc->Left, desc->Top,
|
||||
desc->Width, desc->Height, 1, stride,
|
||||
pBitmapBits, &splash->imageFormat);
|
||||
initRect(&dstRect,
|
||||
cx, cy, cw, ch,
|
||||
1, stride,
|
||||
pBitmapBits, &splash->imageFormat);
|
||||
fillRect(fillColor, &dstRect);
|
||||
}
|
||||
break;
|
||||
case GIF_DISPOSE_RESTORE:
|
||||
{
|
||||
|
||||
int lineSize = desc->Width * splash->imageFormat.depthBytes;
|
||||
|
||||
for (j = 0; j < desc->Height; j++) {
|
||||
int lineIndex = stride * (j + desc->Top) +
|
||||
desc->Left * splash->imageFormat.depthBytes;
|
||||
|
||||
memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
|
||||
lineSize);
|
||||
int lineSize = cw * splash->imageFormat.depthBytes;
|
||||
if (lineSize > 0) {
|
||||
int lineOffset = cx * splash->imageFormat.depthBytes;
|
||||
int lineIndex = cy * stride + lineOffset;
|
||||
for (j=0; j<ch; j++) {
|
||||
memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
|
||||
lineSize);
|
||||
lineIndex += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -155,6 +155,10 @@ int BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out);
|
||||
|
||||
void SplashInitFrameShape(Splash * splash, int imageIndex);
|
||||
|
||||
#define SAFE_TO_ALLOC(c, sz) \
|
||||
(((c) > 0) && ((sz) > 0) && \
|
||||
((0xffffffffu / ((unsigned int)(c))) > (unsigned int)(sz)))
|
||||
|
||||
#define dbgprintf printf
|
||||
|
||||
#endif
|
||||
|
@ -103,9 +103,17 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
|
||||
|
||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
if (!SAFE_TO_ALLOC(rowbytes, height)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
|
||||
goto done;
|
||||
}
|
||||
if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
|
||||
== NULL) {
|
||||
goto done;
|
||||
@ -121,13 +129,28 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
|
||||
splash->width = width;
|
||||
splash->height = height;
|
||||
|
||||
if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
|
||||
goto done;
|
||||
}
|
||||
stride = splash->width * splash->imageFormat.depthBytes;
|
||||
|
||||
if (!SAFE_TO_ALLOC(splash->height, stride)) {
|
||||
goto done;
|
||||
}
|
||||
splash->frameCount = 1;
|
||||
splash->frames = (SplashImage *)
|
||||
malloc(sizeof(SplashImage) * splash->frameCount);
|
||||
|
||||
if (splash->frames == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
splash->loopCount = 1;
|
||||
splash->frames[0].bitmapBits = malloc(stride * splash->height);
|
||||
if (splash->frames[0].bitmapBits == NULL) {
|
||||
free(splash->frames);
|
||||
goto done;
|
||||
}
|
||||
splash->frames[0].delay = 0;
|
||||
|
||||
/* FIXME: sort out the real format */
|
||||
|
@ -354,16 +354,9 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
// invoke by FileFileImpl to release lock
|
||||
@Override
|
||||
void release(FileLockImpl fli) throws IOException {
|
||||
try {
|
||||
begin();
|
||||
nd.release(fdObj, fli.position(), fli.size());
|
||||
removeFromFileLockTable(fli);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
protected void implRelease(FileLockImpl fli) throws IOException {
|
||||
nd.release(fdObj, fli.position(), fli.size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,6 +31,7 @@ import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
import sun.security.rsa.RSAKeyFactory;
|
||||
|
||||
/**
|
||||
* RSA keypair generator.
|
||||
@ -43,8 +44,8 @@ import sun.security.jca.JCAUtil;
|
||||
public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
|
||||
// Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
|
||||
private static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
|
||||
private static final int KEY_SIZE_MAX = 16384;
|
||||
static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
|
||||
static final int KEY_SIZE_MAX = 16384;
|
||||
private static final int KEY_SIZE_DEFAULT = 1024;
|
||||
|
||||
// size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
|
||||
@ -59,7 +60,14 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
// random is always ignored
|
||||
public void initialize(int keySize, SecureRandom random) {
|
||||
|
||||
checkKeySize(keySize);
|
||||
try {
|
||||
RSAKeyFactory.checkKeyLengths(keySize, null,
|
||||
KEY_SIZE_MIN, KEY_SIZE_MAX);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidParameterException(e.getMessage());
|
||||
}
|
||||
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
// second initialize method. See JCA doc
|
||||
@ -67,21 +75,31 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
|
||||
int tmpSize;
|
||||
if (params == null) {
|
||||
checkKeySize(KEY_SIZE_DEFAULT);
|
||||
|
||||
tmpSize = KEY_SIZE_DEFAULT;
|
||||
} else if (params instanceof RSAKeyGenParameterSpec) {
|
||||
|
||||
if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Exponent parameter is not supported");
|
||||
}
|
||||
checkKeySize(((RSAKeyGenParameterSpec) params).getKeysize());
|
||||
tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
|
||||
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException
|
||||
("Params must be an instance of RSAKeyGenParameterSpec");
|
||||
}
|
||||
|
||||
try {
|
||||
RSAKeyFactory.checkKeyLengths(tmpSize, null,
|
||||
KEY_SIZE_MIN, KEY_SIZE_MAX);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Invalid Key sizes", e);
|
||||
}
|
||||
|
||||
this.keySize = tmpSize;
|
||||
}
|
||||
|
||||
// generate the keypair. See JCA doc
|
||||
@ -95,18 +113,6 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
return new KeyPair(keys.getPublic(), keys.getPrivate());
|
||||
}
|
||||
|
||||
private void checkKeySize(int keySize) throws InvalidParameterException {
|
||||
if (keySize < KEY_SIZE_MIN) {
|
||||
throw new InvalidParameterException
|
||||
("Key size must be at least " + KEY_SIZE_MIN + " bits");
|
||||
}
|
||||
if (keySize > KEY_SIZE_MAX) {
|
||||
throw new InvalidParameterException
|
||||
("Key size must be " + KEY_SIZE_MAX + " bits or less");
|
||||
}
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
private static native RSAKeyPair generateRSAKeyPair(int keySize,
|
||||
String keyContainerName);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,6 +38,9 @@ import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureSpi;
|
||||
import java.security.SignatureException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import sun.security.rsa.RSAKeyFactory;
|
||||
|
||||
/**
|
||||
* RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
|
||||
@ -124,7 +127,16 @@ abstract class RSASignature extends java.security.SignatureSpi
|
||||
|
||||
// convert key to MSCAPI format
|
||||
|
||||
byte[] modulusBytes = rsaKey.getModulus().toByteArray();
|
||||
BigInteger modulus = rsaKey.getModulus();
|
||||
BigInteger exponent = rsaKey.getPublicExponent();
|
||||
|
||||
// Check against the local and global values to make sure
|
||||
// the sizes are ok. Round up to the nearest byte.
|
||||
RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
|
||||
exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX);
|
||||
|
||||
byte[] modulusBytes = modulus.toByteArray();
|
||||
byte[] exponentBytes = exponent.toByteArray();
|
||||
|
||||
// Adjust key length due to sign bit
|
||||
int keyBitLength = (modulusBytes[0] == 0)
|
||||
@ -132,8 +144,7 @@ abstract class RSASignature extends java.security.SignatureSpi
|
||||
: modulusBytes.length * 8;
|
||||
|
||||
byte[] keyBlob = generatePublicKeyBlob(
|
||||
keyBitLength, modulusBytes,
|
||||
rsaKey.getPublicExponent().toByteArray());
|
||||
keyBitLength, modulusBytes, exponentBytes);
|
||||
|
||||
publicKey = importPublicKey(keyBlob, keyBitLength);
|
||||
|
||||
@ -166,12 +177,11 @@ abstract class RSASignature extends java.security.SignatureSpi
|
||||
}
|
||||
privateKey = (sun.security.mscapi.RSAPrivateKey) key;
|
||||
|
||||
// Determine byte length from bit length
|
||||
int keySize = (privateKey.bitLength() + 7) >> 3;
|
||||
|
||||
if (keySize < 64)
|
||||
throw new InvalidKeyException(
|
||||
"RSA keys must be at least 512 bits long");
|
||||
// Check against the local and global values to make sure
|
||||
// the sizes are ok. Round up to nearest byte.
|
||||
RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7),
|
||||
null, RSAKeyPairGenerator.KEY_SIZE_MIN,
|
||||
RSAKeyPairGenerator.KEY_SIZE_MAX);
|
||||
|
||||
if (needsReset) {
|
||||
messageDigest.reset();
|
||||
|
@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
|
||||
o.Offset = lowPos;
|
||||
o.OffsetHigh = highPos;
|
||||
result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
|
||||
if (result == 0) {
|
||||
if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Release failed");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -73,6 +73,7 @@ jmethodID setRealmMethod = 0;
|
||||
* Function prototypes for internal routines
|
||||
*
|
||||
*/
|
||||
BOOL native_debug = 0;
|
||||
|
||||
BOOL PackageConnectLookup(PHANDLE,PULONG);
|
||||
|
||||
@ -113,208 +114,221 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
|
||||
jclass cls;
|
||||
JNIEnv *env;
|
||||
jfieldID fldDEBUG;
|
||||
|
||||
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
|
||||
return JNI_EVERSION; /* JNI version not supported */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Krb5");
|
||||
if (cls == NULL) {
|
||||
printf("LSA: Couldn't find Krb5\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
fldDEBUG = (*env)->GetStaticFieldID(env, cls, "DEBUG", "Z");
|
||||
if (fldDEBUG == NULL) {
|
||||
printf("LSA: Krb5 has no DEBUG field\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find Ticket\n");
|
||||
printf("LSA: Couldn't find Ticket\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found Ticket\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found Ticket\n");
|
||||
}
|
||||
|
||||
ticketClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (ticketClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find PrincipalName\n");
|
||||
printf("LSA: Couldn't find PrincipalName\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found PrincipalName\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found PrincipalName\n");
|
||||
}
|
||||
|
||||
principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (principalNameClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/util/DerValue");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find DerValue\n");
|
||||
printf("LSA: Couldn't find DerValue\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found DerValue\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found DerValue\n");
|
||||
}
|
||||
|
||||
derValueClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (derValueClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find EncryptionKey\n");
|
||||
printf("LSA: Couldn't find EncryptionKey\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found EncryptionKey\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found EncryptionKey\n");
|
||||
}
|
||||
|
||||
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (encryptionKeyClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find TicketFlags\n");
|
||||
printf("LSA: Couldn't find TicketFlags\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found TicketFlags\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found TicketFlags\n");
|
||||
}
|
||||
|
||||
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (ticketFlagsClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find KerberosTime\n");
|
||||
printf("LSA: Couldn't find KerberosTime\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found KerberosTime\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KerberosTime\n");
|
||||
}
|
||||
|
||||
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (kerberosTimeClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"java/lang/String");
|
||||
|
||||
if (cls == NULL) {
|
||||
printf("Couldn't find String\n");
|
||||
printf("LSA: Couldn't find String\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found String\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found String\n");
|
||||
}
|
||||
|
||||
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (javaLangStringClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Made NewWeakGlobalRef\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
}
|
||||
|
||||
derValueConstructor = (*env)->GetMethodID(env, derValueClass,
|
||||
"<init>", "([B)V");
|
||||
if (derValueConstructor == 0) {
|
||||
printf("Couldn't find DerValue constructor\n");
|
||||
printf("LSA: Couldn't find DerValue constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found DerValue constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found DerValue constructor\n");
|
||||
}
|
||||
|
||||
ticketConstructor = (*env)->GetMethodID(env, ticketClass,
|
||||
"<init>", "(Lsun/security/util/DerValue;)V");
|
||||
if (ticketConstructor == 0) {
|
||||
printf("Couldn't find Ticket constructor\n");
|
||||
printf("LSA: Couldn't find Ticket constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found Ticket constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found Ticket constructor\n");
|
||||
}
|
||||
|
||||
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
|
||||
"<init>", "([Ljava/lang/String;)V");
|
||||
if (principalNameConstructor == 0) {
|
||||
printf("Couldn't find PrincipalName constructor\n");
|
||||
printf("LSA: Couldn't find PrincipalName constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found PrincipalName constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found PrincipalName constructor\n");
|
||||
}
|
||||
|
||||
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
|
||||
"<init>", "(I[B)V");
|
||||
if (encryptionKeyConstructor == 0) {
|
||||
printf("Couldn't find EncryptionKey constructor\n");
|
||||
printf("LSA: Couldn't find EncryptionKey constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found EncryptionKey constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found EncryptionKey constructor\n");
|
||||
}
|
||||
|
||||
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
|
||||
"<init>", "(I[B)V");
|
||||
if (ticketFlagsConstructor == 0) {
|
||||
printf("Couldn't find TicketFlags constructor\n");
|
||||
printf("LSA: Couldn't find TicketFlags constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found TicketFlags constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found TicketFlags constructor\n");
|
||||
}
|
||||
|
||||
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
|
||||
"<init>", "(Ljava/lang/String;)V");
|
||||
if (kerberosTimeConstructor == 0) {
|
||||
printf("Couldn't find KerberosTime constructor\n");
|
||||
printf("LSA: Couldn't find KerberosTime constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Found KerberosTime constructor\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KerberosTime constructor\n");
|
||||
}
|
||||
|
||||
// load the setRealm method in PrincipalName
|
||||
setRealmMethod = (*env)->GetMethodID(env, principalNameClass,
|
||||
"setRealm", "(Ljava/lang/String;)V");
|
||||
if (setRealmMethod == 0) {
|
||||
printf("Couldn't find setRealm in PrincipalName\n");
|
||||
printf("LSA: Couldn't find setRealm in PrincipalName\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Finished OnLoad processing\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Finished OnLoad processing\n");
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
@ -389,16 +403,25 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
|
||||
if (krbcredsConstructor == 0) {
|
||||
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
|
||||
"(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
|
||||
"(Lsun/security/krb5/internal/Ticket;"
|
||||
"Lsun/security/krb5/PrincipalName;"
|
||||
"Lsun/security/krb5/PrincipalName;"
|
||||
"Lsun/security/krb5/EncryptionKey;"
|
||||
"Lsun/security/krb5/internal/TicketFlags;"
|
||||
"Lsun/security/krb5/internal/KerberosTime;"
|
||||
"Lsun/security/krb5/internal/KerberosTime;"
|
||||
"Lsun/security/krb5/internal/KerberosTime;"
|
||||
"Lsun/security/krb5/internal/KerberosTime;"
|
||||
"Lsun/security/krb5/internal/HostAddresses;)V");
|
||||
if (krbcredsConstructor == 0) {
|
||||
printf("Couldn't find sun.security.krb5.Credentials constructor\n");
|
||||
printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Found KrbCreds constructor\n");
|
||||
#endif
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KrbCreds constructor\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Get the logon handle and package ID from the
|
||||
@ -407,9 +430,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
if (!PackageConnectLookup(&LogonHandle, &PackageId))
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Got handle to Kerberos package\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Got handle to Kerberos package\n");
|
||||
}
|
||||
|
||||
// Get the MS TGT from cache
|
||||
CacheRequest.MessageType = KerbRetrieveTicketMessage;
|
||||
@ -426,9 +449,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
&SubStatus
|
||||
);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Response size is %d\n", rspSize);
|
||||
#endif
|
||||
if (native_debug) {
|
||||
printf("LSA: Response size is %d\n", rspSize);
|
||||
}
|
||||
|
||||
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
|
||||
if (!LSA_SUCCESS(Status)) {
|
||||
@ -467,9 +490,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
}
|
||||
|
||||
if (ignore_cache) {
|
||||
#ifdef DEBUG
|
||||
printf("MS TGT in cache is invalid/not supported; request new ticket\n");
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
|
||||
}
|
||||
|
||||
// use domain to request Ticket
|
||||
Status = ConstructTicketRequest(msticket->TargetDomainName,
|
||||
@ -493,9 +516,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
&SubStatus
|
||||
);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Response size is %d\n", responseSize);
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: Response size is %d\n", responseSize);
|
||||
}
|
||||
|
||||
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
|
||||
if (!LSA_SUCCESS(Status)) {
|
||||
@ -788,7 +811,9 @@ ShowLastError(
|
||||
static WCHAR szMsgBuf[MAX_MSG_SIZE];
|
||||
DWORD dwRes;
|
||||
|
||||
printf("Error calling function %s: %lu\n", szAPI, dwError);
|
||||
if (native_debug) {
|
||||
printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);
|
||||
}
|
||||
|
||||
dwRes = FormatMessage (
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
@ -798,11 +823,13 @@ ShowLastError(
|
||||
szMsgBuf,
|
||||
MAX_MSG_SIZE,
|
||||
NULL);
|
||||
if (0 == dwRes) {
|
||||
printf("FormatMessage failed with %d\n", GetLastError());
|
||||
// ExitProcess(EXIT_FAILURE);
|
||||
} else {
|
||||
printf("%S",szMsgBuf);
|
||||
if (native_debug) {
|
||||
if (0 == dwRes) {
|
||||
printf("LSA: FormatMessage failed with %d\n", GetLastError());
|
||||
// ExitProcess(EXIT_FAILURE);
|
||||
} else {
|
||||
printf("LSA: %S",szMsgBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -896,17 +923,19 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
|
||||
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
|
||||
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Principal domain is %S\n", realm);
|
||||
printf("Name type is %x\n", principalName->NameType);
|
||||
printf("Name count is %x\n", principalName->NameCount);
|
||||
#endif
|
||||
if (native_debug) {
|
||||
printf("LSA: Principal domain is %S\n", realm);
|
||||
printf("LSA: Name type is %x\n", principalName->NameType);
|
||||
printf("LSA: Name count is %x\n", principalName->NameCount);
|
||||
}
|
||||
|
||||
nameCount = principalName->NameCount;
|
||||
stringArray = (*env)->NewObjectArray(env, nameCount,
|
||||
javaLangStringClass, NULL);
|
||||
if (stringArray == NULL) {
|
||||
printf("Can't allocate String array for Principal\n");
|
||||
if (native_debug) {
|
||||
printf("LSA: Can't allocate String array for Principal\n");
|
||||
}
|
||||
LocalFree(realm);
|
||||
return principal;
|
||||
}
|
||||
@ -941,6 +970,17 @@ jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
|
||||
// First, need to build a byte array
|
||||
jbyteArray ary;
|
||||
jobject encryptionKey = NULL;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<cryptoKey->Length; i++) {
|
||||
if (cryptoKey->Value[i]) break;
|
||||
}
|
||||
if (i == cryptoKey->Length) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Session key all zero. Stop.\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ary = (*env)->NewByteArray(env,cryptoKey->Length);
|
||||
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
|
||||
@ -1005,9 +1045,9 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
|
||||
hour,
|
||||
minute,
|
||||
second );
|
||||
#ifdef DEBUG
|
||||
printf("%S\n", (wchar_t *)timeString);
|
||||
#endif /* DEBUG */
|
||||
if (native_debug) {
|
||||
printf("LSA: %S\n", (wchar_t *)timeString);
|
||||
}
|
||||
stringTime = (*env)->NewString(env, timeString,
|
||||
(sizeof(timeString)/sizeof(WCHAR))-1);
|
||||
if (stringTime != NULL) { // everything's OK so far
|
||||
|
BIN
jdk/test/java/awt/FontClass/CreateFont/A.ttf
Normal file
BIN
jdk/test/java/awt/FontClass/CreateFont/A.ttf
Normal file
Binary file not shown.
139
jdk/test/java/awt/FontClass/CreateFont/BigFont.java
Normal file
139
jdk/test/java/awt/FontClass/CreateFont/BigFont.java
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.applet.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
public class BigFont extends Applet {
|
||||
|
||||
static private class SizedInputStream extends InputStream {
|
||||
|
||||
int size;
|
||||
int cnt = 0;
|
||||
|
||||
SizedInputStream(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public int read() {
|
||||
if (cnt < size) {
|
||||
cnt++;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentSize() {
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
|
||||
String id;
|
||||
String fileName;
|
||||
|
||||
public void init() {
|
||||
id = getParameter("number");
|
||||
fileName = getParameter("font");
|
||||
|
||||
System.out.println("Applet " + id + " "+
|
||||
Thread.currentThread().getThreadGroup());
|
||||
// Larger than size for a single font.
|
||||
int fontSize = 64 * 1000 * 1000;
|
||||
SizedInputStream sis = new SizedInputStream(fontSize);
|
||||
try {
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, sis);
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof FontFormatException ||
|
||||
fontSize <= sis.getCurrentSize())
|
||||
{
|
||||
System.out.println(sis.getCurrentSize());
|
||||
System.out.println(t);
|
||||
throw new RuntimeException("Allowed file to be too large.");
|
||||
}
|
||||
}
|
||||
// The following part of the test was verified manually but
|
||||
// is impractical to enable because it requires a fairly large
|
||||
// valid font to be part of the test, and we can't easily include
|
||||
// that, nor dependably reference one from the applet environment.
|
||||
/*
|
||||
if (fileName == null) {
|
||||
return;
|
||||
}
|
||||
int size = getFileSize(fileName);
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
int fontCnt = 1000 * 1000 * 1000 / size;
|
||||
loadMany(size, fontCnt, fileName);
|
||||
System.gc(); System.gc();
|
||||
fontCnt = fontCnt / 2;
|
||||
System.out.println("Applet " + id + " load more.");
|
||||
loadMany(size, fontCnt, fileName);
|
||||
*/
|
||||
System.out.println("Applet " + id + " finished.");
|
||||
}
|
||||
|
||||
int getFileSize(String fileName) {
|
||||
try {
|
||||
URL url = new URL(getCodeBase(), fileName);
|
||||
InputStream inStream = url.openStream();
|
||||
BufferedInputStream fontStream = new BufferedInputStream(inStream);
|
||||
int size = 0;
|
||||
while (fontStream.read() != -1) {
|
||||
size++;
|
||||
}
|
||||
fontStream.close();
|
||||
return size;
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
void loadMany(int oneFont, int fontCnt, String fileName) {
|
||||
System.out.println("fontcnt= " + fontCnt);
|
||||
Font[] fonts = new Font[fontCnt];
|
||||
int totalSize = 0;
|
||||
boolean gotException = false;
|
||||
for (int i=0; i<fontCnt; i++) {
|
||||
try {
|
||||
URL url = new URL(getCodeBase(), fileName);
|
||||
InputStream inStream = url.openStream();
|
||||
BufferedInputStream fontStream =
|
||||
new BufferedInputStream(inStream);
|
||||
fonts[i] = Font.createFont(Font.TRUETYPE_FONT, fontStream);
|
||||
totalSize += oneFont;
|
||||
fontStream.close();
|
||||
} catch (Throwable t) {
|
||||
gotException = true;
|
||||
System.out.println("Applet " + id + " " + t);
|
||||
}
|
||||
}
|
||||
if (!gotException) {
|
||||
throw new RuntimeException("No expected exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
89
jdk/test/java/awt/FontClass/CreateFont/DeleteFont.java
Normal file
89
jdk/test/java/awt/FontClass/CreateFont/DeleteFont.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class DeleteFont {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
|
||||
String font = "A.ttf";
|
||||
String sep = System.getProperty("file.separator");
|
||||
String testSrc = System.getenv("TESTSRC");
|
||||
if (testSrc != null) {
|
||||
font = testSrc + sep + font;
|
||||
}
|
||||
System.out.println("Using font file: " + font);
|
||||
FileInputStream fis = new FileInputStream(font);
|
||||
Font f = Font.createFont(Font.TRUETYPE_FONT, fis);
|
||||
f.toString();
|
||||
f.deriveFont(Font.BOLD);
|
||||
f.canDisplay('X');
|
||||
|
||||
InputStream in = new InputStream() {
|
||||
public int read() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
};
|
||||
boolean gotException = false;
|
||||
try {
|
||||
Font.createFont(java.awt.Font.TRUETYPE_FONT, in);
|
||||
} catch (IOException e) {
|
||||
gotException = true;
|
||||
}
|
||||
if (!gotException) {
|
||||
throw new RuntimeException("No expected IOException");
|
||||
}
|
||||
badRead(-2, Font.TRUETYPE_FONT);
|
||||
badRead(8193, Font.TRUETYPE_FONT);
|
||||
|
||||
badRead(-2, Font.TYPE1_FONT);
|
||||
badRead(8193, Font.TYPE1_FONT);
|
||||
|
||||
// Make sure GC has a chance to clean up before we exit.
|
||||
System.gc(); System.gc();
|
||||
}
|
||||
|
||||
static void badRead(final int retval, int fontType) {
|
||||
int num = 2;
|
||||
byte[] buff = new byte[16*8192]; // Multiple of 8192 is important.
|
||||
for (int ct=0; ct<num; ++ct) {
|
||||
try {
|
||||
Font.createFont(
|
||||
fontType,
|
||||
new ByteArrayInputStream(buff) {
|
||||
@Override
|
||||
public int read(byte[] buff, int off, int len) {
|
||||
int read = super.read(buff, off, len);
|
||||
return read<0 ? retval : read;
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable exc) {
|
||||
//exc.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
66
jdk/test/java/awt/FontClass/CreateFont/DeleteFont.sh
Normal file
66
jdk/test/java/awt/FontClass/CreateFont/DeleteFont.sh
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code 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
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
# have any questions.
|
||||
|
||||
# @test
|
||||
# @bug 6189812 6380357 6632886
|
||||
# @summary Verify that temporary font files are deleted on exit.
|
||||
|
||||
if [ -z "${TESTSRC}" ]; then
|
||||
echo "TESTSRC undefined: defaulting to ."
|
||||
TESTSRC=.
|
||||
fi
|
||||
|
||||
if [ -z "${TESTCLASSES}" ]; then
|
||||
echo "TESTCLASSES undefined: defaulting to ."
|
||||
TESTCLASSES=.
|
||||
fi
|
||||
|
||||
if [ -z "${TESTJAVA}" ]; then
|
||||
echo "TESTJAVA undefined: can't continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "TESTJAVA=${TESTJAVA}"
|
||||
echo "TESTSRC=${TESTSRC}"
|
||||
echo "TESTCLASSES=${TESTCLASSES}"
|
||||
cd ${TESTSRC}
|
||||
${TESTJAVA}/bin/javac -d ${TESTCLASSES} DeleteFont.java
|
||||
|
||||
cd ${TESTCLASSES}
|
||||
|
||||
numfiles0=`ls ${TESTCLASSES} | wc -l`
|
||||
${TESTJAVA}/bin/java -Djava.io.tmpdir=${TESTCLASSES} DeleteFont
|
||||
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Test fails: exception thrown!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
numfiles1=`ls ${TESTCLASSES} | wc -l`
|
||||
|
||||
if [ $numfiles0 -ne $numfiles1 ]
|
||||
then
|
||||
echo "Test fails: tmp file exists!"
|
||||
ls ${TESTCLASSES}
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user