Imported Upstream version 3.10.0

Former-commit-id: 172c8e3c300b39d5785c7a3e8dfb08ebdbc1a99b
This commit is contained in:
Jo Shields
2014-10-04 11:27:48 +01:00
parent fe777c5c82
commit 8b9b85e7f5
970 changed files with 20242 additions and 31308 deletions

View File

@ -1 +1 @@
bbc1d241f632078e8ecf146e9398406c5719dd2f
07fd7bd567e5b0ae8b3ae9c32741b56f6f363b0a

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2007-2011 Jeroen Frijters
Copyright (C) 2007-2014 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -24,80 +24,40 @@
package java.lang;
import ikvm.runtime.AssemblyClassLoader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.util.Enumeration;
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.security.AccessControlContext;
import java.util.Map;
import sun.nio.ch.Interruptible;
import sun.reflect.annotation.AnnotationType;
import sun.security.action.GetPropertyAction;
@ikvm.lang.Internal
public class LangHelper
{
private static boolean addedSystemPackages;
private static void addSystemPackage(Map pkgMap)
{
// NOTE caller must have acquired lock on pkgMap
if (!addedSystemPackages)
{
addedSystemPackages = true;
String[] pkgs = getBootClassPackages();
for (int i = 0; i < pkgs.length; i++)
{
pkgMap.put(pkgs[i],
new Package(pkgs[i],
VMSystemProperties.SPEC_TITLE, // specTitle
VMSystemProperties.SPEC_VERSION, // specVersion
VMSystemProperties.SPEC_VENDOR, // specVendor
"IKVM.NET OpenJDK", // implTitle
PropertyConstants.openjdk_version, // implVersion
"Oracle Corporation & others", // implVendor
null, // sealBase
null)); // class loader
}
}
}
private static native String[] getBootClassPackages();
/* this method gets called by Package.getSystemPackage() via a redefined method in map.xml */
static Package getSystemPackage(Map pkgs, String name)
{
synchronized (pkgs)
{
addSystemPackage(pkgs);
return (Package)pkgs.get(name);
}
}
/* this method gets called by Package.getSystemPackages() via a redefined method in map.xml */
static Package[] getSystemPackages(Map pkgs)
{
synchronized (pkgs)
{
addSystemPackage(pkgs);
return (Package[])pkgs.values().toArray(new Package[pkgs.size()]);
}
}
public static sun.misc.JavaLangAccess getJavaLangAccess()
{
return new sun.misc.JavaLangAccess() {
public sun.reflect.ConstantPool getConstantPool(Class klass) {
return null;
return klass.getConstantPool();
}
public void setAnnotationType(Class klass, AnnotationType type) {
klass.setAnnotationType(type);
public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
return klass.casAnnotationType(oldType, newType);
}
public AnnotationType getAnnotationType(Class klass) {
return klass.getAnnotationType();
}
public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
return klass.getDeclaredAnnotationMap();
}
public byte[] getRawClassAnnotations(Class<?> klass) {
throw new InternalError();
}
public byte[] getRawClassTypeAnnotations(Class<?> klass) {
return klass.getRawTypeAnnotations();
}
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
return Class.getExecutableTypeAnnotationBytes(executable);
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
return klass.getEnumConstantsShared();
@ -114,8 +74,14 @@ public class LangHelper
public StackTraceElement getStackTraceElement(Throwable t, int i) {
return t.getStackTraceElement(i);
}
public int getStringHash32(String string) {
return StringHelper.hash32(string);
public String newStringUnsafe(char[] chars) {
return String.valueOf(chars);
}
public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) {
return new Thread(target, acc);
}
public void invokeFinalize(Object o) throws Throwable {
// we don't actually support invoking the finalize method explicitly
}
};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. 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
@ -42,9 +42,15 @@ import java.io.BufferedOutputStream;
import java.lang.ProcessBuilder.Redirect;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cli.System.AsyncCallback;
import cli.System.IAsyncResult;
import cli.System.Diagnostics.ProcessStartInfo;
import cli.System.EventArgs;
import cli.System.EventHandler;
import cli.System.IO.FileAccess;
import cli.System.IO.FileShare;
import cli.System.IO.FileMode;
@ -146,8 +152,17 @@ final class ProcessImpl extends Process {
return new ProcessImpl(cmdarray, environment, dir,
stdHandles, redirectErrorStream);
} catch (Throwable t) {
if (f0 != null)
f0.close();
if (f1 != null)
f1.close();
if (f2 != null)
f2.close();
throw t;
} finally {
// HACK prevent the File[In|Out]putStream objects from closing the streams
// (the System.IO.FileStream will eventually be closed explicitly or by its finalizer)
if (f0 != null)
cli.System.GC.SuppressFinalize(f0);
if (f1 != null)
@ -158,50 +173,240 @@ final class ProcessImpl extends Process {
}
private static class LazyPattern {
// Escape-support version:
// "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)";
private static final Pattern PATTERN =
Pattern.compile("[^\\s\"]+|\"[^\"]*\"");
};
/* Parses the command string parameter into the executable name and
* program arguments.
*
* The command string is broken into tokens. The token separator is a space
* or quota character. The space inside quotation is not a token separator.
* There are no escape sequences.
*/
private static String[] getTokensFromCommand(String command) {
ArrayList<String> matchList = new ArrayList<>(8);
Matcher regexMatcher = LazyPattern.PATTERN.matcher(command);
while (regexMatcher.find())
matchList.add(regexMatcher.group());
return matchList.toArray(new String[matchList.size()]);
}
private static final int VERIFICATION_CMD_BAT = 0;
private static final int VERIFICATION_WIN32 = 1;
private static final int VERIFICATION_LEGACY = 2;
private static final char ESCAPE_VERIFICATION[][] = {
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
{' ', '\t', '<', '>', '&', '|', '^'},
{' ', '\t', '<', '>'},
{' ', '\t'}
};
private static String createCommandLine(int verificationType,
final String executablePath,
final String cmd[])
{
StringBuilder cmdbuf = new StringBuilder(80);
cmdbuf.append(executablePath);
for (int i = 1; i < cmd.length; ++i) {
cmdbuf.append(' ');
String s = cmd[i];
if (needsEscaping(verificationType, s)) {
cmdbuf.append('"').append(s);
// The code protects the [java.exe] and console command line
// parser, that interprets the [\"] combination as an escape
// sequence for the ["] char.
// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
//
// If the argument is an FS path, doubling of the tail [\]
// char is not a problem for non-console applications.
//
// The [\"] sequence is not an escape sequence for the [cmd.exe]
// command line parser. The case of the [""] tail escape
// sequence could not be realized due to the argument validation
// procedure.
if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) {
cmdbuf.append('\\');
}
cmdbuf.append('"');
} else {
cmdbuf.append(s);
}
}
return cmdbuf.toString();
}
private static boolean isQuoted(boolean noQuotesInside, String arg,
String errorMessage) {
int lastPos = arg.length() - 1;
if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') {
// The argument has already been quoted.
if (noQuotesInside) {
if (arg.indexOf('"', 1) != lastPos) {
// There is ["] inside.
throw new IllegalArgumentException(errorMessage);
}
}
return true;
}
if (noQuotesInside) {
if (arg.indexOf('"') >= 0) {
// There is ["] inside.
throw new IllegalArgumentException(errorMessage);
}
}
return false;
}
private static boolean needsEscaping(int verificationType, String arg) {
// Switch off MS heuristic for internal ["].
// Please, use the explicit [cmd.exe] call
// if you need the internal ["].
// Example: "cmd.exe", "/C", "Extended_MS_Syntax"
// For [.exe] or [.com] file the unpaired/internal ["]
// in the argument is not a problem.
boolean argIsQuoted = isQuoted(
(verificationType == VERIFICATION_CMD_BAT),
arg, "Argument has embedded quote, use the explicit CMD.EXE call.");
if (!argIsQuoted) {
char testEscape[] = ESCAPE_VERIFICATION[verificationType];
for (int i = 0; i < testEscape.length; ++i) {
if (arg.indexOf(testEscape[i]) >= 0) {
return true;
}
}
}
return false;
}
private static String getExecutablePath(String path)
throws IOException
{
boolean pathIsQuoted = isQuoted(true, path,
"Executable name has embedded quote, split the arguments");
// Win32 CreateProcess requires path to be normalized
File fileToRun = new File(pathIsQuoted
? path.substring(1, path.length() - 1)
: path);
// From the [CreateProcess] function documentation:
//
// "If the file name does not contain an extension, .exe is appended.
// Therefore, if the file name extension is .com, this parameter
// must include the .com extension. If the file name ends in
// a period (.) with no extension, or if the file name contains a path,
// .exe is not appended."
//
// "If the file name !does not contain a directory path!,
// the system searches for the executable file in the following
// sequence:..."
//
// In practice ANY non-existent path is extended by [.exe] extension
// in the [CreateProcess] funcion with the only exception:
// the path ends by (.)
return fileToRun.getPath();
}
private boolean isShellFile(String executablePath) {
String upPath = executablePath.toUpperCase();
return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
}
private String quoteString(String arg) {
StringBuilder argbuf = new StringBuilder(arg.length() + 2);
return argbuf.append('"').append(arg).append('"').toString();
}
private cli.System.Diagnostics.Process handle;
private OutputStream stdin_stream;
private InputStream stdout_stream;
private InputStream stderr_stream;
private ProcessImpl(final String cmd[],
private ProcessImpl(String cmd[],
final java.util.Map<String,String> envblock,
final String path,
final Stream[] stdHandles,
final boolean redirectErrorStream)
throws IOException
{
// Win32 CreateProcess requires cmd[0] to be normalized
cmd[0] = new File(cmd[0]).getPath();
// give the runtime an opportunity to map executables from VFS to a real executable
cmd[0] = mapVfsExecutable(cmd[0]);
StringBuilder cmdbuf = new StringBuilder(80);
for (int i = 0; i < cmd.length; i++) {
if (i > 0) {
cmdbuf.append(' ');
}
String s = cmd[i];
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
if (s.charAt(0) != '"') {
cmdbuf.append('"');
cmdbuf.append(s);
if (s.endsWith("\\")) {
cmdbuf.append("\\");
}
cmdbuf.append('"');
} else if (s.endsWith("\"")) {
/* The argument has already been quoted. */
cmdbuf.append(s);
} else {
/* Unmatched quote for the argument. */
throw new IllegalArgumentException();
}
} else {
cmdbuf.append(s);
}
String cmdstr;
SecurityManager security = System.getSecurityManager();
boolean allowAmbiguousCommands = false;
if (security == null) {
allowAmbiguousCommands = true;
String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands");
if (value != null)
allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
}
if (allowAmbiguousCommands) {
// Legacy mode.
// Normalize path if possible.
String executablePath = new File(cmd[0]).getPath();
// No worry about internal, unpaired ["], and redirection/piping.
if (needsEscaping(VERIFICATION_LEGACY, executablePath) )
executablePath = quoteString(executablePath);
cmdstr = createCommandLine(
//legacy mode doesn't worry about extended verification
VERIFICATION_LEGACY,
executablePath,
cmd);
} else {
String executablePath;
try {
executablePath = getExecutablePath(cmd[0]);
} catch (IllegalArgumentException e) {
// Workaround for the calls like
// Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar")
// No chance to avoid CMD/BAT injection, except to do the work
// right from the beginning. Otherwise we have too many corner
// cases from
// Runtime.getRuntime().exec(String[] cmd [, ...])
// calls with internal ["] and escape sequences.
// Restore original command line.
StringBuilder join = new StringBuilder();
// terminal space in command line is ok
for (String s : cmd)
join.append(s).append(' ');
// Parse the command line again.
cmd = getTokensFromCommand(join.toString());
executablePath = getExecutablePath(cmd[0]);
// Check new executable name once more
if (security != null)
security.checkExec(executablePath);
}
// Quotation protects from interpretation of the [path] argument as
// start of longer path with spaces. Quotation has no influence to
// [.exe] extension heuristic.
cmdstr = createCommandLine(
// We need the extended verification procedure for CMD files.
isShellFile(executablePath)
? VERIFICATION_CMD_BAT
: VERIFICATION_WIN32,
quoteString(executablePath),
cmd);
}
String cmdstr = cmdbuf.toString();
handle = create(cmdstr, envblock, path,
stdHandles, redirectErrorStream);
@ -261,6 +466,7 @@ final class ProcessImpl extends Process {
throw new InterruptedException();
return exitValue();
}
private static void waitForInterruptibly(cli.System.Diagnostics.Process handle) throws InterruptedException {
// to be interruptable we have to use polling
// (on .NET 2.0 WaitForExit is actually interruptible, but this isn't documented)
@ -269,7 +475,53 @@ final class ProcessImpl extends Process {
;
}
@Override
public boolean waitFor(long timeout, TimeUnit unit)
throws InterruptedException
{
if (handle.get_HasExited()) return true;
if (timeout <= 0) return false;
long msTimeout = unit.toMillis(timeout);
waitForTimeoutInterruptibly(handle, msTimeout);
if (Thread.interrupted())
throw new InterruptedException();
return handle.get_HasExited();
}
private static void waitForTimeoutInterruptibly(
cli.System.Diagnostics.Process handle, long timeout) {
long now = System.currentTimeMillis();
long exp = now + timeout;
if (exp < now) {
// if we overflowed, just wait for a really long time
exp = Long.MAX_VALUE;
}
Thread current = Thread.currentThread();
for (;;) {
if (current.isInterrupted()) {
return;
}
// wait for a maximum of 100 ms to be interruptible
if (handle.WaitForExit((int)Math.min(100, exp - now))) {
return;
}
now = System.currentTimeMillis();
if (now >= exp) {
return;
}
}
}
public void destroy() { terminateProcess(handle); }
@Override
public Process destroyForcibly() {
destroy();
return this;
}
private static void terminateProcess(cli.System.Diagnostics.Process handle) {
try {
if (false) throw new cli.System.ComponentModel.Win32Exception();
@ -280,10 +532,21 @@ final class ProcessImpl extends Process {
}
}
@Override
public boolean isAlive() {
return isProcessAlive(handle);
}
private static boolean isProcessAlive(cli.System.Diagnostics.Process handle) {
return !handle.get_HasExited();
}
/**
* Create a process using the win32 function CreateProcess.
* The method is synchronized due to MS kb315939 problem.
* All native handles should restore the inherit flag at the end of call.
*
* @param cmdstr the Windows commandline
* @param cmdstr the Windows command line
* @param envblock NUL-separated, double-NUL-terminated list of
* environment strings in VAR=VALUE form
* @param dir the working directory of the process, or null if
@ -312,7 +575,8 @@ final class ProcessImpl extends Process {
argumentsStart++;
}
ProcessStartInfo si = new ProcessStartInfo(cmdstr.substring(0, programEnd), cmdstr.substring(argumentsStart));
String fileName = cmdstr.substring(0, programEnd);
ProcessStartInfo si = new ProcessStartInfo(mapVfsExecutable(fileName), cmdstr.substring(argumentsStart));
si.set_UseShellExecute(false);
si.set_RedirectStandardError(true);
si.set_RedirectStandardOutput(true);
@ -338,6 +602,27 @@ final class ProcessImpl extends Process {
} catch (cli.System.InvalidOperationException x2) {
throw new IOException(x2.getMessage());
}
// if any of the handles is redirected to/from a file,
// we need to close the files as soon as the process exits
if (stdHandles[0] instanceof FileStream
|| stdHandles[1] instanceof FileStream
|| stdHandles[2] instanceof FileStream) {
final Stream s0 = stdHandles[0];
final Stream s1 = stdHandles[1];
final Stream s2 = stdHandles[2];
proc.set_EnableRaisingEvents(true);
proc.add_Exited(new EventHandler(new EventHandler.Method() {
public void Invoke(Object sender, EventArgs e) {
if (s0 instanceof FileStream)
s0.Close();
if (s1 instanceof FileStream)
s1.Close();
if (s2 instanceof FileStream)
s2.Close();
}
}));
}
Stream stdin = proc.get_StandardInput().get_BaseStream();
Stream stdout = proc.get_StandardOutput().get_BaseStream();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
7ab53c76bb97c702c39866643a2547962ef3ead6