提交 edc21737 编写于 作者: K ksrini

7146424: Wildcard expansion for single entry classpath

Reviewed-by: dholmes, darcy, jjh, sherman
上级 175e85db
......@@ -153,7 +153,6 @@ ifeq ($(PLATFORM), windows)
ifndef LOCAL_RESOURCE_FILE
@$(ECHO) $(OBJDIR)/$(PROGRAM).res >> $@
endif
@$(ECHO) setargv.obj >> $@
@$(ECHO) Created $@
$(ACTUAL_PROGRAM):: $(OBJDIR)/$(PROGRAM)$(EXE_SUFFIX)
......
......@@ -90,7 +90,8 @@ endif # SYSTEM_ZLIB
# add platform specific files
ifeq ($(PLATFORM), windows)
FILES_c += java_md.c
FILES_c += java_md.c \
cmdtoargs.c
else # NIXES
FILES_c += java_md_common.c
ifeq ($(PLATFORM), macosx)
......@@ -149,7 +150,11 @@ ifeq ($(PLATFORM), windows)
-export:JLI_ReportErrorMessage \
-export:JLI_ReportErrorMessageSys \
-export:JLI_ReportMessage \
-export:JLI_ReportExceptionDescription
-export:JLI_ReportExceptionDescription \
-export:JLI_MemAlloc \
-export:JLI_CmdToArgs \
-export:JLI_GetStdArgc \
-export:JLI_GetStdArgs
endif # PLATFORM
OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)
......
#
# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2005, 2012, 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
......@@ -34,6 +34,8 @@ SUNWprivate_1.1 {
JLI_ReportErrorMessageSys;
JLI_ReportMessage;
JLI_ReportExceptionDescription;
JLI_GetStdArgs;
JLI_GetStdArgc;
local:
*;
};
......@@ -104,7 +104,6 @@ static jboolean ParseArguments(int *pargc, char ***pargv,
static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
InvocationFunctions *ifn);
static jstring NewPlatformString(JNIEnv *env, char *s);
static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
......@@ -160,7 +159,7 @@ static jboolean IsWildCardEnabled();
* Running Java code in primordial thread caused many problems. We will
* create a new thread to invoke JVM. See 6316197 for more information.
*/
static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
static jlong initialHeapSize = 0; /* inital heap size */
......@@ -202,6 +201,14 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
InitLauncher(javaw);
DumpState();
if (JLI_IsTraceLauncher()) {
int i;
printf("Command line args:\n");
for (i = 0; i < argc ; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
AddOption("-Dsun.java.launcher.diag=true", NULL);
}
/*
* Make sure the specified version of the JRE is running.
......@@ -222,15 +229,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
*/
SelectVersion(argc, argv, &main_class);
if (JLI_IsTraceLauncher()) {
int i;
printf("Command line args:\n");
for (i = 0; i < argc ; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
AddOption("-Dsun.java.launcher.diag=true", NULL);
}
CreateExecutionEnvironment(&argc, &argv,
jrepath, sizeof(jrepath),
jvmpath, sizeof(jvmpath),
......@@ -435,8 +433,8 @@ JavaMain(void * _args)
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
/* Build platform specific argument array */
mainArgs = CreateApplicationArgs(env, argv, argc);
CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
/* Invoke main method. */
......@@ -1120,8 +1118,9 @@ InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
static jclass helperClass = NULL;
static jclass
GetLauncherHelperClass(JNIEnv *env) {
jclass
GetLauncherHelperClass(JNIEnv *env)
{
if (helperClass == NULL) {
NULL_CHECK0(helperClass = FindBootStrapClass(env,
"sun/launcher/LauncherHelper"));
......@@ -1165,7 +1164,7 @@ NewPlatformString(JNIEnv *env, char *s)
* Returns a new array of Java string objects for the specified
* array of platform strings.
*/
static jobjectArray
jobjectArray
NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
{
jarray cls;
......@@ -1210,7 +1209,7 @@ LoadMainClass(JNIEnv *env, int mode, char *name)
end = CounterGet();
printf("%ld micro seconds to load main class\n",
(long)(jint)Counter2Micros(end-start));
printf("----_JAVA_LAUNCHER_DEBUG----\n");
printf("----%s----\n", JLDEBUG_ENV_ENTRY);
}
return (jclass)result;
......@@ -1745,7 +1744,6 @@ FreeKnownVMs()
JLI_MemFree(knownVMs);
}
/*
* Displays the splash screen according to the jar file name
* and image file names stored in environment variables
......
......@@ -219,6 +219,10 @@ typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
const char *name));
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
jobjectArray CreateApplicationArgs(JNIEnv *env, char **strv, int argc);
jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
jclass GetLauncherHelperClass(JNIEnv *env);
int JNICALL JavaMain(void * args); /* entry point */
enum LaunchMode { // cf. sun.launcher.LauncherHelper
......
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -102,9 +102,9 @@ JLI_TraceLauncher(const char* fmt, ...)
void
JLI_SetTraceLauncher()
{
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
if (getenv(JLDEBUG_ENV_ENTRY) != 0) {
_launcher_debug = JNI_TRUE;
JLI_TraceLauncher("----_JAVA_LAUNCHER_DEBUG----\n");
JLI_TraceLauncher("----%s----\n", JLDEBUG_ENV_ENTRY);
}
}
......
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -30,6 +30,7 @@
#include <string.h>
#include <stdio.h>
#include <jni.h>
#define JLDEBUG_ENV_ENTRY "_JAVA_LAUNCHER_DEBUG"
void *JLI_MemAlloc(size_t size);
void *JLI_MemRealloc(void *ptr, size_t size);
......@@ -37,6 +38,14 @@ char *JLI_StringDup(const char *s1);
void JLI_MemFree(void *ptr);
int JLI_StrCCmp(const char *s1, const char* s2);
typedef struct {
char *arg;
jboolean has_wildcard;
} StdArg;
StdArg *JLI_GetStdArgs();
int JLI_GetStdArgc();
#define JLI_StrLen(p1) strlen((p1))
#define JLI_StrChr(p1, p2) strchr((p1), (p2))
#define JLI_StrRChr(p1, p2) strrchr((p1), (p2))
......@@ -58,6 +67,7 @@ int JLI_StrCCmp(const char *s1, const char* s2);
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
#define JLI_Snprintf _snprintf
void JLI_CmdToArgs(char *cmdline);
#else
#include <unistd.h>
#include <strings.h>
......
/*
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2012, 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
......@@ -87,22 +87,41 @@ WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
const jboolean const_javaw = JNI_TRUE;
__initenv = _environ;
margc = __argc;
margv = __argv;
#else /* JAVAW */
int
main(int argc, char ** argv)
main(int argc, char **argv)
{
int margc;
char** margv;
const jboolean const_javaw = JNI_FALSE;
#endif /* JAVAW */
#ifdef _WIN32
{
int i = 0;
if (getenv(JLDEBUG_ENV_ENTRY) != NULL) {
printf("Windows original main args:\n");
for (i = 0 ; i < __argc ; i++) {
printf("wwwd_args[%d] = %s\n", i, __argv[i]);
}
}
}
JLI_CmdToArgs(GetCommandLine());
margc = JLI_GetStdArgc();
// add one more to mark the end
margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *)));
{
int i = 0;
StdArg *stdargs = JLI_GetStdArgs();
for (i = 0 ; i < margc ; i++) {
margv[i] = stdargs[i].arg;
}
margv[i] = NULL;
}
#else /* *NIXES */
margc = argc;
margv = argv;
#endif /* JAVAW */
#endif /* WIN32 */
return JLI_Launch(margc, margv,
sizeof(const_jargs) / sizeof(char *), const_jargs,
sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
......
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
......@@ -129,11 +129,11 @@ struct WildcardIterator_
HANDLE handle;
char *firstFile; /* Stupid FindFirstFile...FindNextFile */
};
// since this is used repeatedly we keep it here.
static WIN32_FIND_DATA find_data;
static WildcardIterator
WildcardIterator_for(const char *wildcard)
{
WIN32_FIND_DATA find_data;
WildcardIterator it = NEW_(WildcardIterator);
HANDLE handle = FindFirstFile(wildcard, &find_data);
if (handle == INVALID_HANDLE_VALUE)
......@@ -146,7 +146,6 @@ WildcardIterator_for(const char *wildcard)
static char *
WildcardIterator_next(WildcardIterator it)
{
WIN32_FIND_DATA find_data;
if (it->firstFile != NULL) {
char *firstFile = it->firstFile;
it->firstFile = NULL;
......@@ -412,7 +411,7 @@ JLI_WildcardExpandClasspath(const char *classpath)
FileList_expandWildcards(fl);
expanded = FileList_join(fl, PATH_SEPARATOR);
FileList_free(fl);
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0)
if (getenv(JLDEBUG_ENV_ENTRY) != 0)
printf("Expanded wildcards:\n"
" before: \"%s\"\n"
" after : \"%s\"\n",
......
......@@ -48,6 +48,9 @@ import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import java.util.ArrayList;
......@@ -69,8 +72,6 @@ public enum LauncherHelper {
private static StringBuilder outBuf = new StringBuilder();
private static ResourceBundle javarb = null;
private static final String INDENT = " ";
private static final String VM_SETTINGS = "VM settings:";
private static final String PROP_SETTINGS = "Property settings:";
......@@ -78,6 +79,7 @@ public enum LauncherHelper {
// sync with java.c and sun.misc.VM
private static final String diagprop = "sun.java.launcher.diag";
final static boolean trace = sun.misc.VM.getSavedProperty(diagprop) != null;
private static final String defaultBundleName =
"sun.launcher.resources.launcher";
......@@ -428,7 +430,7 @@ public enum LauncherHelper {
if (msgKey != null) {
ostream.println(getLocalizedMessage(msgKey, args));
}
if (sun.misc.VM.getSavedProperty(diagprop) != null) {
if (trace) {
if (t != null) {
t.printStackTrace();
} else {
......@@ -532,4 +534,82 @@ public enum LauncherHelper {
}
return null; // keep the compiler happy
}
static String[] expandArgs(String[] argArray) {
List<StdArg> aList = new ArrayList<>();
for (String x : argArray) {
aList.add(new StdArg(x));
}
return expandArgs(aList);
}
static String[] expandArgs(List<StdArg> argList) {
ArrayList<String> out = new ArrayList<>();
if (trace) {
System.err.println("Incoming arguments:");
}
for (StdArg a : argList) {
if (trace) {
System.err.println(a);
}
if (a.needsExpansion) {
File x = new File(a.arg);
File parent = x.getParentFile();
String glob = x.getName();
if (parent == null) {
parent = new File(".");
}
try (DirectoryStream<Path> dstream =
Files.newDirectoryStream(parent.toPath(), glob)) {
int entries = 0;
for (Path p : dstream) {
out.add(p.normalize().toString());
entries++;
}
if (entries == 0) {
out.add(a.arg);
}
} catch (Exception e) {
out.add(a.arg);
if (trace) {
System.err.println("Warning: passing argument as-is " + a);
System.err.print(e);
}
}
} else {
out.add(a.arg);
}
}
String[] oarray = new String[out.size()];
out.toArray(oarray);
if (trace) {
System.err.println("Expanded arguments:");
for (String x : oarray) {
System.err.println(x);
}
}
return oarray;
}
/* duplicate of the native StdArg struct */
private static class StdArg {
final String arg;
final boolean needsExpansion;
StdArg(String arg, boolean expand) {
this.arg = arg;
this.needsExpansion = expand;
}
// protocol: first char indicates whether expansion is required
// 'T' = true ; needs expansion
// 'F' = false; needs no expansion
StdArg(String in) {
this.arg = in.substring(1);
needsExpansion = in.charAt(0) == 'T';
}
public String toString() {
return "StdArg{" + "arg=" + arg + ", needsExpansion=" + needsExpansion + '}';
}
}
}
......@@ -136,3 +136,4 @@ java.launcher.jar.error1=\
Error: An unexpected error occurred while trying to open file {0}
java.launcher.jar.error2=manifest not found in {0}
java.launcher.jar.error3=no main manifest attribute, in {0}
java.launcher.init.error=initialization error
此差异已折叠。
......@@ -502,3 +502,19 @@ FindBootStrapClass(JNIEnv *env, const char* classname)
return findBootClass(env, classname);
}
StdArg
*JLI_GetStdArgs()
{
return NULL;
}
int
JLI_GetStdArgc() {
return 0;
}
jobjectArray
CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
{
return NewPlatformStringArray(env, strv, argc);
}
......@@ -1357,3 +1357,89 @@ ProcessPlatformOption(const char *arg)
{
return JNI_FALSE;
}
/*
* At this point we have the arguments to the application, and we need to
* check with original stdargs in order to compare which of these truly
* needs expansion. cmdtoargs will specify this if it finds a bare
* (unquoted) argument containing a glob character(s) ie. * or ?
*/
jobjectArray
CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
{
int i, j, idx, tlen;
jobjectArray outArray, inArray;
char *ostart, *astart, **nargv;
jboolean needs_expansion = JNI_FALSE;
jmethodID mid;
int stdargc;
StdArg *stdargs;
jclass cls = GetLauncherHelperClass(env);
NULL_CHECK0(cls);
if (argc == 0) {
return NewPlatformStringArray(env, strv, argc);
}
// the holy grail we need to compare with.
stdargs = JLI_GetStdArgs();
stdargc = JLI_GetStdArgc();
// sanity check, this should never happen
if (argc > stdargc) {
JLI_TraceLauncher("Warning: app args is larger than the original, %d %d\n", argc, stdargc);
JLI_TraceLauncher("passing arguments as-is.\n");
return NewPlatformStringArray(env, strv, argc);
}
// sanity check, match the args we have, to the holy grail
idx = stdargc - argc;
ostart = stdargs[idx].arg;
astart = strv[0];
// sanity check, ensure that the first argument of the arrays are the same
if (JLI_StrCmp(ostart, astart) != 0) {
// some thing is amiss the args don't match
JLI_TraceLauncher("Warning: app args parsing error\n");
JLI_TraceLauncher("passing arguments as-is\n");
return NewPlatformStringArray(env, strv, argc);
}
// make a copy of the args which will be expanded in java if required.
nargv = (char **)JLI_MemAlloc(argc * sizeof(char*));
for (i = 0, j = idx; i < argc; i++, j++) {
jboolean arg_expand = (JLI_StrCmp(stdargs[j].arg, strv[i]) == 0)
? stdargs[j].has_wildcard
: JNI_FALSE;
if (needs_expansion == JNI_FALSE)
needs_expansion = arg_expand;
// indicator char + String + NULL terminator, the java method will strip
// out the first character, the indicator character, so no matter what
// we add the indicator
tlen = 1 + JLI_StrLen(strv[i]) + 1;
nargv[i] = (char *) JLI_MemAlloc(tlen);
JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]);
JLI_TraceLauncher("%s\n", nargv[i]);
}
if (!needs_expansion) {
// clean up any allocated memory and return back the old arguments
for (i = 0 ; i < argc ; i++) {
JLI_MemFree(nargv[i]);
}
JLI_MemFree(nargv);
return NewPlatformStringArray(env, strv, argc);
}
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,
"expandArgs",
"([Ljava/lang/String;)[Ljava/lang/String;"));
// expand the arguments that require expansion, the java method will strip
// out the indicator character.
inArray = NewPlatformStringArray(env, nargv, argc);
outArray = (*env)->CallStaticObjectMethod(env, cls, mid, inArray);
for (i = 0; i < argc; i++) {
JLI_MemFree(nargv[i]);
}
JLI_MemFree(nargv);
return outArray;
}
此差异已折叠。
......@@ -21,6 +21,12 @@
* questions.
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.Set;
......@@ -63,6 +69,8 @@ public class TestHelper {
static final String javawCmd;
static final String java64Cmd;
static final String javacCmd;
static final String jarCmd;
static final JavaCompiler compiler;
static final boolean debug = Boolean.getBoolean("TestHelper.Debug");
......@@ -131,6 +139,15 @@ public class TestHelper {
: new File(binDir, "javac");
javacCmd = javacCmdFile.getAbsolutePath();
File jarCmdFile = (isWindows)
? new File(binDir, "jar.exe")
: new File(binDir, "jar");
jarCmd = jarCmdFile.getAbsolutePath();
if (!jarCmdFile.canExecute()) {
throw new RuntimeException("java <" + TestHelper.jarCmd +
"> must exist and should be executable");
}
if (isWindows) {
File javawCmdFile = new File(binDir, "javaw.exe");
javawCmd = javawCmdFile.getAbsolutePath();
......@@ -158,6 +175,35 @@ public class TestHelper {
java64Cmd = null;
}
}
void run(String[] args) throws Exception {
int passed = 0, failed = 0;
final Pattern p = (args != null && args.length > 0)
? Pattern.compile(args[0])
: null;
for (Method m : this.getClass().getDeclaredMethods()) {
boolean selected = (p == null)
? m.isAnnotationPresent(Test.class)
: p.matcher(m.getName()).matches();
if (selected) {
try {
m.invoke(this, (Object[]) null);
System.out.println(m.getName() + ": OK");
passed++;
} catch (Throwable ex) {
System.out.printf("Test %s failed: %s %n", m, ex.getCause());
failed++;
}
}
}
System.out.printf("Passed: %d, Failed %d%n", passed, failed);
if (failed > 0) {
throw new RuntimeException("Tests failed: " + failed);
}
if (passed == 0 && failed == 0) {
throw new AssertionError("No test(s) selected: passed = " +
passed + ", failed = " + failed + " ??????????");
}
}
/*
* is a dual mode available in the test jdk
......@@ -395,6 +441,7 @@ public class TestHelper {
List<String> testOutput;
Map<String, String> env;
Throwable t;
boolean testStatus;
public TestResult(String str, int rv, List<String> oList,
Map<String, String> env, Throwable t) {
......@@ -405,6 +452,7 @@ public class TestHelper {
testOutput = oList;
this.env = env;
this.t = t;
testStatus = true;
}
void appendError(String x) {
......@@ -418,12 +466,14 @@ public class TestHelper {
void checkNegative() {
if (exitValue == 0) {
appendError("test must not return 0 exit value");
testStatus = false;
testExitValue++;
}
}
void checkPositive() {
if (exitValue != 0) {
testStatus = false;
appendError("test did not return 0 exit value");
testExitValue++;
}
......@@ -435,6 +485,7 @@ public class TestHelper {
boolean isZeroOutput() {
if (!testOutput.isEmpty()) {
testStatus = false;
appendError("No message from cmd please");
testExitValue++;
return false;
......@@ -444,6 +495,7 @@ public class TestHelper {
boolean isNotZeroOutput() {
if (testOutput.isEmpty()) {
testStatus = false;
appendError("Missing message");
testExitValue++;
return false;
......@@ -454,6 +506,7 @@ public class TestHelper {
@Override
public String toString() {
status.println("++++Begin Test Info++++");
status.println("Test Status: " + (testStatus ? "PASS" : "FAIL"));
status.println("++++Test Environment++++");
for (String x : env.keySet()) {
indentStatus(x + "=" + env.get(x));
......@@ -496,4 +549,10 @@ public class TestHelper {
return false;
}
}
/**
* Indicates that the annotated method is a test method.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {}
}
......@@ -160,7 +160,7 @@ public class ToolsOpts extends TestHelper {
for (String arg[] : optionPatterns) {
jpos = indexOfJoption(arg);
//Build a cmd string for output in results reporting.
String cmdString = javacCmd + JBCP_PREPEND + sTestJar;
String cmdString = javacCmd + " " + JBCP_PREPEND + sTestJar;
for (String opt : arg) {
cmdString = cmdString.concat(" " + opt);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册