Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/Imports.java
38918 views
1
/*
2
* Copyright (c) 1994, 2003, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.tools.java;
27
28
import java.util.Hashtable;
29
import java.util.Vector;
30
import java.util.Enumeration;
31
import java.util.List;
32
import java.util.Collections;
33
import java.io.IOException;
34
35
/**
36
* This class describes the classes and packages imported
37
* from a source file. A Hashtable called bindings is maintained
38
* to quickly map symbol names to classes. This table is flushed
39
* everytime a new import is added.
40
*
41
* A class name is resolved as follows:
42
* - if it is a qualified name then return the corresponding class
43
* - if the name corresponds to an individually imported class then return that class
44
* - check if the class is defined in any of the imported packages,
45
* if it is then return it, make sure it is defined in only one package
46
* - assume that the class is defined in the current package
47
*
48
* WARNING: The contents of this source file are not part of any
49
* supported API. Code that depends on them does so at its own risk:
50
* they are subject to change or removal without notice.
51
*/
52
53
public
54
class Imports implements Constants {
55
/**
56
* The current package, which is implicitly imported,
57
* and has precedence over other imported packages.
58
*/
59
Identifier currentPackage = idNull;
60
61
/**
62
* A location for the current package declaration. Used to
63
* report errors against the current package.
64
*/
65
long currentPackageWhere = 0;
66
67
/**
68
* The imported classes, including memoized imports from packages.
69
*/
70
Hashtable classes = new Hashtable();
71
72
/**
73
* The imported package identifiers. This will not contain duplicate
74
* imports for the same package. It will also not contain the
75
* current package.
76
*/
77
Vector packages = new Vector();
78
79
/**
80
* The (originally) imported classes.
81
* A vector of IdentifierToken.
82
*/
83
Vector singles = new Vector();
84
85
/**
86
* Are the import names checked yet?
87
*/
88
protected int checked;
89
90
/**
91
* Constructor, always import java.lang.
92
*/
93
public Imports(Environment env) {
94
addPackage(idJavaLang);
95
}
96
97
/**
98
* Check the names of the imports.
99
*/
100
public synchronized void resolve(Environment env) {
101
if (checked != 0) {
102
return;
103
}
104
checked = -1;
105
106
// After all class information has been read, now we can
107
// safely inspect import information for errors.
108
// If we did this before all parsing was finished,
109
// we could get vicious circularities, since files can
110
// import each others' classes.
111
112
// A note: the resolution of the package java.lang takes place
113
// in the sun.tools.javac.BatchEnvironment#setExemptPackages().
114
115
// Make sure that the current package's name does not collide
116
// with the name of an existing class. (bug 4101529)
117
//
118
// This change has been backed out because, on WIN32, it
119
// failed to distinguish between java.awt.event and
120
// java.awt.Event when looking for a directory. We will
121
// add this back in later.
122
//
123
// if (currentPackage != idNull) {
124
// Identifier resolvedName =
125
// env.resolvePackageQualifiedName(currentPackage);
126
//
127
// Identifier className = resolvedName.getTopName();
128
//
129
// if (importable(className, env)) {
130
// // The name of the current package is also the name
131
// // of a class.
132
// env.error(currentPackageWhere, "package.class.conflict",
133
// currentPackage, className);
134
// }
135
// }
136
137
Vector resolvedPackages = new Vector();
138
for (Enumeration e = packages.elements() ; e.hasMoreElements() ;) {
139
IdentifierToken t = (IdentifierToken)e.nextElement();
140
Identifier nm = t.getName();
141
long where = t.getWhere();
142
143
// Check to see if this package is exempt from the "exists"
144
// check. See the note in
145
// sun.tools.javac.BatchEnvironment#setExemptPackages()
146
// for more information.
147
if (env.isExemptPackage(nm)) {
148
resolvedPackages.addElement(t);
149
continue;
150
}
151
152
// (Note: This code is moved from BatchParser.importPackage().)
153
try {
154
Identifier rnm = env.resolvePackageQualifiedName(nm);
155
if (importable(rnm, env)) {
156
// This name is a real class; better not be a package too.
157
if (env.getPackage(rnm.getTopName()).exists()) {
158
env.error(where, "class.and.package",
159
rnm.getTopName());
160
}
161
// Pass an "inner" name to the imports.
162
if (!rnm.isInner())
163
rnm = Identifier.lookupInner(rnm, idNull);
164
nm = rnm;
165
} else if (!env.getPackage(nm).exists()) {
166
env.error(where, "package.not.found", nm, "import");
167
} else if (rnm.isInner()) {
168
// nm exists, and rnm.getTopName() is a parent package
169
env.error(where, "class.and.package", rnm.getTopName());
170
}
171
resolvedPackages.addElement(new IdentifierToken(where, nm));
172
} catch (IOException ee) {
173
env.error(where, "io.exception", "import");
174
}
175
}
176
packages = resolvedPackages;
177
178
for (Enumeration e = singles.elements() ; e.hasMoreElements() ;) {
179
IdentifierToken t = (IdentifierToken)e.nextElement();
180
Identifier nm = t.getName();
181
long where = t.getWhere();
182
Identifier pkg = nm.getQualifier();
183
184
// (Note: This code is moved from BatchParser.importClass().)
185
nm = env.resolvePackageQualifiedName(nm);
186
if (!env.classExists(nm.getTopName())) {
187
env.error(where, "class.not.found", nm, "import");
188
}
189
190
// (Note: This code is moved from Imports.addClass().)
191
Identifier snm = nm.getFlatName().getName();
192
193
// make sure it isn't already imported explicitly
194
Identifier className = (Identifier)classes.get(snm);
195
if (className != null) {
196
Identifier f1 = Identifier.lookup(className.getQualifier(),
197
className.getFlatName());
198
Identifier f2 = Identifier.lookup(nm.getQualifier(),
199
nm.getFlatName());
200
if (!f1.equals(f2)) {
201
env.error(where, "ambig.class", nm, className);
202
}
203
}
204
classes.put(snm, nm);
205
206
207
// The code here needs to check to see, if we
208
// are importing an inner class, that all of its
209
// enclosing classes are visible to us. To check this,
210
// we need to construct a definition for the class.
211
// The code here used to call...
212
//
213
// ClassDefinition def = env.getClassDefinition(nm);
214
//
215
// ...but that interfered with the basicCheck()'ing of
216
// interfaces in certain cases (bug no. 4086139). Never
217
// fear. Instead we load the class with a call to the
218
// new getClassDefinitionNoCheck() which does no basicCheck() and
219
// lets us answer the questions we are interested in w/o
220
// interfering with the demand-driven nature of basicCheck().
221
222
try {
223
// Get a declaration
224
ClassDeclaration decl = env.getClassDeclaration(nm);
225
226
// Get the definition (no env argument)
227
ClassDefinition def = decl.getClassDefinitionNoCheck(env);
228
229
// Get the true name of the package containing this class.
230
// `pkg' from above is insufficient. It includes the
231
// names of our enclosing classes. Fix for 4086815.
232
Identifier importedPackage = def.getName().getQualifier();
233
234
// Walk out the outerClass chain, ensuring that each level
235
// is visible from our perspective.
236
for (; def != null; def = def.getOuterClass()) {
237
if (def.isPrivate()
238
|| !(def.isPublic()
239
|| importedPackage.equals(currentPackage))) {
240
env.error(where, "cant.access.class", def);
241
break;
242
}
243
}
244
} catch (AmbiguousClass ee) {
245
env.error(where, "ambig.class", ee.name1, ee.name2);
246
} catch (ClassNotFound ee) {
247
env.error(where, "class.not.found", ee.name, "import");
248
}
249
}
250
checked = 1;
251
}
252
253
/**
254
* Lookup a class, given the current set of imports,
255
* AmbiguousClass exception is thrown if the name can be
256
* resolved in more than one way. A ClassNotFound exception
257
* is thrown if the class is not found in the imported classes
258
* and packages.
259
*/
260
public synchronized Identifier resolve(Environment env, Identifier nm) throws ClassNotFound {
261
if (tracing) env.dtEnter("Imports.resolve: " + nm);
262
263
// If the class has the special ambiguous prefix, then we will
264
// get the original AmbiguousClass exception by removing the
265
// prefix and proceeding in the normal fashion.
266
// (part of solution for 4059855)
267
if (nm.hasAmbigPrefix()) {
268
nm = nm.removeAmbigPrefix();
269
}
270
271
if (nm.isQualified()) {
272
// Don't bother it is already qualified
273
if (tracing) env.dtExit("Imports.resolve: QUALIFIED " + nm);
274
return nm;
275
}
276
277
if (checked <= 0) {
278
checked = 0;
279
resolve(env);
280
}
281
282
// Check if it was imported before
283
Identifier className = (Identifier)classes.get(nm);
284
if (className != null) {
285
if (tracing) env.dtExit("Imports.resolve: PREVIOUSLY IMPORTED " + nm);
286
return className;
287
}
288
289
// Note: the section below has changed a bit during the fix
290
// for bug 4093217. The current package is no longer grouped
291
// with the rest of the import-on-demands; it is now checked
292
// separately. Also, the list of import-on-demands is now
293
// guarranteed to be duplicate-free, so the code below can afford
294
// to be a bit simpler.
295
296
// First we look in the current package. The current package
297
// is given precedence over the rest of the import-on-demands,
298
// which means, among other things, that a class in the current
299
// package cannot be ambiguous.
300
Identifier id = Identifier.lookup(currentPackage, nm);
301
if (importable(id, env)) {
302
className = id;
303
} else {
304
// If it isn't in the current package, try to find it in
305
// our import-on-demands.
306
Enumeration e = packages.elements();
307
while (e.hasMoreElements()) {
308
IdentifierToken t = (IdentifierToken)e.nextElement();
309
id = Identifier.lookup(t.getName(), nm);
310
311
if (importable(id, env)) {
312
if (className == null) {
313
// We haven't found any other matching classes yet.
314
// Set className to what we've found and continue
315
// looking for an ambiguity.
316
className = id;
317
} else {
318
if (tracing)
319
env.dtExit("Imports.resolve: AMBIGUOUS " + nm);
320
321
// We've found an ambiguity.
322
throw new AmbiguousClass(className, id);
323
}
324
}
325
}
326
}
327
328
// Make sure a class was found
329
if (className == null) {
330
if (tracing) env.dtExit("Imports.resolve: NOT FOUND " + nm);
331
throw new ClassNotFound(nm);
332
}
333
334
// Remember the binding
335
classes.put(nm, className);
336
if (tracing) env.dtExit("Imports.resolve: FIRST IMPORT " + nm);
337
return className;
338
}
339
340
/**
341
* Check to see if 'id' names an importable class in `env'.
342
* This method was made public and static for utility.
343
*/
344
static public boolean importable(Identifier id, Environment env) {
345
if (!id.isInner()) {
346
return env.classExists(id);
347
} else if (!env.classExists(id.getTopName())) {
348
return false;
349
} else {
350
// load the top class and look inside it
351
try {
352
// There used to be a call to...
353
// env.getClassDeclaration(id.getTopName());
354
// ...here. It has been replaced with the
355
// two statements below. These should be functionally
356
// the same except for the fact that
357
// getClassDefinitionNoCheck() does not call
358
// basicCheck(). This allows us to avoid a circular
359
// need to do basicChecking that can arise with
360
// certain patterns of importing and inheritance.
361
// This is a fix for a variant of bug 4086139.
362
//
363
// Note: the special case code in env.getClassDefinition()
364
// which handles inner class names is not replicated below.
365
// This should be okay, as we are looking up id.getTopName(),
366
// not id.
367
ClassDeclaration decl =
368
env.getClassDeclaration(id.getTopName());
369
ClassDefinition c =
370
decl.getClassDefinitionNoCheck(env);
371
372
return c.innerClassExists(id.getFlatName().getTail());
373
} catch (ClassNotFound ee) {
374
return false;
375
}
376
}
377
}
378
379
/**
380
* Suppose a resolve() call has failed.
381
* This routine can be used silently to give a reasonable
382
* default qualification (the current package) to the identifier.
383
* This decision is recorded for future reference.
384
*/
385
public synchronized Identifier forceResolve(Environment env, Identifier nm) {
386
if (nm.isQualified())
387
return nm;
388
389
Identifier className = (Identifier)classes.get(nm);
390
if (className != null) {
391
return className;
392
}
393
394
className = Identifier.lookup(currentPackage, nm);
395
396
classes.put(nm, className);
397
return className;
398
}
399
400
/**
401
* Add a class import
402
*/
403
public synchronized void addClass(IdentifierToken t) {
404
singles.addElement(t);
405
}
406
// for compatibility
407
public void addClass(Identifier nm) throws AmbiguousClass {
408
addClass(new IdentifierToken(nm));
409
}
410
411
/**
412
* Add a package import, or perhaps an inner class scope.
413
* Ignore any duplicate imports.
414
*/
415
public synchronized void addPackage(IdentifierToken t) {
416
final Identifier name = t.getName();
417
418
// If this is a duplicate import for the current package,
419
// ignore it.
420
if (name == currentPackage) {
421
return;
422
}
423
424
// If this is a duplicate of a package which has already been
425
// added to the list, ignore it.
426
final int size = packages.size();
427
for (int i = 0; i < size; i++) {
428
if (name == ((IdentifierToken)packages.elementAt(i)).getName()) {
429
return;
430
}
431
}
432
433
// Add the package to the list.
434
packages.addElement(t);
435
}
436
// for compatibility
437
public void addPackage(Identifier id) {
438
addPackage(new IdentifierToken(id));
439
}
440
441
/**
442
* Specify the current package with an IdentifierToken.
443
*/
444
public synchronized void setCurrentPackage(IdentifierToken t) {
445
currentPackage = t.getName();
446
currentPackageWhere = t.getWhere();
447
}
448
449
/**
450
* Specify the current package
451
*/
452
public synchronized void setCurrentPackage(Identifier id) {
453
currentPackage = id;
454
}
455
456
/**
457
* Report the current package
458
*/
459
public Identifier getCurrentPackage() {
460
return currentPackage;
461
}
462
463
/**
464
* Return an unmodifiable list of IdentifierToken representing
465
* packages specified as imports.
466
*/
467
public List getImportedPackages() {
468
return Collections.unmodifiableList(packages);
469
}
470
471
/**
472
* Return an unmodifiable list of IdentifierToken representing
473
* classes specified as imports.
474
*/
475
public List getImportedClasses() {
476
return Collections.unmodifiableList(singles);
477
}
478
479
/**
480
* Extend an environment with my resolve() method.
481
*/
482
public Environment newEnvironment(Environment env) {
483
return new ImportEnvironment(env, this);
484
}
485
}
486
487
final
488
class ImportEnvironment extends Environment {
489
Imports imports;
490
491
ImportEnvironment(Environment env, Imports imports) {
492
super(env, env.getSource());
493
this.imports = imports;
494
}
495
496
public Identifier resolve(Identifier nm) throws ClassNotFound {
497
return imports.resolve(this, nm);
498
}
499
500
public Imports getImports() {
501
return imports;
502
}
503
}
504
505