-
Notifications
You must be signed in to change notification settings - Fork 230
Expand file tree
/
Copy pathSysPackageManager.java
More file actions
260 lines (226 loc) · 8.75 KB
/
Copy pathSysPackageManager.java
File metadata and controls
260 lines (226 loc) · 8.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
// Copyright (c) Corporation for National Research Initiatives
// Copyright 2000 Samuele Pedroni
package org.python.core.packagecache;
import org.python.core.Py;
import org.python.core.PyJavaPackage;
import org.python.core.PyList;
import org.python.core.PySystemState;
import org.python.core.RegistryKey;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.ProviderNotFoundException;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* System package manager. Used by org.python.core.PySystemState.
*/
public class SysPackageManager extends PathPackageManager {
private static Logger pkglog = Logger.getLogger("org.python.package");
@Override
protected void message(String msg, Object... params) {
pkglog.log(Level.INFO, msg, params);
}
@Override
protected void warning(String msg, Object... params) {
pkglog.log(Level.WARNING, msg, params);
}
@Override
protected void comment(String msg, Object... params) {
pkglog.log(Level.CONFIG, msg, params);
}
@Override
protected void debug(String msg, Object... params) {
pkglog.log(Level.FINE, msg, params);
}
public SysPackageManager(File cachedir, Properties registry) {
if (useCacheDir(cachedir)) {
initCache();
findAllPackages(registry);
saveCache();
}
}
@Override
public void addJar(String jarfile, boolean cache) {
addJarToPackages(new File(jarfile), cache);
if (cache) {
saveCache();
}
}
@Override
public void addJarDir(String jdir, boolean cache) {
addJarDir(jdir, cache, cache);
}
/**
* Index the contents of every JAR or ZIP in a directory.
*
* @param jdir directory containing some JAR or ZIP files
* @param cache
* @param saveCache
*/
private void addJarDir(String jdir, boolean cache, boolean saveCache) {
File file = new File(jdir);
String[] files = file.list();
if (files != null) {
// jdir is a directory, enumerated in the array files
for (int i = 0; i < files.length; i++) {
String entry = files[i];
if (entry.endsWith(".jar") || entry.endsWith(".zip")) {
addJarToPackages(new File(jdir, entry), cache);
}
}
if (saveCache) {
saveCache();
}
}
}
/**
* Scan a path that contains directory specifiers, and within each directory, find every JAR or
* ZIP archive and add it to the list of archives searched for packages. (This means, index it.)
* Non-directory entries are ignored.
*/
private void addJarPath(String path) {
StringTokenizer tok = new StringTokenizer(path, java.io.File.pathSeparator);
while (tok.hasMoreTokens()) {
// ??pending: do jvms trim? how is interpreted entry=""?
String entry = tok.nextToken();
// Use the extra flag to defer writing out the cache.
addJarDir(entry, true, false);
}
}
/**
* Index the packages in every module in a directory. Entries in the directory that are not modules
* (do not contain a {@code module-info.class}) are ignored. Only modules exploded on the file system of this path are (currently) supported,
* and at the time of writing, we only use this method on the {@code jrt:} file system.
*
* @param moduleDir directory containing some modules
*/
private void addModuleDir(final Path moduleDir) {
try {
// Walk the directory tree with this visitor
FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
// System.out.println(dir);
if (dir.equals(moduleDir)) {
// Ignore this, it's just the root)
} else if (Files.exists(dir.resolve("module-info.class"))) {
// dir is a module: scan packages from it.
addModuleToPackages(dir);
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
};
Files.walkFileTree(moduleDir, visitor);
} catch (IOException e) {
warning("error enumerating Java modules in {0}: {1}", moduleDir, e.getMessage());
}
}
/**
* Walk the packages found in paths specified indirectly through the given {@code Properties}
* object.
*
* @param registry in practice, the Jython registry
*/
private void findAllPackages(Properties registry) {
/*
* Packages in the Java runtime environment are enumerated in the jrt file system (from Java
* 9 onwards), or in JARs and directories designated by the properties
* sun.boot.class.path and java.ext.dirs (up to Java 8).
*/
String defaultClassPaths, defaultDirectories;
try {
// Support for the modular JVM (particular packages).
FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
addModuleDir(jrtfs.getPath("/modules/"));
defaultClassPaths = "java.class.path";
defaultDirectories = "";
} catch (ProviderNotFoundException e) {
// Running on a JVM before Java 9: add boot class path and optional extensions.
defaultClassPaths = "java.class.path,sun.boot.class.path";
defaultDirectories = "java.ext.dirs";
}
Set<String> cps = split(registry.getProperty(
RegistryKey.PYTHON_PACKAGES_PATHS, defaultClassPaths));
for (String name : cps) {
// Each property is a class-path string containing JARS and directories
String classPath = registry.getProperty(name);
if (classPath != null) {
// Each path may be a mixture of directory and JAR specifiers (source of packages)
addClassPath(classPath);
}
}
Set<String> directories =
split(registry.getProperty(
RegistryKey.PYTHON_PACKAGES_DIRECTORIES,
defaultDirectories));
for (String name : directories) {
// Each property defines a path string containing directories
String path = registry.getProperty(name);
if (path != null) {
// Add the JAR/ZIP archives in those directories to the search path for packages
addJarPath(path);
}
}
String fakepath = registry.getProperty(
RegistryKey.PYTHON_PACKAGES_FAKEPATH, null);
if (fakepath != null) {
addClassPath(fakepath);
}
}
@Override
public void notifyPackageImport(String pkg, String name) {
if (pkg != null && pkg.length() > 0) {
comment("import {0} # as java package {1}.{0}", name);
} else {
comment("import {0} # as java package", name);
}
}
@Override
public Class findClass(String pkg, String name) {
Class c = super.findClass(pkg, name);
if (c != null) {
comment("import {0} # as java class", name);
}
return c;
}
@Override
public Class findClass(String pkg, String name, String reason) {
if (pkg != null && pkg.length() > 0) {
name = pkg + '.' + name;
}
return Py.findClassEx(name, reason);
}
@Override
public PyList doDir(PyJavaPackage jpkg, boolean instantiate, boolean exclpkgs) {
PyList basic = basicDoDir(jpkg, instantiate, exclpkgs);
PyList ret = new PyList();
doDir(this.searchPath, ret, jpkg, instantiate, exclpkgs);
PySystemState sys = Py.getSystemState();
if (sys.getClassLoader() == null) {
doDir(sys.path, ret, jpkg, instantiate, exclpkgs);
}
return merge(basic, ret);
}
@Override
public boolean packageExists(String pkg, String name) {
if (packageExists(this.searchPath, pkg, name)) {
return true;
} else {
PySystemState sys = Py.getSystemState();
return sys.getClassLoader() == null && packageExists(sys.path, pkg, name);
}
}
}