Mercurial > hg > truffle
annotate src/share/tools/launcher/wildcard.c @ 9099:ed81c74f92ff
Cache boolean flags instead of full Annotation objects
author | Christian Wimmer <christian.wimmer@oracle.com> |
---|---|
date | Fri, 12 Apr 2013 16:05:56 -0700 |
parents | bad3bed4b323 |
children |
rev | line source |
---|---|
1985 | 1 /* |
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 /* | |
26 * Class-Path Wildcards | |
27 * | |
28 * The syntax for wildcards is a single asterisk. The class path | |
29 * foo/"*", e.g., loads all jar files in the directory named foo. | |
30 * (This requires careful quotation when used in shell scripts.) | |
31 * | |
32 * Only files whose names end in .jar or .JAR are matched. | |
33 * Files whose names end in .zip, or which have a particular | |
34 * magic number, regardless of filename extension, are not | |
35 * matched. | |
36 * | |
37 * Files are considered regardless of whether or not they are | |
38 * "hidden" in the UNIX sense, i.e., have names beginning with '.'. | |
39 * | |
40 * A wildcard only matches jar files, not class files in the same | |
41 * directory. If you want to load both class files and jar files from | |
42 * a single directory foo then you can say foo:foo/"*", or foo/"*":foo | |
43 * if you want the jar files to take precedence. | |
44 * | |
45 * Subdirectories are not searched recursively, i.e., foo/"*" only | |
46 * looks for jar files in foo, not in foo/bar, foo/baz, etc. | |
47 * | |
48 * Expansion of wildcards is done early, prior to the invocation of a | |
49 * program's main method, rather than late, during the class-loading | |
50 * process itself. Each element of the input class path containing a | |
51 * wildcard is replaced by the (possibly empty) sequence of elements | |
52 * generated by enumerating the jar files in the named directory. If | |
53 * the directory foo contains a.jar, b.jar, and c.jar, | |
54 * e.g., then the class path foo/"*" is expanded into | |
55 * foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value | |
56 * of the system property java.class.path. | |
57 * | |
58 * The order in which the jar files in a directory are enumerated in | |
59 * the expanded class path is not specified and may vary from platform | |
60 * to platform and even from moment to moment on the same machine. A | |
61 * well-constructed application should not depend upon any particular | |
62 * order. If a specific order is required then the jar files can be | |
63 * enumerated explicitly in the class path. | |
64 * | |
65 * The CLASSPATH environment variable is not treated any differently | |
66 * from the -classpath (equiv. -cp) command-line option, | |
67 * i.e. wildcards are honored in all these cases. | |
68 * | |
69 * Class-path wildcards are not honored in the Class-Path jar-manifest | |
70 * header. | |
71 * | |
72 * Class-path wildcards are honored not only by the Java launcher but | |
73 * also by most other command-line tools that accept class paths, and | |
74 * in particular by javac and javadoc. | |
75 * | |
76 * Class-path wildcards are not honored in any other kind of path, and | |
77 * especially not in the bootstrap class path, which is a mere | |
78 * artifact of our implementation and not something that developers | |
79 * should use. | |
80 * | |
81 * Classpath wildcards are only expanded in the Java launcher code, | |
82 * supporting the use of wildcards on the command line and in the | |
83 * CLASSPATH environment variable. We do not support the use of | |
84 * wildcards by applications that embed the JVM. | |
85 */ | |
86 | |
87 #include <stddef.h> | |
88 #include <stdio.h> | |
89 #include <stdlib.h> | |
90 #include <string.h> | |
91 #include <sys/types.h> | |
92 #include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */ | |
93 #include "jli_util.h" | |
94 | |
95 #ifdef _WIN32 | |
96 #include <windows.h> | |
97 #else /* Unix */ | |
98 #include <unistd.h> | |
99 #include <dirent.h> | |
100 #endif /* Unix */ | |
101 | |
102 static int | |
103 exists(const char* filename) | |
104 { | |
105 #ifdef _WIN32 | |
106 return _access(filename, 0) == 0; | |
107 #else | |
108 return access(filename, F_OK) == 0; | |
109 #endif | |
110 } | |
111 | |
112 #define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_))) | |
113 | |
114 /* | |
115 * Wildcard directory iteration. | |
116 * WildcardIterator_for(wildcard) returns an iterator. | |
117 * Each call to that iterator's next() method returns the basename | |
118 * of an entry in the wildcard's directory. The basename's memory | |
119 * belongs to the iterator. The caller is responsible for prepending | |
120 * the directory name and file separator, if necessary. | |
121 * When done with the iterator, call the close method to clean up. | |
122 */ | |
123 typedef struct WildcardIterator_* WildcardIterator; | |
124 | |
125 #ifdef _WIN32 | |
126 struct WildcardIterator_ | |
127 { | |
128 HANDLE handle; | |
129 char *firstFile; /* Stupid FindFirstFile...FindNextFile */ | |
130 }; | |
131 | |
132 static WildcardIterator | |
133 WildcardIterator_for(const char *wildcard) | |
134 { | |
135 WIN32_FIND_DATA find_data; | |
136 WildcardIterator it = NEW_(WildcardIterator); | |
137 HANDLE handle = FindFirstFile(wildcard, &find_data); | |
138 if (handle == INVALID_HANDLE_VALUE) | |
139 return NULL; | |
140 it->handle = handle; | |
141 it->firstFile = find_data.cFileName; | |
142 return it; | |
143 } | |
144 | |
145 static char * | |
146 WildcardIterator_next(WildcardIterator it) | |
147 { | |
148 WIN32_FIND_DATA find_data; | |
149 if (it->firstFile != NULL) { | |
150 char *firstFile = it->firstFile; | |
151 it->firstFile = NULL; | |
152 return firstFile; | |
153 } | |
154 return FindNextFile(it->handle, &find_data) | |
155 ? find_data.cFileName : NULL; | |
156 } | |
157 | |
158 static void | |
159 WildcardIterator_close(WildcardIterator it) | |
160 { | |
161 if (it) { | |
162 FindClose(it->handle); | |
163 JLI_MemFree(it->firstFile); | |
164 JLI_MemFree(it); | |
165 } | |
166 } | |
167 | |
168 #else /* Unix */ | |
169 struct WildcardIterator_ | |
170 { | |
171 DIR *dir; | |
172 }; | |
173 | |
174 static WildcardIterator | |
175 WildcardIterator_for(const char *wildcard) | |
176 { | |
177 DIR *dir; | |
178 int wildlen = strlen(wildcard); | |
179 if (wildlen < 2) { | |
180 dir = opendir("."); | |
181 } else { | |
182 char *dirname = JLI_StringDup(wildcard); | |
183 dirname[wildlen - 1] = '\0'; | |
184 dir = opendir(dirname); | |
185 JLI_MemFree(dirname); | |
186 } | |
187 if (dir == NULL) | |
188 return NULL; | |
189 else { | |
190 WildcardIterator it = NEW_(WildcardIterator); | |
191 it->dir = dir; | |
192 return it; | |
193 } | |
194 } | |
195 | |
196 static char * | |
197 WildcardIterator_next(WildcardIterator it) | |
198 { | |
199 struct dirent* dirp = readdir(it->dir); | |
200 return dirp ? dirp->d_name : NULL; | |
201 } | |
202 | |
203 static void | |
204 WildcardIterator_close(WildcardIterator it) | |
205 { | |
206 if (it) { | |
207 closedir(it->dir); | |
208 JLI_MemFree(it); | |
209 } | |
210 } | |
211 #endif /* Unix */ | |
212 | |
213 static int | |
214 equal(const char *s1, const char *s2) | |
215 { | |
216 return strcmp(s1, s2) == 0; | |
217 } | |
218 | |
219 /* | |
220 * FileList ADT - a dynamic list of C filenames | |
221 */ | |
222 struct FileList_ | |
223 { | |
224 char **files; | |
225 int size; | |
226 int capacity; | |
227 }; | |
228 typedef struct FileList_ *FileList; | |
229 | |
230 static FileList | |
231 FileList_new(int capacity) | |
232 { | |
233 FileList fl = NEW_(FileList); | |
234 fl->capacity = capacity; | |
235 fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0])); | |
236 fl->size = 0; | |
237 return fl; | |
238 } | |
239 | |
240 #ifdef DEBUG_WILDCARD | |
241 static void | |
242 FileList_print(FileList fl) | |
243 { | |
244 int i; | |
245 putchar('['); | |
246 for (i = 0; i < fl->size; i++) { | |
247 if (i > 0) printf(", "); | |
248 printf("\"%s\"",fl->files[i]); | |
249 } | |
250 putchar(']'); | |
251 } | |
252 #endif | |
253 | |
254 static void | |
255 FileList_free(FileList fl) | |
256 { | |
257 if (fl) { | |
258 if (fl->files) { | |
259 int i; | |
260 for (i = 0; i < fl->size; i++) | |
261 JLI_MemFree(fl->files[i]); | |
262 JLI_MemFree(fl->files); | |
263 } | |
264 JLI_MemFree(fl); | |
265 } | |
266 } | |
267 | |
268 static void | |
269 FileList_ensureCapacity(FileList fl, int capacity) | |
270 { | |
271 if (fl->capacity < capacity) { | |
272 while (fl->capacity < capacity) | |
273 fl->capacity *= 2; | |
274 fl->files = JLI_MemRealloc(fl->files, | |
275 fl->capacity * sizeof(fl->files[0])); | |
276 } | |
277 } | |
278 | |
279 static void | |
280 FileList_add(FileList fl, char *file) | |
281 { | |
282 FileList_ensureCapacity(fl, fl->size+1); | |
283 fl->files[fl->size++] = file; | |
284 } | |
285 | |
286 static void | |
287 FileList_addSubstring(FileList fl, const char *beg, int len) | |
288 { | |
289 char *filename = (char *) JLI_MemAlloc(len+1); | |
290 memcpy(filename, beg, len); | |
291 filename[len] = '\0'; | |
292 FileList_ensureCapacity(fl, fl->size+1); | |
293 fl->files[fl->size++] = filename; | |
294 } | |
295 | |
296 static char * | |
297 FileList_join(FileList fl, char sep) | |
298 { | |
299 int i; | |
300 int size; | |
301 char *path; | |
302 char *p; | |
303 for (i = 0, size = 1; i < fl->size; i++) | |
304 size += strlen(fl->files[i]) + 1; | |
305 | |
306 path = JLI_MemAlloc(size); | |
307 | |
308 for (i = 0, p = path; i < fl->size; i++) { | |
309 int len = strlen(fl->files[i]); | |
310 if (i > 0) *p++ = sep; | |
311 memcpy(p, fl->files[i], len); | |
312 p += len; | |
313 } | |
314 *p = '\0'; | |
315 | |
316 return path; | |
317 } | |
318 | |
319 static FileList | |
320 FileList_split(const char *path, char sep) | |
321 { | |
322 const char *p, *q; | |
323 int len = strlen(path); | |
324 int count; | |
325 FileList fl; | |
326 for (count = 1, p = path; p < path + len; p++) | |
327 count += (*p == sep); | |
328 fl = FileList_new(count); | |
329 for (p = path;;) { | |
330 for (q = p; q <= path + len; q++) { | |
331 if (*q == sep || *q == '\0') { | |
332 FileList_addSubstring(fl, p, q - p); | |
333 if (*q == '\0') | |
334 return fl; | |
335 p = q + 1; | |
336 } | |
337 } | |
338 } | |
339 } | |
340 | |
341 static int | |
342 isJarFileName(const char *filename) | |
343 { | |
344 int len = strlen(filename); | |
345 return (len >= 4) && | |
346 (filename[len - 4] == '.') && | |
347 (equal(filename + len - 3, "jar") || | |
348 equal(filename + len - 3, "JAR")) && | |
349 /* Paranoia: Maybe filename is "DIR:foo.jar" */ | |
350 (strchr(filename, PATH_SEPARATOR) == NULL); | |
351 } | |
352 | |
353 static char * | |
354 wildcardConcat(const char *wildcard, const char *basename) | |
355 { | |
356 int wildlen = strlen(wildcard); | |
357 int baselen = strlen(basename); | |
358 char *filename = (char *) JLI_MemAlloc(wildlen + baselen); | |
359 /* Replace the trailing '*' with basename */ | |
360 memcpy(filename, wildcard, wildlen-1); | |
361 memcpy(filename+wildlen-1, basename, baselen+1); | |
362 return filename; | |
363 } | |
364 | |
365 static FileList | |
366 wildcardFileList(const char *wildcard) | |
367 { | |
368 const char *basename; | |
369 FileList fl = FileList_new(16); | |
370 WildcardIterator it = WildcardIterator_for(wildcard); | |
9058
bad3bed4b323
8006006: [parfait] Memory leak at hotspot/src/share/tools/launcher/wildcard.c
ccheung
parents:
1985
diff
changeset
|
371 if (it == NULL) { |
bad3bed4b323
8006006: [parfait] Memory leak at hotspot/src/share/tools/launcher/wildcard.c
ccheung
parents:
1985
diff
changeset
|
372 FileList_free(fl); |
1985 | 373 return NULL; |
9058
bad3bed4b323
8006006: [parfait] Memory leak at hotspot/src/share/tools/launcher/wildcard.c
ccheung
parents:
1985
diff
changeset
|
374 } |
1985 | 375 while ((basename = WildcardIterator_next(it)) != NULL) |
376 if (isJarFileName(basename)) | |
377 FileList_add(fl, wildcardConcat(wildcard, basename)); | |
378 WildcardIterator_close(it); | |
379 return fl; | |
380 } | |
381 | |
382 static int | |
383 isWildcard(const char *filename) | |
384 { | |
385 int len = strlen(filename); | |
386 return (len > 0) && | |
387 (filename[len - 1] == '*') && | |
388 (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) && | |
389 (! exists(filename)); | |
390 } | |
391 | |
392 static void | |
393 FileList_expandWildcards(FileList fl) | |
394 { | |
395 int i, j; | |
396 for (i = 0; i < fl->size; i++) { | |
397 if (isWildcard(fl->files[i])) { | |
398 FileList expanded = wildcardFileList(fl->files[i]); | |
399 if (expanded != NULL && expanded->size > 0) { | |
400 JLI_MemFree(fl->files[i]); | |
401 FileList_ensureCapacity(fl, fl->size + expanded->size); | |
402 for (j = fl->size - 1; j >= i+1; j--) | |
403 fl->files[j+expanded->size-1] = fl->files[j]; | |
404 for (j = 0; j < expanded->size; j++) | |
405 fl->files[i+j] = expanded->files[j]; | |
406 i += expanded->size - 1; | |
407 fl->size += expanded->size - 1; | |
408 /* fl expropriates expanded's elements. */ | |
409 expanded->size = 0; | |
410 } | |
411 FileList_free(expanded); | |
412 } | |
413 } | |
414 } | |
415 | |
416 const char * | |
417 JLI_WildcardExpandClasspath(const char *classpath) | |
418 { | |
419 char *expanded; | |
420 FileList fl; | |
421 | |
422 if (strchr(classpath, '*') == NULL) | |
423 return classpath; | |
424 fl = FileList_split(classpath, PATH_SEPARATOR); | |
425 FileList_expandWildcards(fl); | |
426 expanded = FileList_join(fl, PATH_SEPARATOR); | |
427 FileList_free(fl); | |
428 if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) | |
429 printf("Expanded wildcards:\n" | |
430 " before: \"%s\"\n" | |
431 " after : \"%s\"\n", | |
432 classpath, expanded); | |
433 return expanded; | |
434 } | |
435 | |
436 #ifdef DEBUG_WILDCARD | |
437 static void | |
438 wildcardExpandArgv(const char ***argv) | |
439 { | |
440 int i; | |
441 for (i = 0; (*argv)[i]; i++) { | |
442 if (equal((*argv)[i], "-cp") || | |
443 equal((*argv)[i], "-classpath")) { | |
444 i++; | |
445 (*argv)[i] = wildcardExpandClasspath((*argv)[i]); | |
446 } | |
447 } | |
448 } | |
449 | |
450 static void | |
451 debugPrintArgv(char *argv[]) | |
452 { | |
453 int i; | |
454 putchar('['); | |
455 for (i = 0; argv[i]; i++) { | |
456 if (i > 0) printf(", "); | |
457 printf("\"%s\"", argv[i]); | |
458 } | |
459 printf("]\n"); | |
460 } | |
461 | |
462 int | |
463 main(int argc, char *argv[]) | |
464 { | |
465 argv[0] = "java"; | |
466 wildcardExpandArgv((const char***)&argv); | |
467 debugPrintArgv(argv); | |
468 /* execvp("java", argv); */ | |
469 return 0; | |
470 } | |
471 #endif /* DEBUG_WILDCARD */ | |
472 | |
473 /* Cute little perl prototype implementation.... | |
474 | |
475 my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":"; | |
476 | |
477 sub expand($) { | |
478 opendir DIR, $_[0] or return $_[0]; | |
479 join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR; | |
480 } | |
481 | |
482 sub munge($) { | |
483 join $sep, | |
484 map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0]; | |
485 } | |
486 | |
487 for (my $i = 0; $i < @ARGV - 1; $i++) { | |
488 $ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/; | |
489 } | |
490 | |
491 $ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH}; | |
492 @ARGV = ("java", @ARGV); | |
493 print "@ARGV\n"; | |
494 exec @ARGV; | |
495 | |
496 */ |