Source Code Cross Referenced for ClassReader.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » javac » jvm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules com.sun » tools » com.sun.tools.javac.jvm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.tools.javac.jvm;
0027:
0028:        import java.io.*;
0029:        import java.net.URI;
0030:        import java.nio.CharBuffer;
0031:        import java.util.EnumSet;
0032:        import java.util.HashMap;
0033:        import java.util.Map;
0034:        import java.util.Set;
0035:        import javax.lang.model.SourceVersion;
0036:        import javax.tools.JavaFileObject;
0037:        import javax.tools.JavaFileManager;
0038:        import javax.tools.StandardJavaFileManager;
0039:
0040:        import com.sun.tools.javac.comp.Annotate;
0041:        import com.sun.tools.javac.code.*;
0042:        import com.sun.tools.javac.code.Type.*;
0043:        import com.sun.tools.javac.code.Symbol.*;
0044:        import com.sun.tools.javac.code.Symtab;
0045:        import com.sun.tools.javac.util.*;
0046:        import com.sun.tools.javac.util.List;
0047:
0048:        import static com.sun.tools.javac.code.Flags.*;
0049:        import static com.sun.tools.javac.code.Kinds.*;
0050:        import static com.sun.tools.javac.code.TypeTags.*;
0051:        import com.sun.tools.javac.jvm.ClassFile.NameAndType;
0052:        import javax.tools.JavaFileManager.Location;
0053:        import static javax.tools.StandardLocation.*;
0054:
0055:        /** This class provides operations to read a classfile into an internal
0056:         *  representation. The internal representation is anchored in a
0057:         *  ClassSymbol which contains in its scope symbol representations
0058:         *  for all other definitions in the classfile. Top-level Classes themselves
0059:         *  appear as members of the scopes of PackageSymbols.
0060:         *
0061:         *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
0062:         *  you write code that depends on this, you do so at your own risk.
0063:         *  This code and its internal interfaces are subject to change or
0064:         *  deletion without notice.</b>
0065:         */
0066:        @Version("@(#)ClassReader.java	1.142 07/05/05")
0067:        public class ClassReader extends ClassFile implements  Completer {
0068:            /** The context key for the class reader. */
0069:            protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<ClassReader>();
0070:
0071:            Annotate annotate;
0072:
0073:            /** Switch: verbose output.
0074:             */
0075:            boolean verbose;
0076:
0077:            /** Switch: check class file for correct minor version, unrecognized
0078:             *  attributes.
0079:             */
0080:            boolean checkClassFile;
0081:
0082:            /** Switch: read constant pool and code sections. This switch is initially
0083:             *  set to false but can be turned on from outside.
0084:             */
0085:            public boolean readAllOfClassFile = false;
0086:
0087:            /** Switch: read GJ signature information.
0088:             */
0089:            boolean allowGenerics;
0090:
0091:            /** Switch: read varargs attribute.
0092:             */
0093:            boolean allowVarargs;
0094:
0095:            /** Switch: allow annotations.
0096:             */
0097:            boolean allowAnnotations;
0098:
0099:            /** Switch: preserve parameter names from the variable table.
0100:             */
0101:            public boolean saveParameterNames;
0102:
0103:            /**
0104:             * Switch: cache completion failures unless -XDdev is used
0105:             */
0106:            private boolean cacheCompletionFailure;
0107:
0108:            /**
0109:             * Switch: prefer source files instead of newer when both source 
0110:             * and class are available
0111:             **/
0112:            public boolean preferSource;
0113:
0114:            /** The log to use for verbose output
0115:             */
0116:            final Log log;
0117:
0118:            /** The symbol table. */
0119:            Symtab syms;
0120:
0121:            Types types;
0122:
0123:            /** The name table. */
0124:            final Name.Table names;
0125:
0126:            /** Force a completion failure on this name
0127:             */
0128:            final Name completionFailureName;
0129:
0130:            /** Access to files
0131:             */
0132:            private final JavaFileManager fileManager;
0133:
0134:            /** Can be reassigned from outside:
0135:             *  the completer to be used for ".java" files. If this remains unassigned
0136:             *  ".java" files will not be loaded.
0137:             */
0138:            public SourceCompleter sourceCompleter = null;
0139:
0140:            /** A hashtable containing the encountered top-level and member classes,
0141:             *  indexed by flat names. The table does not contain local classes.
0142:             */
0143:            private Map<Name, ClassSymbol> classes;
0144:
0145:            /** A hashtable containing the encountered packages.
0146:             */
0147:            private Map<Name, PackageSymbol> packages;
0148:
0149:            /** The current scope where type variables are entered.
0150:             */
0151:            protected Scope typevars;
0152:
0153:            /** The path name of the class file currently being read.
0154:             */
0155:            protected JavaFileObject currentClassFile = null;
0156:
0157:            /** The class or method currently being read.
0158:             */
0159:            protected Symbol currentOwner = null;
0160:
0161:            /** The buffer containing the currently read class file.
0162:             */
0163:            byte[] buf = new byte[0x0fff0];
0164:
0165:            /** The current input pointer.
0166:             */
0167:            int bp;
0168:
0169:            /** The objects of the constant pool.
0170:             */
0171:            Object[] poolObj;
0172:
0173:            /** For every constant pool entry, an index into buf where the
0174:             *  defining section of the entry is found.
0175:             */
0176:            int[] poolIdx;
0177:
0178:            /** Get the ClassReader instance for this invocation. */
0179:            public static ClassReader instance(Context context) {
0180:                ClassReader instance = context.get(classReaderKey);
0181:                if (instance == null)
0182:                    instance = new ClassReader(context, true);
0183:                return instance;
0184:            }
0185:
0186:            /** Initialize classes and packages, treating this as the definitive classreader. */
0187:            public void init(Symtab syms) {
0188:                init(syms, true);
0189:            }
0190:
0191:            /** Initialize classes and packages, optionally treating this as
0192:             *  the definitive classreader.
0193:             */
0194:            private void init(Symtab syms, boolean definitive) {
0195:                if (classes != null)
0196:                    return;
0197:
0198:                if (definitive) {
0199:                    assert packages == null || packages == syms.packages;
0200:                    packages = syms.packages;
0201:                    assert classes == null || classes == syms.classes;
0202:                    classes = syms.classes;
0203:                } else {
0204:                    packages = new HashMap<Name, PackageSymbol>();
0205:                    classes = new HashMap<Name, ClassSymbol>();
0206:                }
0207:
0208:                packages.put(names.empty, syms.rootPackage);
0209:                syms.rootPackage.completer = this ;
0210:                syms.unnamedPackage.completer = this ;
0211:            }
0212:
0213:            /** Construct a new class reader, optionally treated as the
0214:             *  definitive classreader for this invocation.
0215:             */
0216:            protected ClassReader(Context context, boolean definitive) {
0217:                if (definitive)
0218:                    context.put(classReaderKey, this );
0219:
0220:                names = Name.Table.instance(context);
0221:                syms = Symtab.instance(context);
0222:                types = Types.instance(context);
0223:                fileManager = context.get(JavaFileManager.class);
0224:                if (fileManager == null)
0225:                    throw new AssertionError("FileManager initialization error");
0226:
0227:                init(syms, definitive);
0228:                log = Log.instance(context);
0229:
0230:                Options options = Options.instance(context);
0231:                annotate = Annotate.instance(context);
0232:                verbose = options.get("-verbose") != null;
0233:                checkClassFile = options.get("-checkclassfile") != null;
0234:                Source source = Source.instance(context);
0235:                allowGenerics = source.allowGenerics();
0236:                allowVarargs = source.allowVarargs();
0237:                allowAnnotations = source.allowAnnotations();
0238:                saveParameterNames = options.get("save-parameter-names") != null;
0239:                cacheCompletionFailure = options.get("dev") == null;
0240:                preferSource = "source".equals(options.get("-Xprefer"));
0241:
0242:                completionFailureName = (options.get("failcomplete") != null) ? names
0243:                        .fromString(options.get("failcomplete"))
0244:                        : null;
0245:
0246:                typevars = new Scope(syms.noSymbol);
0247:            }
0248:
0249:            /** Add member to class unless it is synthetic.
0250:             */
0251:            private void enterMember(ClassSymbol c, Symbol sym) {
0252:                if ((sym.flags_field & (SYNTHETIC | BRIDGE)) != SYNTHETIC)
0253:                    c.members_field.enter(sym);
0254:            }
0255:
0256:            /************************************************************************
0257:             * Error Diagnoses
0258:             ***********************************************************************/
0259:
0260:            public static class BadClassFile extends CompletionFailure {
0261:                private static final long serialVersionUID = 0;
0262:
0263:                /**
0264:                 * @param msg A localized message.
0265:                 */
0266:                public BadClassFile(ClassSymbol c, Object cname, Object msg) {
0267:                    super (c, Log.getLocalizedString("bad.class.file.header",
0268:                            cname, msg));
0269:                }
0270:            }
0271:
0272:            public BadClassFile badClassFile(String key, Object... args) {
0273:                return new BadClassFile(currentOwner.enclClass(),
0274:                        currentClassFile, Log.getLocalizedString(key, args));
0275:            }
0276:
0277:            /************************************************************************
0278:             * Buffer Access
0279:             ***********************************************************************/
0280:
0281:            /** Read a character.
0282:             */
0283:            char nextChar() {
0284:                return (char) (((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
0285:            }
0286:
0287:            /** Read an integer.
0288:             */
0289:            int nextInt() {
0290:                return ((buf[bp++] & 0xFF) << 24) + ((buf[bp++] & 0xFF) << 16)
0291:                        + ((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF);
0292:            }
0293:
0294:            /** Extract a character at position bp from buf.
0295:             */
0296:            char getChar(int bp) {
0297:                return (char) (((buf[bp] & 0xFF) << 8) + (buf[bp + 1] & 0xFF));
0298:            }
0299:
0300:            /** Extract an integer at position bp from buf.
0301:             */
0302:            int getInt(int bp) {
0303:                return ((buf[bp] & 0xFF) << 24) + ((buf[bp + 1] & 0xFF) << 16)
0304:                        + ((buf[bp + 2] & 0xFF) << 8) + (buf[bp + 3] & 0xFF);
0305:            }
0306:
0307:            /** Extract a long integer at position bp from buf.
0308:             */
0309:            long getLong(int bp) {
0310:                DataInputStream bufin = new DataInputStream(
0311:                        new ByteArrayInputStream(buf, bp, 8));
0312:                try {
0313:                    return bufin.readLong();
0314:                } catch (IOException e) {
0315:                    throw new AssertionError(e);
0316:                }
0317:            }
0318:
0319:            /** Extract a float at position bp from buf.
0320:             */
0321:            float getFloat(int bp) {
0322:                DataInputStream bufin = new DataInputStream(
0323:                        new ByteArrayInputStream(buf, bp, 4));
0324:                try {
0325:                    return bufin.readFloat();
0326:                } catch (IOException e) {
0327:                    throw new AssertionError(e);
0328:                }
0329:            }
0330:
0331:            /** Extract a double at position bp from buf.
0332:             */
0333:            double getDouble(int bp) {
0334:                DataInputStream bufin = new DataInputStream(
0335:                        new ByteArrayInputStream(buf, bp, 8));
0336:                try {
0337:                    return bufin.readDouble();
0338:                } catch (IOException e) {
0339:                    throw new AssertionError(e);
0340:                }
0341:            }
0342:
0343:            /************************************************************************
0344:             * Constant Pool Access
0345:             ***********************************************************************/
0346:
0347:            /** Index all constant pool entries, writing their start addresses into
0348:             *  poolIdx.
0349:             */
0350:            void indexPool() {
0351:                poolIdx = new int[nextChar()];
0352:                poolObj = new Object[poolIdx.length];
0353:                int i = 1;
0354:                while (i < poolIdx.length) {
0355:                    poolIdx[i++] = bp;
0356:                    byte tag = buf[bp++];
0357:                    switch (tag) {
0358:                    case CONSTANT_Utf8:
0359:                    case CONSTANT_Unicode: {
0360:                        int len = nextChar();
0361:                        bp = bp + len;
0362:                        break;
0363:                    }
0364:                    case CONSTANT_Class:
0365:                    case CONSTANT_String:
0366:                        bp = bp + 2;
0367:                        break;
0368:                    case CONSTANT_Fieldref:
0369:                    case CONSTANT_Methodref:
0370:                    case CONSTANT_InterfaceMethodref:
0371:                    case CONSTANT_NameandType:
0372:                    case CONSTANT_Integer:
0373:                    case CONSTANT_Float:
0374:                        bp = bp + 4;
0375:                        break;
0376:                    case CONSTANT_Long:
0377:                    case CONSTANT_Double:
0378:                        bp = bp + 8;
0379:                        i++;
0380:                        break;
0381:                    default:
0382:                        throw badClassFile("bad.const.pool.tag.at", Byte
0383:                                .toString(tag), Integer.toString(bp - 1));
0384:                    }
0385:                }
0386:            }
0387:
0388:            /** Read constant pool entry at start address i, use pool as a cache.
0389:             */
0390:            Object readPool(int i) {
0391:                Object result = poolObj[i];
0392:                if (result != null)
0393:                    return result;
0394:
0395:                int index = poolIdx[i];
0396:                if (index == 0)
0397:                    return null;
0398:
0399:                byte tag = buf[index];
0400:                switch (tag) {
0401:                case CONSTANT_Utf8:
0402:                    poolObj[i] = names.fromUtf(buf, index + 3,
0403:                            getChar(index + 1));
0404:                    break;
0405:                case CONSTANT_Unicode:
0406:                    throw badClassFile("unicode.str.not.supported");
0407:                case CONSTANT_Class:
0408:                    poolObj[i] = readClassOrType(getChar(index + 1));
0409:                    break;
0410:                case CONSTANT_String:
0411:                    // FIXME: (footprint) do not use toString here
0412:                    poolObj[i] = readName(getChar(index + 1)).toString();
0413:                    break;
0414:                case CONSTANT_Fieldref: {
0415:                    ClassSymbol owner = readClassSymbol(getChar(index + 1));
0416:                    NameAndType nt = (NameAndType) readPool(getChar(index + 3));
0417:                    poolObj[i] = new VarSymbol(0, nt.name, nt.type, owner);
0418:                    break;
0419:                }
0420:                case CONSTANT_Methodref:
0421:                case CONSTANT_InterfaceMethodref: {
0422:                    ClassSymbol owner = readClassSymbol(getChar(index + 1));
0423:                    NameAndType nt = (NameAndType) readPool(getChar(index + 3));
0424:                    poolObj[i] = new MethodSymbol(0, nt.name, nt.type, owner);
0425:                    break;
0426:                }
0427:                case CONSTANT_NameandType:
0428:                    poolObj[i] = new NameAndType(readName(getChar(index + 1)),
0429:                            readType(getChar(index + 3)));
0430:                    break;
0431:                case CONSTANT_Integer:
0432:                    poolObj[i] = getInt(index + 1);
0433:                    break;
0434:                case CONSTANT_Float:
0435:                    poolObj[i] = new Float(getFloat(index + 1));
0436:                    break;
0437:                case CONSTANT_Long:
0438:                    poolObj[i] = new Long(getLong(index + 1));
0439:                    break;
0440:                case CONSTANT_Double:
0441:                    poolObj[i] = new Double(getDouble(index + 1));
0442:                    break;
0443:                default:
0444:                    throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
0445:                }
0446:                return poolObj[i];
0447:            }
0448:
0449:            /** Read signature and convert to type.
0450:             */
0451:            Type readType(int i) {
0452:                int index = poolIdx[i];
0453:                return sigToType(buf, index + 3, getChar(index + 1));
0454:            }
0455:
0456:            /** If name is an array type or class signature, return the
0457:             *  corresponding type; otherwise return a ClassSymbol with given name.
0458:             */
0459:            Object readClassOrType(int i) {
0460:                int index = poolIdx[i];
0461:                int len = getChar(index + 1);
0462:                int start = index + 3;
0463:                assert buf[start] == '[' || buf[start + len - 1] != ';';
0464:                // by the above assertion, the following test can be
0465:                // simplified to (buf[start] == '[')
0466:                return (buf[start] == '[' || buf[start + len - 1] == ';') ? (Object) sigToType(
0467:                        buf, start, len)
0468:                        : (Object) enterClass(names.fromUtf(internalize(buf,
0469:                                start, len)));
0470:            }
0471:
0472:            /** Read signature and convert to type parameters.
0473:             */
0474:            List<Type> readTypeParams(int i) {
0475:                int index = poolIdx[i];
0476:                return sigToTypeParams(buf, index + 3, getChar(index + 1));
0477:            }
0478:
0479:            /** Read class entry.
0480:             */
0481:            ClassSymbol readClassSymbol(int i) {
0482:                return (ClassSymbol) (readPool(i));
0483:            }
0484:
0485:            /** Read name.
0486:             */
0487:            Name readName(int i) {
0488:                return (Name) (readPool(i));
0489:            }
0490:
0491:            /************************************************************************
0492:             * Reading Types
0493:             ***********************************************************************/
0494:
0495:            /** The unread portion of the currently read type is
0496:             *  signature[sigp..siglimit-1].
0497:             */
0498:            byte[] signature;
0499:            int sigp;
0500:            int siglimit;
0501:            boolean sigEnterPhase = false;
0502:
0503:            /** Convert signature to type, where signature is a name.
0504:             */
0505:            Type sigToType(Name sig) {
0506:                return sig == null ? null : sigToType(sig.table.names,
0507:                        sig.index, sig.len);
0508:            }
0509:
0510:            /** Convert signature to type, where signature is a byte array segment.
0511:             */
0512:            Type sigToType(byte[] sig, int offset, int len) {
0513:                signature = sig;
0514:                sigp = offset;
0515:                siglimit = offset + len;
0516:                return sigToType();
0517:            }
0518:
0519:            /** Convert signature to type, where signature is implicit.
0520:             */
0521:            Type sigToType() {
0522:                switch ((char) signature[sigp]) {
0523:                case 'T':
0524:                    sigp++;
0525:                    int start = sigp;
0526:                    while (signature[sigp] != ';')
0527:                        sigp++;
0528:                    sigp++;
0529:                    return sigEnterPhase ? Type.noType : findTypeVar(names
0530:                            .fromUtf(signature, start, sigp - 1 - start));
0531:                case '+': {
0532:                    sigp++;
0533:                    Type t = sigToType();
0534:                    return new WildcardType(t, BoundKind.EXTENDS,
0535:                            syms.boundClass);
0536:                }
0537:                case '*':
0538:                    sigp++;
0539:                    return new WildcardType(syms.objectType, BoundKind.UNBOUND,
0540:                            syms.boundClass);
0541:                case '-': {
0542:                    sigp++;
0543:                    Type t = sigToType();
0544:                    return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
0545:                }
0546:                case 'B':
0547:                    sigp++;
0548:                    return syms.byteType;
0549:                case 'C':
0550:                    sigp++;
0551:                    return syms.charType;
0552:                case 'D':
0553:                    sigp++;
0554:                    return syms.doubleType;
0555:                case 'F':
0556:                    sigp++;
0557:                    return syms.floatType;
0558:                case 'I':
0559:                    sigp++;
0560:                    return syms.intType;
0561:                case 'J':
0562:                    sigp++;
0563:                    return syms.longType;
0564:                case 'L': {
0565:                    // int oldsigp = sigp;
0566:                    Type t = classSigToType();
0567:                    if (sigp < siglimit && signature[sigp] == '.')
0568:                        throw badClassFile("deprecated inner class signature syntax "
0569:                                + "(please recompile from source)");
0570:                    /*
0571:                    System.err.println(" decoded " +
0572:                                       new String(signature, oldsigp, sigp-oldsigp) +
0573:                                       " => " + t + " outer " + t.outer());
0574:                     */
0575:                    return t;
0576:                }
0577:                case 'S':
0578:                    sigp++;
0579:                    return syms.shortType;
0580:                case 'V':
0581:                    sigp++;
0582:                    return syms.voidType;
0583:                case 'Z':
0584:                    sigp++;
0585:                    return syms.booleanType;
0586:                case '[':
0587:                    sigp++;
0588:                    return new ArrayType(sigToType(), syms.arrayClass);
0589:                case '(':
0590:                    sigp++;
0591:                    List<Type> argtypes = sigToTypes(')');
0592:                    Type restype = sigToType();
0593:                    List<Type> thrown = List.nil();
0594:                    while (signature[sigp] == '^') {
0595:                        sigp++;
0596:                        thrown = thrown.prepend(sigToType());
0597:                    }
0598:                    return new MethodType(argtypes, restype, thrown.reverse(),
0599:                            syms.methodClass);
0600:                case '<':
0601:                    typevars = typevars.dup(currentOwner);
0602:                    Type poly = new ForAll(sigToTypeParams(), sigToType());
0603:                    typevars = typevars.leave();
0604:                    return poly;
0605:                default:
0606:                    throw badClassFile("bad.signature", Convert.utf2string(
0607:                            signature, sigp, 10));
0608:                }
0609:            }
0610:
0611:            byte[] signatureBuffer = new byte[0];
0612:            int sbp = 0;
0613:
0614:            /** Convert class signature to type, where signature is implicit.
0615:             */
0616:            Type classSigToType() {
0617:                if (signature[sigp] != 'L')
0618:                    throw badClassFile("bad.class.signature", Convert
0619:                            .utf2string(signature, sigp, 10));
0620:                sigp++;
0621:                Type outer = Type.noType;
0622:                int startSbp = sbp;
0623:
0624:                while (true) {
0625:                    final byte c = signature[sigp++];
0626:                    switch (c) {
0627:
0628:                    case ';': { // end
0629:                        ClassSymbol t = enterClass(names.fromUtf(
0630:                                signatureBuffer, startSbp, sbp - startSbp));
0631:                        if (outer == Type.noType)
0632:                            outer = t.erasure(types);
0633:                        else
0634:                            outer = new ClassType(outer, List.<Type> nil(), t);
0635:                        sbp = startSbp;
0636:                        return outer;
0637:                    }
0638:
0639:                    case '<': // generic arguments
0640:                        ClassSymbol t = enterClass(names.fromUtf(
0641:                                signatureBuffer, startSbp, sbp - startSbp));
0642:                        outer = new ClassType(outer, sigToTypes('>'), t) {
0643:                            boolean completed = false;
0644:
0645:                            public Type getEnclosingType() {
0646:                                if (!completed) {
0647:                                    completed = true;
0648:                                    tsym.complete();
0649:                                    Type enclosingType = tsym.type
0650:                                            .getEnclosingType();
0651:                                    if (enclosingType != Type.noType) {
0652:                                        List<Type> typeArgs = super 
0653:                                                .getEnclosingType().allparams();
0654:                                        List<Type> typeParams = enclosingType
0655:                                                .allparams();
0656:                                        if (typeParams.length() != typeArgs
0657:                                                .length()) {
0658:                                            // no "rare" types
0659:                                            super .setEnclosingType(types
0660:                                                    .erasure(enclosingType));
0661:                                        } else {
0662:                                            super .setEnclosingType(types.subst(
0663:                                                    enclosingType, typeParams,
0664:                                                    typeArgs));
0665:                                        }
0666:                                    } else {
0667:                                        super .setEnclosingType(Type.noType);
0668:                                    }
0669:                                }
0670:                                return super .getEnclosingType();
0671:                            }
0672:
0673:                            public void setEnclosingType(Type outer) {
0674:                                throw new UnsupportedOperationException();
0675:                            }
0676:                        };
0677:                        switch (signature[sigp++]) {
0678:                        case ';':
0679:                            if (sigp < signature.length
0680:                                    && signature[sigp] == '.') {
0681:                                // support old-style GJC signatures
0682:                                // The signature produced was
0683:                                // Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
0684:                                // rather than say
0685:                                // Lfoo/Outer<Lfoo/X;>.Inner<Lfoo/Y;>;
0686:                                // so we skip past ".Lfoo/Outer$"
0687:                                sigp += (sbp - startSbp) + // "foo/Outer"
0688:                                3; // ".L" and "$"
0689:                                signatureBuffer[sbp++] = (byte) '$';
0690:                                break;
0691:                            } else {
0692:                                sbp = startSbp;
0693:                                return outer;
0694:                            }
0695:                        case '.':
0696:                            signatureBuffer[sbp++] = (byte) '$';
0697:                            break;
0698:                        default:
0699:                            throw new AssertionError(signature[sigp - 1]);
0700:                        }
0701:                        continue;
0702:
0703:                    case '.':
0704:                        signatureBuffer[sbp++] = (byte) '$';
0705:                        continue;
0706:                    case '/':
0707:                        signatureBuffer[sbp++] = (byte) '.';
0708:                        continue;
0709:                    default:
0710:                        signatureBuffer[sbp++] = c;
0711:                        continue;
0712:                    }
0713:                }
0714:            }
0715:
0716:            /** Convert (implicit) signature to list of types
0717:             *  until `terminator' is encountered.
0718:             */
0719:            List<Type> sigToTypes(char terminator) {
0720:                List<Type> head = List.of(null);
0721:                List<Type> tail = head;
0722:                while (signature[sigp] != terminator)
0723:                    tail = tail.setTail(List.of(sigToType()));
0724:                sigp++;
0725:                return head.tail;
0726:            }
0727:
0728:            /** Convert signature to type parameters, where signature is a name.
0729:             */
0730:            List<Type> sigToTypeParams(Name name) {
0731:                return sigToTypeParams(name.table.names, name.index, name.len);
0732:            }
0733:
0734:            /** Convert signature to type parameters, where signature is a byte
0735:             *  array segment.
0736:             */
0737:            List<Type> sigToTypeParams(byte[] sig, int offset, int len) {
0738:                signature = sig;
0739:                sigp = offset;
0740:                siglimit = offset + len;
0741:                return sigToTypeParams();
0742:            }
0743:
0744:            /** Convert signature to type parameters, where signature is implicit.
0745:             */
0746:            List<Type> sigToTypeParams() {
0747:                List<Type> tvars = List.nil();
0748:                if (signature[sigp] == '<') {
0749:                    sigp++;
0750:                    int start = sigp;
0751:                    sigEnterPhase = true;
0752:                    while (signature[sigp] != '>')
0753:                        tvars = tvars.prepend(sigToTypeParam());
0754:                    sigEnterPhase = false;
0755:                    sigp = start;
0756:                    while (signature[sigp] != '>')
0757:                        sigToTypeParam();
0758:                    sigp++;
0759:                }
0760:                return tvars.reverse();
0761:            }
0762:
0763:            /** Convert (implicit) signature to type parameter.
0764:             */
0765:            Type sigToTypeParam() {
0766:                int start = sigp;
0767:                while (signature[sigp] != ':')
0768:                    sigp++;
0769:                Name name = names.fromUtf(signature, start, sigp - start);
0770:                TypeVar tvar;
0771:                if (sigEnterPhase) {
0772:                    tvar = new TypeVar(name, currentOwner, syms.botType);
0773:                    typevars.enter(tvar.tsym);
0774:                } else {
0775:                    tvar = (TypeVar) findTypeVar(name);
0776:                }
0777:                List<Type> bounds = List.nil();
0778:                Type st = null;
0779:                if (signature[sigp] == ':' && signature[sigp + 1] == ':') {
0780:                    sigp++;
0781:                    st = syms.objectType;
0782:                }
0783:                while (signature[sigp] == ':') {
0784:                    sigp++;
0785:                    bounds = bounds.prepend(sigToType());
0786:                }
0787:                if (!sigEnterPhase) {
0788:                    types.setBounds(tvar, bounds.reverse(), st);
0789:                }
0790:                return tvar;
0791:            }
0792:
0793:            /** Find type variable with given name in `typevars' scope.
0794:             */
0795:            Type findTypeVar(Name name) {
0796:                Scope.Entry e = typevars.lookup(name);
0797:                if (e.scope != null) {
0798:                    return e.sym.type;
0799:                } else {
0800:                    if (readingClassAttr) {
0801:                        // While reading the class attribute, the supertypes
0802:                        // might refer to a type variable from an enclosing element
0803:                        // (method or class).
0804:                        // If the type variable is defined in the enclosing class,
0805:                        // we can actually find it in
0806:                        // currentOwner.owner.type.getTypeArguments()
0807:                        // However, until we have read the enclosing method attribute
0808:                        // we don't know for sure if this owner is correct.  It could
0809:                        // be a method and there is no way to tell before reading the
0810:                        // enclosing method attribute.
0811:                        TypeVar t = new TypeVar(name, currentOwner,
0812:                                syms.botType);
0813:                        missingTypeVariables = missingTypeVariables.prepend(t);
0814:                        // System.err.println("Missing type var " + name);
0815:                        return t;
0816:                    }
0817:                    throw badClassFile("undecl.type.var", name);
0818:                }
0819:            }
0820:
0821:            /************************************************************************
0822:             * Reading Attributes
0823:             ***********************************************************************/
0824:
0825:            /** Report unrecognized attribute.
0826:             */
0827:            void unrecognized(Name attrName) {
0828:                if (checkClassFile)
0829:                    printCCF("ccf.unrecognized.attribute", attrName);
0830:            }
0831:
0832:            /** Read member attribute.
0833:             */
0834:            void readMemberAttr(Symbol sym, Name attrName, int attrLen) {
0835:                //- System.err.println(" z " + sym + ", " + attrName + ", " + attrLen);
0836:                if (attrName == names.ConstantValue) {
0837:                    Object v = readPool(nextChar());
0838:                    // Ignore ConstantValue attribute if field not final.
0839:                    if ((sym.flags() & FINAL) != 0)
0840:                        ((VarSymbol) sym).setData(v);
0841:                } else if (attrName == names.Code) {
0842:                    if (readAllOfClassFile || saveParameterNames)
0843:                        ((MethodSymbol) sym).code = readCode(sym);
0844:                    else
0845:                        bp = bp + attrLen;
0846:                } else if (attrName == names.Exceptions) {
0847:                    int nexceptions = nextChar();
0848:                    List<Type> thrown = List.nil();
0849:                    for (int j = 0; j < nexceptions; j++)
0850:                        thrown = thrown
0851:                                .prepend(readClassSymbol(nextChar()).type);
0852:                    if (sym.type.getThrownTypes().isEmpty())
0853:                        sym.type.asMethodType().thrown = thrown.reverse();
0854:                } else if (attrName == names.Synthetic) {
0855:                    // bridge methods are visible when generics not enabled
0856:                    if (allowGenerics || (sym.flags_field & BRIDGE) == 0)
0857:                        sym.flags_field |= SYNTHETIC;
0858:                } else if (attrName == names.Bridge) {
0859:                    sym.flags_field |= BRIDGE;
0860:                    if (!allowGenerics)
0861:                        sym.flags_field &= ~SYNTHETIC;
0862:                } else if (attrName == names.Deprecated) {
0863:                    sym.flags_field |= DEPRECATED;
0864:                } else if (attrName == names.Varargs) {
0865:                    if (allowVarargs)
0866:                        sym.flags_field |= VARARGS;
0867:                } else if (attrName == names.Annotation) {
0868:                    if (allowAnnotations)
0869:                        sym.flags_field |= ANNOTATION;
0870:                } else if (attrName == names.Enum) {
0871:                    sym.flags_field |= ENUM;
0872:                } else if (allowGenerics && attrName == names.Signature) {
0873:                    List<Type> thrown = sym.type.getThrownTypes();
0874:                    sym.type = readType(nextChar());
0875:                    //- System.err.println(" # " + sym.type);
0876:                    if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
0877:                        sym.type.asMethodType().thrown = thrown;
0878:                } else if (attrName == names.RuntimeVisibleAnnotations) {
0879:                    attachAnnotations(sym);
0880:                } else if (attrName == names.RuntimeInvisibleAnnotations) {
0881:                    attachAnnotations(sym);
0882:                } else if (attrName == names.RuntimeVisibleParameterAnnotations) {
0883:                    attachParameterAnnotations(sym);
0884:                } else if (attrName == names.RuntimeInvisibleParameterAnnotations) {
0885:                    attachParameterAnnotations(sym);
0886:                } else if (attrName == names.LocalVariableTable) {
0887:                    int newbp = bp + attrLen;
0888:                    if (saveParameterNames) {
0889:                        // pick up parameter names from the variable table
0890:                        List<Name> parameterNames = List.nil();
0891:                        int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
0892:                        int endParam = firstParam
0893:                                + Code.width(sym.type.getParameterTypes());
0894:                        int numEntries = nextChar();
0895:                        for (int i = 0; i < numEntries; i++) {
0896:                            int start_pc = nextChar();
0897:                            int length = nextChar();
0898:                            int nameIndex = nextChar();
0899:                            int sigIndex = nextChar();
0900:                            int register = nextChar();
0901:                            if (start_pc == 0 && firstParam <= register
0902:                                    && register < endParam) {
0903:                                int index = firstParam;
0904:                                for (Type t : sym.type.getParameterTypes()) {
0905:                                    if (index == register) {
0906:                                        parameterNames = parameterNames
0907:                                                .prepend(readName(nameIndex));
0908:                                        break;
0909:                                    }
0910:                                    index += Code.width(t);
0911:                                }
0912:                            }
0913:                        }
0914:                        parameterNames = parameterNames.reverse();
0915:                        ((MethodSymbol) sym).savedParameterNames = parameterNames;
0916:                    }
0917:                    bp = newbp;
0918:                } else if (attrName == names.AnnotationDefault) {
0919:                    attachAnnotationDefault(sym);
0920:                } else if (attrName == names.EnclosingMethod) {
0921:                    int newbp = bp + attrLen;
0922:                    readEnclosingMethodAttr(sym);
0923:                    bp = newbp;
0924:                } else {
0925:                    unrecognized(attrName);
0926:                    bp = bp + attrLen;
0927:                }
0928:            }
0929:
0930:            void readEnclosingMethodAttr(Symbol sym) {
0931:                // sym is a nested class with an "Enclosing Method" attribute
0932:                // remove sym from it's current owners scope and place it in
0933:                // the scope specified by the attribute
0934:                sym.owner.members().remove(sym);
0935:                ClassSymbol self = (ClassSymbol) sym;
0936:                ClassSymbol c = readClassSymbol(nextChar());
0937:                NameAndType nt = (NameAndType) readPool(nextChar());
0938:
0939:                MethodSymbol m = findMethod(nt, c.members_field, self.flags());
0940:                if (nt != null && m == null)
0941:                    throw badClassFile("bad.enclosing.method", self);
0942:
0943:                self.name = simpleBinaryName(self.flatname, c.flatname);
0944:                self.owner = m != null ? m : c;
0945:                if (self.name.len == 0)
0946:                    self.fullname = null;
0947:                else
0948:                    self.fullname = ClassSymbol.formFullName(self.name,
0949:                            self.owner);
0950:
0951:                if (m != null) {
0952:                    ((ClassType) sym.type).setEnclosingType(m.type);
0953:                } else if ((self.flags_field & STATIC) == 0) {
0954:                    ((ClassType) sym.type).setEnclosingType(c.type);
0955:                } else {
0956:                    ((ClassType) sym.type).setEnclosingType(Type.noType);
0957:                }
0958:                enterTypevars(self);
0959:                if (!missingTypeVariables.isEmpty()) {
0960:                    ListBuffer<Type> typeVars = new ListBuffer<Type>();
0961:                    for (Type typevar : missingTypeVariables) {
0962:                        typeVars.append(findTypeVar(typevar.tsym.name));
0963:                    }
0964:                    foundTypeVariables = typeVars.toList();
0965:                } else {
0966:                    foundTypeVariables = List.nil();
0967:                }
0968:            }
0969:
0970:            // See java.lang.Class
0971:            private Name simpleBinaryName(Name self, Name enclosing) {
0972:                String simpleBinaryName = self.toString().substring(
0973:                        enclosing.toString().length());
0974:                if (simpleBinaryName.length() < 1
0975:                        || simpleBinaryName.charAt(0) != '$')
0976:                    throw badClassFile("bad.enclosing.method", self);
0977:                int index = 1;
0978:                while (index < simpleBinaryName.length()
0979:                        && isAsciiDigit(simpleBinaryName.charAt(index)))
0980:                    index++;
0981:                return names.fromString(simpleBinaryName.substring(index));
0982:            }
0983:
0984:            private MethodSymbol findMethod(NameAndType nt, Scope scope,
0985:                    long flags) {
0986:                if (nt == null)
0987:                    return null;
0988:
0989:                MethodType type = nt.type.asMethodType();
0990:
0991:                for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e
0992:                        .next())
0993:                    if (e.sym.kind == MTH
0994:                            && isSameBinaryType(e.sym.type.asMethodType(), type))
0995:                        return (MethodSymbol) e.sym;
0996:
0997:                if (nt.name != names.init)
0998:                    // not a constructor
0999:                    return null;
1000:                if ((flags & INTERFACE) != 0)
1001:                    // no enclosing instance
1002:                    return null;
1003:                if (nt.type.getParameterTypes().isEmpty())
1004:                    // no parameters
1005:                    return null;
1006:
1007:                // A constructor of an inner class.
1008:                // Remove the first argument (the enclosing instance)
1009:                nt.type = new MethodType(nt.type.getParameterTypes().tail,
1010:                        nt.type.getReturnType(), nt.type.getThrownTypes(),
1011:                        syms.methodClass);
1012:                // Try searching again
1013:                return findMethod(nt, scope, flags);
1014:            }
1015:
1016:            /** Similar to Types.isSameType but avoids completion */
1017:            private boolean isSameBinaryType(MethodType mt1, MethodType mt2) {
1018:                List<Type> types1 = types.erasure(mt1.getParameterTypes())
1019:                        .prepend(types.erasure(mt1.getReturnType()));
1020:                List<Type> types2 = mt2.getParameterTypes().prepend(
1021:                        mt2.getReturnType());
1022:                while (!types1.isEmpty() && !types2.isEmpty()) {
1023:                    if (types1.head.tsym != types2.head.tsym)
1024:                        return false;
1025:                    types1 = types1.tail;
1026:                    types2 = types2.tail;
1027:                }
1028:                return types1.isEmpty() && types2.isEmpty();
1029:            }
1030:
1031:            /**
1032:             * Character.isDigit answers <tt>true</tt> to some non-ascii
1033:             * digits.  This one does not.  <b>copied from java.lang.Class</b>
1034:             */
1035:            private static boolean isAsciiDigit(char c) {
1036:                return '0' <= c && c <= '9';
1037:            }
1038:
1039:            /** Read member attributes.
1040:             */
1041:            void readMemberAttrs(Symbol sym) {
1042:                char ac = nextChar();
1043:                for (int i = 0; i < ac; i++) {
1044:                    Name attrName = readName(nextChar());
1045:                    int attrLen = nextInt();
1046:                    readMemberAttr(sym, attrName, attrLen);
1047:                }
1048:            }
1049:
1050:            /** Read class attribute.
1051:             */
1052:            void readClassAttr(ClassSymbol c, Name attrName, int attrLen) {
1053:                if (attrName == names.SourceFile) {
1054:                    Name n = readName(nextChar());
1055:                    c.sourcefile = new SourceFileObject(n);
1056:                } else if (attrName == names.InnerClasses) {
1057:                    readInnerClasses(c);
1058:                } else if (allowGenerics && attrName == names.Signature) {
1059:                    readingClassAttr = true;
1060:                    try {
1061:                        ClassType ct1 = (ClassType) c.type;
1062:                        assert c == currentOwner;
1063:                        ct1.typarams_field = readTypeParams(nextChar());
1064:                        ct1.super type_field = sigToType();
1065:                        ListBuffer<Type> is = new ListBuffer<Type>();
1066:                        while (sigp != siglimit)
1067:                            is.append(sigToType());
1068:                        ct1.interfaces_field = is.toList();
1069:                    } finally {
1070:                        readingClassAttr = false;
1071:                    }
1072:                } else {
1073:                    readMemberAttr(c, attrName, attrLen);
1074:                }
1075:            }
1076:
1077:            private boolean readingClassAttr = false;
1078:            private List<Type> missingTypeVariables = List.nil();
1079:            private List<Type> foundTypeVariables = List.nil();
1080:
1081:            /** Read class attributes.
1082:             */
1083:            void readClassAttrs(ClassSymbol c) {
1084:                char ac = nextChar();
1085:                for (int i = 0; i < ac; i++) {
1086:                    Name attrName = readName(nextChar());
1087:                    int attrLen = nextInt();
1088:                    readClassAttr(c, attrName, attrLen);
1089:                }
1090:            }
1091:
1092:            /** Read code block.
1093:             */
1094:            Code readCode(Symbol owner) {
1095:                nextChar(); // max_stack
1096:                nextChar(); // max_locals
1097:                final int code_length = nextInt();
1098:                bp += code_length;
1099:                final char exception_table_length = nextChar();
1100:                bp += exception_table_length * 8;
1101:                readMemberAttrs(owner);
1102:                return null;
1103:            }
1104:
1105:            /************************************************************************
1106:             * Reading Java-language annotations
1107:             ***********************************************************************/
1108:
1109:            /** Attach annotations.
1110:             */
1111:            void attachAnnotations(final Symbol sym) {
1112:                int numAttributes = nextChar();
1113:                if (numAttributes != 0) {
1114:                    ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<CompoundAnnotationProxy>();
1115:                    for (int i = 0; i < numAttributes; i++) {
1116:                        CompoundAnnotationProxy proxy = readCompoundAnnotation();
1117:                        if (proxy.type.tsym == syms.proprietaryType.tsym)
1118:                            sym.flags_field |= PROPRIETARY;
1119:                        else
1120:                            proxies.append(proxy);
1121:                    }
1122:                    annotate.later(new AnnotationCompleter(sym, proxies
1123:                            .toList()));
1124:                }
1125:            }
1126:
1127:            /** Attach parameter annotations.
1128:             */
1129:            void attachParameterAnnotations(final Symbol method) {
1130:                final MethodSymbol meth = (MethodSymbol) method;
1131:                int numParameters = buf[bp++] & 0xFF;
1132:                List<VarSymbol> parameters = meth.params();
1133:                int pnum = 0;
1134:                while (parameters.tail != null) {
1135:                    attachAnnotations(parameters.head);
1136:                    parameters = parameters.tail;
1137:                    pnum++;
1138:                }
1139:                if (pnum != numParameters) {
1140:                    throw badClassFile(
1141:                            "bad.runtime.invisible.param.annotations", meth);
1142:                }
1143:            }
1144:
1145:            /** Attach the default value for an annotation element.
1146:             */
1147:            void attachAnnotationDefault(final Symbol sym) {
1148:                final MethodSymbol meth = (MethodSymbol) sym; // only on methods
1149:                final Attribute value = readAttributeValue();
1150:                annotate.later(new AnnotationDefaultCompleter(meth, value));
1151:            }
1152:
1153:            Type readTypeOrClassSymbol(int i) {
1154:                // support preliminary jsr175-format class files
1155:                if (buf[poolIdx[i]] == CONSTANT_Class)
1156:                    return readClassSymbol(i).type;
1157:                return readType(i);
1158:            }
1159:
1160:            Type readEnumType(int i) {
1161:                // support preliminary jsr175-format class files
1162:                int index = poolIdx[i];
1163:                int length = getChar(index + 1);
1164:                if (buf[index + length + 2] != ';')
1165:                    return enterClass(readName(i)).type;
1166:                return readType(i);
1167:            }
1168:
1169:            CompoundAnnotationProxy readCompoundAnnotation() {
1170:                Type t = readTypeOrClassSymbol(nextChar());
1171:                int numFields = nextChar();
1172:                ListBuffer<Pair<Name, Attribute>> pairs = new ListBuffer<Pair<Name, Attribute>>();
1173:                for (int i = 0; i < numFields; i++) {
1174:                    Name name = readName(nextChar());
1175:                    Attribute value = readAttributeValue();
1176:                    pairs.append(new Pair<Name, Attribute>(name, value));
1177:                }
1178:                return new CompoundAnnotationProxy(t, pairs.toList());
1179:            }
1180:
1181:            Attribute readAttributeValue() {
1182:                char c = (char) buf[bp++];
1183:                switch (c) {
1184:                case 'B':
1185:                    return new Attribute.Constant(syms.byteType,
1186:                            readPool(nextChar()));
1187:                case 'C':
1188:                    return new Attribute.Constant(syms.charType,
1189:                            readPool(nextChar()));
1190:                case 'D':
1191:                    return new Attribute.Constant(syms.doubleType,
1192:                            readPool(nextChar()));
1193:                case 'F':
1194:                    return new Attribute.Constant(syms.floatType,
1195:                            readPool(nextChar()));
1196:                case 'I':
1197:                    return new Attribute.Constant(syms.intType,
1198:                            readPool(nextChar()));
1199:                case 'J':
1200:                    return new Attribute.Constant(syms.longType,
1201:                            readPool(nextChar()));
1202:                case 'S':
1203:                    return new Attribute.Constant(syms.shortType,
1204:                            readPool(nextChar()));
1205:                case 'Z':
1206:                    return new Attribute.Constant(syms.booleanType,
1207:                            readPool(nextChar()));
1208:                case 's':
1209:                    return new Attribute.Constant(syms.stringType, readPool(
1210:                            nextChar()).toString());
1211:                case 'e':
1212:                    return new EnumAttributeProxy(readEnumType(nextChar()),
1213:                            readName(nextChar()));
1214:                case 'c':
1215:                    return new Attribute.Class(types,
1216:                            readTypeOrClassSymbol(nextChar()));
1217:                case '[': {
1218:                    int n = nextChar();
1219:                    ListBuffer<Attribute> l = new ListBuffer<Attribute>();
1220:                    for (int i = 0; i < n; i++)
1221:                        l.append(readAttributeValue());
1222:                    return new ArrayAttributeProxy(l.toList());
1223:                }
1224:                case '@':
1225:                    return readCompoundAnnotation();
1226:                default:
1227:                    throw new AssertionError("unknown annotation tag '" + c
1228:                            + "'");
1229:                }
1230:            }
1231:
1232:            interface ProxyVisitor extends Attribute.Visitor {
1233:                void visitEnumAttributeProxy(EnumAttributeProxy proxy);
1234:
1235:                void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
1236:
1237:                void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
1238:            }
1239:
1240:            static class EnumAttributeProxy extends Attribute {
1241:                Type enumType;
1242:                Name enumerator;
1243:
1244:                public EnumAttributeProxy(Type enumType, Name enumerator) {
1245:                    super (null);
1246:                    this .enumType = enumType;
1247:                    this .enumerator = enumerator;
1248:                }
1249:
1250:                public void accept(Visitor v) {
1251:                    ((ProxyVisitor) v).visitEnumAttributeProxy(this );
1252:                }
1253:
1254:                public String toString() {
1255:                    return "/*proxy enum*/" + enumType + "." + enumerator;
1256:                }
1257:            }
1258:
1259:            static class ArrayAttributeProxy extends Attribute {
1260:                List<Attribute> values;
1261:
1262:                ArrayAttributeProxy(List<Attribute> values) {
1263:                    super (null);
1264:                    this .values = values;
1265:                }
1266:
1267:                public void accept(Visitor v) {
1268:                    ((ProxyVisitor) v).visitArrayAttributeProxy(this );
1269:                }
1270:
1271:                public String toString() {
1272:                    return "{" + values + "}";
1273:                }
1274:            }
1275:
1276:            /** A temporary proxy representing a compound attribute.
1277:             */
1278:            static class CompoundAnnotationProxy extends Attribute {
1279:                final List<Pair<Name, Attribute>> values;
1280:
1281:                public CompoundAnnotationProxy(Type type,
1282:                        List<Pair<Name, Attribute>> values) {
1283:                    super (type);
1284:                    this .values = values;
1285:                }
1286:
1287:                public void accept(Visitor v) {
1288:                    ((ProxyVisitor) v).visitCompoundAnnotationProxy(this );
1289:                }
1290:
1291:                public String toString() {
1292:                    StringBuffer buf = new StringBuffer();
1293:                    buf.append("@");
1294:                    buf.append(type.tsym.getQualifiedName());
1295:                    buf.append("/*proxy*/{");
1296:                    boolean first = true;
1297:                    for (List<Pair<Name, Attribute>> v = values; v.nonEmpty(); v = v.tail) {
1298:                        Pair<Name, Attribute> value = v.head;
1299:                        if (!first)
1300:                            buf.append(",");
1301:                        first = false;
1302:                        buf.append(value.fst);
1303:                        buf.append("=");
1304:                        buf.append(value.snd);
1305:                    }
1306:                    buf.append("}");
1307:                    return buf.toString();
1308:                }
1309:            }
1310:
1311:            class AnnotationDeproxy implements  ProxyVisitor {
1312:                private ClassSymbol requestingOwner = currentOwner.kind == MTH ? currentOwner
1313:                        .enclClass()
1314:                        : (ClassSymbol) currentOwner;
1315:
1316:                List<Attribute.Compound> deproxyCompoundList(
1317:                        List<CompoundAnnotationProxy> pl) {
1318:                    // also must fill in types!!!!
1319:                    ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
1320:                    for (List<CompoundAnnotationProxy> l = pl; l.nonEmpty(); l = l.tail) {
1321:                        buf.append(deproxyCompound(l.head));
1322:                    }
1323:                    return buf.toList();
1324:                }
1325:
1326:                Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
1327:                    ListBuffer<Pair<Symbol.MethodSymbol, Attribute>> buf = new ListBuffer<Pair<Symbol.MethodSymbol, Attribute>>();
1328:                    for (List<Pair<Name, Attribute>> l = a.values; l.nonEmpty(); l = l.tail) {
1329:                        MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
1330:                        buf.append(new Pair<Symbol.MethodSymbol, Attribute>(
1331:                                meth, deproxy(meth.type.getReturnType(),
1332:                                        l.head.snd)));
1333:                    }
1334:                    return new Attribute.Compound(a.type, buf.toList());
1335:                }
1336:
1337:                MethodSymbol findAccessMethod(Type container, Name name) {
1338:                    CompletionFailure failure = null;
1339:                    try {
1340:                        for (Scope.Entry e = container.tsym.members().lookup(
1341:                                name); e.scope != null; e = e.next()) {
1342:                            Symbol sym = e.sym;
1343:                            if (sym.kind == MTH
1344:                                    && sym.type.getParameterTypes().length() == 0)
1345:                                return (MethodSymbol) sym;
1346:                        }
1347:                    } catch (CompletionFailure ex) {
1348:                        failure = ex;
1349:                    }
1350:                    // The method wasn't found: emit a warning and recover
1351:                    JavaFileObject prevSource = log
1352:                            .useSource(requestingOwner.classfile);
1353:                    try {
1354:                        if (failure == null) {
1355:                            log.warning("annotation.method.not.found",
1356:                                    container, name);
1357:                        } else {
1358:                            log.warning("annotation.method.not.found.reason",
1359:                                    container, name, failure.getMessage());
1360:                        }
1361:                    } finally {
1362:                        log.useSource(prevSource);
1363:                    }
1364:                    // Construct a new method type and symbol.  Use bottom
1365:                    // type (typeof null) as return type because this type is
1366:                    // a subtype of all reference types and can be converted
1367:                    // to primitive types by unboxing.
1368:                    MethodType mt = new MethodType(List.<Type> nil(),
1369:                            syms.botType, List.<Type> nil(), syms.methodClass);
1370:                    return new MethodSymbol(PUBLIC | ABSTRACT, name, mt,
1371:                            container.tsym);
1372:                }
1373:
1374:                Attribute result;
1375:                Type type;
1376:
1377:                Attribute deproxy(Type t, Attribute a) {
1378:                    Type oldType = type;
1379:                    try {
1380:                        type = t;
1381:                        a.accept(this );
1382:                        return result;
1383:                    } finally {
1384:                        type = oldType;
1385:                    }
1386:                }
1387:
1388:                // implement Attribute.Visitor below
1389:
1390:                public void visitConstant(Attribute.Constant value) {
1391:                    // assert value.type == type;
1392:                    result = value;
1393:                }
1394:
1395:                public void visitClass(Attribute.Class clazz) {
1396:                    result = clazz;
1397:                }
1398:
1399:                public void visitEnum(Attribute.Enum e) {
1400:                    throw new AssertionError(); // shouldn't happen
1401:                }
1402:
1403:                public void visitCompound(Attribute.Compound compound) {
1404:                    throw new AssertionError(); // shouldn't happen
1405:                }
1406:
1407:                public void visitArray(Attribute.Array array) {
1408:                    throw new AssertionError(); // shouldn't happen
1409:                }
1410:
1411:                public void visitError(Attribute.Error e) {
1412:                    throw new AssertionError(); // shouldn't happen
1413:                }
1414:
1415:                public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
1416:                    // type.tsym.flatName() should == proxy.enumFlatName
1417:                    TypeSymbol enumTypeSym = proxy.enumType.tsym;
1418:                    VarSymbol enumerator = null;
1419:                    for (Scope.Entry e = enumTypeSym.members().lookup(
1420:                            proxy.enumerator); e.scope != null; e = e.next()) {
1421:                        if (e.sym.kind == VAR) {
1422:                            enumerator = (VarSymbol) e.sym;
1423:                            break;
1424:                        }
1425:                    }
1426:                    if (enumerator == null) {
1427:                        log.error("unknown.enum.constant", currentClassFile,
1428:                                enumTypeSym, proxy.enumerator);
1429:                        result = new Attribute.Error(enumTypeSym.type);
1430:                    } else {
1431:                        result = new Attribute.Enum(enumTypeSym.type,
1432:                                enumerator);
1433:                    }
1434:                }
1435:
1436:                public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
1437:                    int length = proxy.values.length();
1438:                    Attribute[] ats = new Attribute[length];
1439:                    Type elemtype = types.elemtype(type);
1440:                    int i = 0;
1441:                    for (List<Attribute> p = proxy.values; p.nonEmpty(); p = p.tail) {
1442:                        ats[i++] = deproxy(elemtype, p.head);
1443:                    }
1444:                    result = new Attribute.Array(type, ats);
1445:                }
1446:
1447:                public void visitCompoundAnnotationProxy(
1448:                        CompoundAnnotationProxy proxy) {
1449:                    result = deproxyCompound(proxy);
1450:                }
1451:            }
1452:
1453:            class AnnotationDefaultCompleter extends AnnotationDeproxy
1454:                    implements  Annotate.Annotator {
1455:                final MethodSymbol sym;
1456:                final Attribute value;
1457:                final JavaFileObject classFile = currentClassFile;
1458:
1459:                public String toString() {
1460:                    return " ClassReader store default for " + sym.owner + "."
1461:                            + sym + " is " + value;
1462:                }
1463:
1464:                AnnotationDefaultCompleter(MethodSymbol sym, Attribute value) {
1465:                    this .sym = sym;
1466:                    this .value = value;
1467:                }
1468:
1469:                // implement Annotate.Annotator.enterAnnotation()
1470:                public void enterAnnotation() {
1471:                    JavaFileObject previousClassFile = currentClassFile;
1472:                    try {
1473:                        currentClassFile = classFile;
1474:                        sym.defaultValue = deproxy(sym.type.getReturnType(),
1475:                                value);
1476:                    } finally {
1477:                        currentClassFile = previousClassFile;
1478:                    }
1479:                }
1480:            }
1481:
1482:            class AnnotationCompleter extends AnnotationDeproxy implements 
1483:                    Annotate.Annotator {
1484:                final Symbol sym;
1485:                final List<CompoundAnnotationProxy> l;
1486:                final JavaFileObject classFile;
1487:
1488:                public String toString() {
1489:                    return " ClassReader annotate " + sym.owner + "." + sym
1490:                            + " with " + l;
1491:                }
1492:
1493:                AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
1494:                    this .sym = sym;
1495:                    this .l = l;
1496:                    this .classFile = currentClassFile;
1497:                }
1498:
1499:                // implement Annotate.Annotator.enterAnnotation()
1500:                public void enterAnnotation() {
1501:                    JavaFileObject previousClassFile = currentClassFile;
1502:                    try {
1503:                        currentClassFile = classFile;
1504:                        List<Attribute.Compound> newList = deproxyCompoundList(l);
1505:                        sym.attributes_field = ((sym.attributes_field == null) ? newList
1506:                                : newList.prependList(sym.attributes_field));
1507:                    } finally {
1508:                        currentClassFile = previousClassFile;
1509:                    }
1510:                }
1511:            }
1512:
1513:            /************************************************************************
1514:             * Reading Symbols
1515:             ***********************************************************************/
1516:
1517:            /** Read a field.
1518:             */
1519:            VarSymbol readField() {
1520:                long flags = adjustFieldFlags(nextChar());
1521:                Name name = readName(nextChar());
1522:                Type type = readType(nextChar());
1523:                VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
1524:                readMemberAttrs(v);
1525:                return v;
1526:            }
1527:
1528:            /** Read a method.
1529:             */
1530:            MethodSymbol readMethod() {
1531:                long flags = adjustMethodFlags(nextChar());
1532:                Name name = readName(nextChar());
1533:                Type type = readType(nextChar());
1534:                if (name == names.init && currentOwner.hasOuterInstance()) {
1535:                    // Sometimes anonymous classes don't have an outer
1536:                    // instance, however, there is no reliable way to tell so
1537:                    // we never strip this$n
1538:                    if (currentOwner.name.len != 0)
1539:                        type = new MethodType(type.getParameterTypes().tail,
1540:                                type.getReturnType(), type.getThrownTypes(),
1541:                                syms.methodClass);
1542:                }
1543:                MethodSymbol m = new MethodSymbol(flags, name, type,
1544:                        currentOwner);
1545:                Symbol prevOwner = currentOwner;
1546:                currentOwner = m;
1547:                try {
1548:                    readMemberAttrs(m);
1549:                } finally {
1550:                    currentOwner = prevOwner;
1551:                }
1552:                return m;
1553:            }
1554:
1555:            /** Skip a field or method
1556:             */
1557:            void skipMember() {
1558:                bp = bp + 6;
1559:                char ac = nextChar();
1560:                for (int i = 0; i < ac; i++) {
1561:                    bp = bp + 2;
1562:                    int attrLen = nextInt();
1563:                    bp = bp + attrLen;
1564:                }
1565:            }
1566:
1567:            /** Enter type variables of this classtype and all enclosing ones in
1568:             *  `typevars'.
1569:             */
1570:            protected void enterTypevars(Type t) {
1571:                if (t.getEnclosingType() != null
1572:                        && t.getEnclosingType().tag == CLASS)
1573:                    enterTypevars(t.getEnclosingType());
1574:                for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
1575:                    typevars.enter(xs.head.tsym);
1576:            }
1577:
1578:            protected void enterTypevars(Symbol sym) {
1579:                if (sym.owner.kind == MTH) {
1580:                    enterTypevars(sym.owner);
1581:                    enterTypevars(sym.owner.owner);
1582:                }
1583:                enterTypevars(sym.type);
1584:            }
1585:
1586:            /** Read contents of a given class symbol `c'. Both external and internal
1587:             *  versions of an inner class are read.
1588:             */
1589:            void readClass(ClassSymbol c) {
1590:                ClassType ct = (ClassType) c.type;
1591:
1592:                // allocate scope for members
1593:                c.members_field = new Scope(c);
1594:
1595:                // prepare type variable table
1596:                typevars = typevars.dup(currentOwner);
1597:                if (ct.getEnclosingType().tag == CLASS)
1598:                    enterTypevars(ct.getEnclosingType());
1599:
1600:                // read flags, or skip if this is an inner class
1601:                long flags = adjustClassFlags(nextChar());
1602:                if (c.owner.kind == PCK)
1603:                    c.flags_field = flags;
1604:
1605:                // read own class name and check that it matches
1606:                ClassSymbol self = readClassSymbol(nextChar());
1607:                if (c != self)
1608:                    throw badClassFile("class.file.wrong.class", self.flatname);
1609:
1610:                // class attributes must be read before class
1611:                // skip ahead to read class attributes
1612:                int startbp = bp;
1613:                nextChar();
1614:                char interfaceCount = nextChar();
1615:                bp += interfaceCount * 2;
1616:                char fieldCount = nextChar();
1617:                for (int i = 0; i < fieldCount; i++)
1618:                    skipMember();
1619:                char methodCount = nextChar();
1620:                for (int i = 0; i < methodCount; i++)
1621:                    skipMember();
1622:                readClassAttrs(c);
1623:
1624:                if (readAllOfClassFile) {
1625:                    for (int i = 1; i < poolObj.length; i++)
1626:                        readPool(i);
1627:                    c.pool = new Pool(poolObj.length, poolObj);
1628:                }
1629:
1630:                // reset and read rest of classinfo
1631:                bp = startbp;
1632:                int n = nextChar();
1633:                if (ct.super type_field == null)
1634:                    ct.super type_field = (n == 0) ? Type.noType
1635:                            : readClassSymbol(n).erasure(types);
1636:                n = nextChar();
1637:                List<Type> is = List.nil();
1638:                for (int i = 0; i < n; i++) {
1639:                    Type _inter = readClassSymbol(nextChar()).erasure(types);
1640:                    is = is.prepend(_inter);
1641:                }
1642:                if (ct.interfaces_field == null)
1643:                    ct.interfaces_field = is.reverse();
1644:
1645:                if (fieldCount != nextChar())
1646:                    assert false;
1647:                for (int i = 0; i < fieldCount; i++)
1648:                    enterMember(c, readField());
1649:                if (methodCount != nextChar())
1650:                    assert false;
1651:                for (int i = 0; i < methodCount; i++)
1652:                    enterMember(c, readMethod());
1653:
1654:                typevars = typevars.leave();
1655:            }
1656:
1657:            /** Read inner class info. For each inner/outer pair allocate a
1658:             *  member class.
1659:             */
1660:            void readInnerClasses(ClassSymbol c) {
1661:                int n = nextChar();
1662:                for (int i = 0; i < n; i++) {
1663:                    nextChar(); // skip inner class symbol
1664:                    ClassSymbol outer = readClassSymbol(nextChar());
1665:                    Name name = readName(nextChar());
1666:                    if (name == null)
1667:                        name = names.empty;
1668:                    long flags = adjustClassFlags(nextChar());
1669:                    if (outer != null) { // we have a member class
1670:                        if (name == names.empty)
1671:                            name = names.one;
1672:                        ClassSymbol member = enterClass(name, outer);
1673:                        if ((flags & STATIC) == 0) {
1674:                            ((ClassType) member.type)
1675:                                    .setEnclosingType(outer.type);
1676:                            if (member.erasure_field != null)
1677:                                ((ClassType) member.erasure_field)
1678:                                        .setEnclosingType(types
1679:                                                .erasure(outer.type));
1680:                        }
1681:                        if (c == outer) {
1682:                            member.flags_field = flags;
1683:                            enterMember(c, member);
1684:                        }
1685:                    }
1686:                }
1687:            }
1688:
1689:            /** Read a class file.
1690:             */
1691:            private void readClassFile(ClassSymbol c) throws IOException {
1692:                int magic = nextInt();
1693:                if (magic != JAVA_MAGIC)
1694:                    throw badClassFile("illegal.start.of.class.file");
1695:
1696:                int minorVersion = nextChar();
1697:                int majorVersion = nextChar();
1698:                int maxMajor = Target.MAX().majorVersion;
1699:                int maxMinor = Target.MAX().minorVersion;
1700:                if (majorVersion > maxMajor
1701:                        || majorVersion * 1000 + minorVersion < Target.MIN().majorVersion
1702:                                * 1000 + Target.MIN().minorVersion) {
1703:                    if (majorVersion == (maxMajor + 1))
1704:                        log.warning("big.major.version", currentClassFile,
1705:                                majorVersion, maxMajor);
1706:                    else
1707:                        throw badClassFile("wrong.version", Integer
1708:                                .toString(majorVersion), Integer
1709:                                .toString(minorVersion), Integer
1710:                                .toString(maxMajor), Integer.toString(maxMinor));
1711:                } else if (checkClassFile && majorVersion == maxMajor
1712:                        && minorVersion > maxMinor) {
1713:                    printCCF("found.later.version", Integer
1714:                            .toString(minorVersion));
1715:                }
1716:                indexPool();
1717:                if (signatureBuffer.length < bp) {
1718:                    int ns = Integer.highestOneBit(bp) << 1;
1719:                    signatureBuffer = new byte[ns];
1720:                }
1721:                readClass(c);
1722:            }
1723:
1724:            /************************************************************************
1725:             * Adjusting flags
1726:             ***********************************************************************/
1727:
1728:            long adjustFieldFlags(long flags) {
1729:                return flags;
1730:            }
1731:
1732:            long adjustMethodFlags(long flags) {
1733:                if ((flags & ACC_BRIDGE) != 0) {
1734:                    flags &= ~ACC_BRIDGE;
1735:                    flags |= BRIDGE;
1736:                    if (!allowGenerics)
1737:                        flags &= ~SYNTHETIC;
1738:                }
1739:                if ((flags & ACC_VARARGS) != 0) {
1740:                    flags &= ~ACC_VARARGS;
1741:                    flags |= VARARGS;
1742:                }
1743:                return flags;
1744:            }
1745:
1746:            long adjustClassFlags(long flags) {
1747:                return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
1748:            }
1749:
1750:            /************************************************************************
1751:             * Loading Classes
1752:             ***********************************************************************/
1753:
1754:            /** Define a new class given its name and owner.
1755:             */
1756:            public ClassSymbol defineClass(Name name, Symbol owner) {
1757:                ClassSymbol c = new ClassSymbol(0, name, owner);
1758:                if (owner.kind == PCK)
1759:                    assert classes.get(c.flatname) == null : c;
1760:                c.completer = this ;
1761:                return c;
1762:            }
1763:
1764:            /** Create a new toplevel or member class symbol with given name
1765:             *  and owner and enter in `classes' unless already there.
1766:             */
1767:            public ClassSymbol enterClass(Name name, TypeSymbol owner) {
1768:                Name flatname = TypeSymbol.formFlatName(name, owner);
1769:                ClassSymbol c = classes.get(flatname);
1770:                if (c == null) {
1771:                    c = defineClass(name, owner);
1772:                    classes.put(flatname, c);
1773:                } else if ((c.name != name || c.owner != owner)
1774:                        && owner.kind == TYP && c.owner.kind == PCK) {
1775:                    // reassign fields of classes that might have been loaded with
1776:                    // their flat names.
1777:                    c.owner.members().remove(c);
1778:                    c.name = name;
1779:                    c.owner = owner;
1780:                    c.fullname = ClassSymbol.formFullName(name, owner);
1781:                }
1782:                return c;
1783:            }
1784:
1785:            /**
1786:             * Creates a new toplevel class symbol with given flat name and
1787:             * given class (or source) file.
1788:             *
1789:             * @param flatName a fully qualified binary class name
1790:             * @param classFile the class file or compilation unit defining
1791:             * the class (may be {@code null})
1792:             * @return a newly created class symbol
1793:             * @throws AssertionError if the class symbol already exists
1794:             */
1795:            public ClassSymbol enterClass(Name flatName,
1796:                    JavaFileObject classFile) {
1797:                ClassSymbol cs = classes.get(flatName);
1798:                if (cs != null) {
1799:                    String msg = Log
1800:                            .format(
1801:                                    "%s: completer = %s; class file = %s; source file = %s",
1802:                                    cs.fullname, cs.completer, cs.classfile,
1803:                                    cs.sourcefile);
1804:                    throw new AssertionError(msg);
1805:                }
1806:                Name packageName = Convert.packagePart(flatName);
1807:                PackageSymbol owner = packageName.isEmpty() ? syms.unnamedPackage
1808:                        : enterPackage(packageName);
1809:                cs = defineClass(Convert.shortName(flatName), owner);
1810:                cs.classfile = classFile;
1811:                classes.put(flatName, cs);
1812:                return cs;
1813:            }
1814:
1815:            /** Create a new member or toplevel class symbol with given flat name
1816:             *  and enter in `classes' unless already there.
1817:             */
1818:            public ClassSymbol enterClass(Name flatname) {
1819:                ClassSymbol c = classes.get(flatname);
1820:                if (c == null)
1821:                    return enterClass(flatname, (JavaFileObject) null);
1822:                else
1823:                    return c;
1824:            }
1825:
1826:            private boolean suppressFlush = false;
1827:
1828:            /** Completion for classes to be loaded. Before a class is loaded
1829:             *  we make sure its enclosing class (if any) is loaded.
1830:             */
1831:            public void complete(Symbol sym) throws CompletionFailure {
1832:                if (sym.kind == TYP) {
1833:                    ClassSymbol c = (ClassSymbol) sym;
1834:                    c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
1835:                    boolean suppressFlush = this .suppressFlush;
1836:                    this .suppressFlush = true;
1837:                    try {
1838:                        completeOwners(c.owner);
1839:                        completeEnclosing(c);
1840:                    } finally {
1841:                        this .suppressFlush = suppressFlush;
1842:                    }
1843:                    fillIn(c);
1844:                } else if (sym.kind == PCK) {
1845:                    PackageSymbol p = (PackageSymbol) sym;
1846:                    try {
1847:                        fillIn(p);
1848:                    } catch (IOException ex) {
1849:                        throw new CompletionFailure(sym, ex
1850:                                .getLocalizedMessage()).initCause(ex);
1851:                    }
1852:                }
1853:                if (!filling && !suppressFlush)
1854:                    annotate.flush(); // finish attaching annotations
1855:            }
1856:
1857:            /** complete up through the enclosing package. */
1858:            private void completeOwners(Symbol o) {
1859:                if (o.kind != PCK)
1860:                    completeOwners(o.owner);
1861:                o.complete();
1862:            }
1863:
1864:            /**
1865:             * Tries to complete lexically enclosing classes if c looks like a
1866:             * nested class.  This is similar to completeOwners but handles
1867:             * the situation when a nested class is accessed directly as it is
1868:             * possible with the Tree API or javax.lang.model.*.
1869:             */
1870:            private void completeEnclosing(ClassSymbol c) {
1871:                if (c.owner.kind == PCK) {
1872:                    Symbol owner = c.owner;
1873:                    for (Name name : Convert.enclosingCandidates(Convert
1874:                            .shortName(c.name))) {
1875:                        Symbol encl = owner.members().lookup(name).sym;
1876:                        if (encl == null)
1877:                            encl = classes.get(TypeSymbol.formFlatName(name,
1878:                                    owner));
1879:                        if (encl != null)
1880:                            encl.complete();
1881:                    }
1882:                }
1883:            }
1884:
1885:            /** We can only read a single class file at a time; this
1886:             *  flag keeps track of when we are currently reading a class
1887:             *  file.
1888:             */
1889:            private boolean filling = false;
1890:
1891:            /** Fill in definition of class `c' from corresponding class or
1892:             *  source file.
1893:             */
1894:            private void fillIn(ClassSymbol c) {
1895:                if (completionFailureName == c.fullname) {
1896:                    throw new CompletionFailure(c,
1897:                            "user-selected completion failure by class name");
1898:                }
1899:                currentOwner = c;
1900:                JavaFileObject classfile = c.classfile;
1901:                if (classfile != null) {
1902:                    JavaFileObject previousClassFile = currentClassFile;
1903:                    try {
1904:                        assert !filling : "Filling " + classfile.toUri()
1905:                                + " during " + previousClassFile;
1906:                        currentClassFile = classfile;
1907:                        if (verbose) {
1908:                            printVerbose("loading", currentClassFile.toString());
1909:                        }
1910:                        if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
1911:                            filling = true;
1912:                            try {
1913:                                bp = 0;
1914:                                buf = readInputStream(buf, classfile
1915:                                        .openInputStream());
1916:                                readClassFile(c);
1917:                                if (!missingTypeVariables.isEmpty()
1918:                                        && !foundTypeVariables.isEmpty()) {
1919:                                    List<Type> missing = missingTypeVariables;
1920:                                    List<Type> found = foundTypeVariables;
1921:                                    missingTypeVariables = List.nil();
1922:                                    foundTypeVariables = List.nil();
1923:                                    filling = false;
1924:                                    ClassType ct = (ClassType) currentOwner.type;
1925:                                    ct.super type_field = types.subst(
1926:                                            ct.super type_field, missing, found);
1927:                                    ct.interfaces_field = types
1928:                                            .subst(ct.interfaces_field,
1929:                                                    missing, found);
1930:                                } else if (missingTypeVariables.isEmpty() != foundTypeVariables
1931:                                        .isEmpty()) {
1932:                                    Name name = missingTypeVariables.head.tsym.name;
1933:                                    throw badClassFile("undecl.type.var", name);
1934:                                }
1935:                            } finally {
1936:                                missingTypeVariables = List.nil();
1937:                                foundTypeVariables = List.nil();
1938:                                filling = false;
1939:                            }
1940:                        } else {
1941:                            if (sourceCompleter != null) {
1942:                                sourceCompleter.complete(c);
1943:                            } else {
1944:                                throw new IllegalStateException(
1945:                                        "Source completer required to read "
1946:                                                + classfile.toUri());
1947:                            }
1948:                        }
1949:                        return;
1950:                    } catch (IOException ex) {
1951:                        throw badClassFile("unable.to.access.file", ex
1952:                                .getMessage());
1953:                    } finally {
1954:                        currentClassFile = previousClassFile;
1955:                    }
1956:                } else {
1957:                    throw newCompletionFailure(c, Log.getLocalizedString(
1958:                            "class.file.not.found", c.flatname));
1959:                }
1960:            }
1961:
1962:            // where
1963:            private static byte[] readInputStream(byte[] buf, InputStream s)
1964:                    throws IOException {
1965:                try {
1966:                    buf = ensureCapacity(buf, s.available());
1967:                    int r = s.read(buf);
1968:                    int bp = 0;
1969:                    while (r != -1) {
1970:                        bp += r;
1971:                        buf = ensureCapacity(buf, bp);
1972:                        r = s.read(buf, bp, buf.length - bp);
1973:                    }
1974:                    return buf;
1975:                } finally {
1976:                    try {
1977:                        s.close();
1978:                    } catch (IOException e) {
1979:                        /* Ignore any errors, as this stream may have already
1980:                         * thrown a related exception which is the one that
1981:                         * should be reported.
1982:                         */
1983:                    }
1984:                }
1985:            }
1986:
1987:            private static byte[] ensureCapacity(byte[] buf, int needed) {
1988:                if (buf.length < needed) {
1989:                    byte[] old = buf;
1990:                    buf = new byte[Integer.highestOneBit(needed) << 1];
1991:                    System.arraycopy(old, 0, buf, 0, old.length);
1992:                }
1993:                return buf;
1994:            }
1995:
1996:            /** Static factory for CompletionFailure objects.
1997:             *  In practice, only one can be used at a time, so we share one
1998:             *  to reduce the expense of allocating new exception objects.
1999:             */
2000:            private CompletionFailure newCompletionFailure(ClassSymbol c,
2001:                    String localized) {
2002:                if (!cacheCompletionFailure) {
2003:                    // log.warning("proc.messager",
2004:                    //             Log.getLocalizedString("class.file.not.found", c.flatname));
2005:                    // c.debug.printStackTrace();
2006:                    return new CompletionFailure(c, localized);
2007:                } else {
2008:                    CompletionFailure result = cachedCompletionFailure;
2009:                    result.sym = c;
2010:                    result.errmsg = localized;
2011:                    return result;
2012:                }
2013:            }
2014:
2015:            private CompletionFailure cachedCompletionFailure = new CompletionFailure(
2016:                    null, null);
2017:            {
2018:                cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
2019:            }
2020:
2021:            /** Load a toplevel class with given fully qualified name
2022:             *  The class is entered into `classes' only if load was successful.
2023:             */
2024:            public ClassSymbol loadClass(Name flatname)
2025:                    throws CompletionFailure {
2026:                boolean absent = classes.get(flatname) == null;
2027:                ClassSymbol c = enterClass(flatname);
2028:                if (c.members_field == null && c.completer != null) {
2029:                    try {
2030:                        c.complete();
2031:                    } catch (CompletionFailure ex) {
2032:                        if (absent)
2033:                            classes.remove(flatname);
2034:                        throw ex;
2035:                    }
2036:                }
2037:                return c;
2038:            }
2039:
2040:            /************************************************************************
2041:             * Loading Packages
2042:             ***********************************************************************/
2043:
2044:            /** Check to see if a package exists, given its fully qualified name.
2045:             */
2046:            public boolean packageExists(Name fullname) {
2047:                return enterPackage(fullname).exists();
2048:            }
2049:
2050:            /** Make a package, given its fully qualified name.
2051:             */
2052:            public PackageSymbol enterPackage(Name fullname) {
2053:                PackageSymbol p = packages.get(fullname);
2054:                if (p == null) {
2055:                    assert !fullname.isEmpty() : "rootPackage missing!";
2056:                    p = new PackageSymbol(Convert.shortName(fullname),
2057:                            enterPackage(Convert.packagePart(fullname)));
2058:                    p.completer = this ;
2059:                    packages.put(fullname, p);
2060:                }
2061:                return p;
2062:            }
2063:
2064:            /** Make a package, given its unqualified name and enclosing package.
2065:             */
2066:            public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
2067:                return enterPackage(TypeSymbol.formFullName(name, owner));
2068:            }
2069:
2070:            /** Include class corresponding to given class file in package,
2071:             *  unless (1) we already have one the same kind (.class or .java), or
2072:             *         (2) we have one of the other kind, and the given class file
2073:             *             is older.
2074:             */
2075:            protected void includeClassFile(PackageSymbol p, JavaFileObject file) {
2076:                if ((p.flags_field & EXISTS) == 0)
2077:                    for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
2078:                        q.flags_field |= EXISTS;
2079:                JavaFileObject.Kind kind = file.getKind();
2080:                int seen;
2081:                if (kind == JavaFileObject.Kind.CLASS)
2082:                    seen = CLASS_SEEN;
2083:                else
2084:                    seen = SOURCE_SEEN;
2085:                String binaryName = fileManager.inferBinaryName(currentLoc,
2086:                        file);
2087:                int lastDot = binaryName.lastIndexOf(".");
2088:                Name classname = names.fromString(binaryName
2089:                        .substring(lastDot + 1));
2090:                boolean isPkgInfo = classname == names.package_info;
2091:                ClassSymbol c = isPkgInfo ? p.package_info
2092:                        : (ClassSymbol) p.members_field.lookup(classname).sym;
2093:                if (c == null) {
2094:                    c = enterClass(classname, p);
2095:                    if (c.classfile == null) // only update the file if's it's newly created
2096:                        c.classfile = file;
2097:                    if (isPkgInfo) {
2098:                        p.package_info = c;
2099:                    } else {
2100:                        if (c.owner == p) // it might be an inner class
2101:                            p.members_field.enter(c);
2102:                    }
2103:                } else if (c.classfile != null && (c.flags_field & seen) == 0) {
2104:                    // if c.classfile == null, we are currently compiling this class
2105:                    // and no further action is necessary.
2106:                    // if (c.flags_field & seen) != 0, we have already encountered
2107:                    // a file of the same kind; again no further action is necessary.
2108:                    if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0)
2109:                        c.classfile = preferredFileObject(file, c.classfile);
2110:                }
2111:                c.flags_field |= seen;
2112:            }
2113:
2114:            /** Implement policy to choose to derive information from a source
2115:             *  file or a class file when both are present.  May be overridden
2116:             *  by subclasses.
2117:             */
2118:            protected JavaFileObject preferredFileObject(JavaFileObject a,
2119:                    JavaFileObject b) {
2120:
2121:                if (preferSource)
2122:                    return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b;
2123:                else {
2124:                    long adate = a.getLastModified();
2125:                    long bdate = b.getLastModified();
2126:                    // 6449326: policy for bad lastModifiedTime in ClassReader
2127:                    //assert adate >= 0 && bdate >= 0;
2128:                    return (adate > bdate) ? a : b;
2129:                }
2130:            }
2131:
2132:            /**
2133:             * specifies types of files to be read when filling in a package symbol
2134:             */
2135:            protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
2136:                return EnumSet.of(JavaFileObject.Kind.CLASS,
2137:                        JavaFileObject.Kind.SOURCE);
2138:            }
2139:
2140:            /**
2141:             * this is used to support javadoc
2142:             */
2143:            protected void extraFileActions(PackageSymbol pack,
2144:                    JavaFileObject fe) {
2145:            }
2146:
2147:            protected Location currentLoc; // FIXME
2148:
2149:            private boolean verbosePath = true;
2150:
2151:            /** Load directory of package into members scope.
2152:             */
2153:            private void fillIn(PackageSymbol p) throws IOException {
2154:                if (p.members_field == null)
2155:                    p.members_field = new Scope(p);
2156:                String packageName = p.fullname.toString();
2157:
2158:                Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
2159:
2160:                fillIn(p, PLATFORM_CLASS_PATH, fileManager.list(
2161:                        PLATFORM_CLASS_PATH, packageName, EnumSet
2162:                                .of(JavaFileObject.Kind.CLASS), false));
2163:
2164:                Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
2165:                classKinds.remove(JavaFileObject.Kind.SOURCE);
2166:                boolean wantClassFiles = !classKinds.isEmpty();
2167:
2168:                Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
2169:                sourceKinds.remove(JavaFileObject.Kind.CLASS);
2170:                boolean wantSourceFiles = !sourceKinds.isEmpty();
2171:
2172:                boolean haveSourcePath = fileManager.hasLocation(SOURCE_PATH);
2173:
2174:                if (verbose && verbosePath) {
2175:                    if (fileManager instanceof  StandardJavaFileManager) {
2176:                        StandardJavaFileManager fm = (StandardJavaFileManager) fileManager;
2177:                        if (haveSourcePath && wantSourceFiles) {
2178:                            List<File> path = List.nil();
2179:                            for (File file : fm.getLocation(SOURCE_PATH)) {
2180:                                path = path.prepend(file);
2181:                            }
2182:                            printVerbose("sourcepath", path.reverse()
2183:                                    .toString());
2184:                        } else if (wantSourceFiles) {
2185:                            List<File> path = List.nil();
2186:                            for (File file : fm.getLocation(CLASS_PATH)) {
2187:                                path = path.prepend(file);
2188:                            }
2189:                            printVerbose("sourcepath", path.reverse()
2190:                                    .toString());
2191:                        }
2192:                        if (wantClassFiles) {
2193:                            List<File> path = List.nil();
2194:                            for (File file : fm
2195:                                    .getLocation(PLATFORM_CLASS_PATH)) {
2196:                                path = path.prepend(file);
2197:                            }
2198:                            for (File file : fm.getLocation(CLASS_PATH)) {
2199:                                path = path.prepend(file);
2200:                            }
2201:                            printVerbose("classpath", path.reverse().toString());
2202:                        }
2203:                    }
2204:                }
2205:
2206:                if (wantSourceFiles && !haveSourcePath) {
2207:                    fillIn(p, CLASS_PATH, fileManager.list(CLASS_PATH,
2208:                            packageName, kinds, false));
2209:                } else {
2210:                    if (wantClassFiles)
2211:                        fillIn(p, CLASS_PATH, fileManager.list(CLASS_PATH,
2212:                                packageName, classKinds, false));
2213:                    if (wantSourceFiles)
2214:                        fillIn(p, SOURCE_PATH, fileManager.list(SOURCE_PATH,
2215:                                packageName, sourceKinds, false));
2216:                }
2217:                verbosePath = false;
2218:            }
2219:
2220:            // where
2221:            private void fillIn(PackageSymbol p, Location location,
2222:                    Iterable<JavaFileObject> files) {
2223:                currentLoc = location;
2224:                for (JavaFileObject fo : files) {
2225:                    switch (fo.getKind()) {
2226:                    case CLASS:
2227:                    case SOURCE: {
2228:                        // TODO pass binaryName to includeClassFile
2229:                        String binaryName = fileManager.inferBinaryName(
2230:                                currentLoc, fo);
2231:                        String simpleName = binaryName.substring(binaryName
2232:                                .lastIndexOf(".") + 1);
2233:                        if (SourceVersion.isIdentifier(simpleName)
2234:                                || simpleName.equals("package-info"))
2235:                            includeClassFile(p, fo);
2236:                        break;
2237:                    }
2238:                    default:
2239:                        extraFileActions(p, fo);
2240:                    }
2241:                }
2242:            }
2243:
2244:            /** Output for "-verbose" option.
2245:             *  @param key The key to look up the correct internationalized string.
2246:             *  @param arg An argument for substitution into the output string.
2247:             */
2248:            private void printVerbose(String key, CharSequence arg) {
2249:                Log.printLines(log.noticeWriter, Log.getLocalizedString(
2250:                        "verbose." + key, arg));
2251:            }
2252:
2253:            /** Output for "-checkclassfile" option.
2254:             *  @param key The key to look up the correct internationalized string.
2255:             *  @param arg An argument for substitution into the output string.
2256:             */
2257:            private void printCCF(String key, Object arg) {
2258:                Log.printLines(log.noticeWriter, Log.getLocalizedString(key,
2259:                        arg));
2260:            }
2261:
2262:            public interface SourceCompleter {
2263:                void complete(ClassSymbol sym) throws CompletionFailure;
2264:            }
2265:
2266:            /**
2267:             * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
2268:             * The attribute is only the last component of the original filename, so is unlikely
2269:             * to be valid as is, so operations other than those to access the name throw
2270:             * UnsupportedOperationException
2271:             */
2272:            private static class SourceFileObject extends BaseFileObject {
2273:
2274:                /** The file's name.
2275:                 */
2276:                private Name name;
2277:
2278:                public SourceFileObject(Name name) {
2279:                    this .name = name;
2280:                }
2281:
2282:                public InputStream openInputStream() {
2283:                    throw new UnsupportedOperationException();
2284:                }
2285:
2286:                public OutputStream openOutputStream() {
2287:                    throw new UnsupportedOperationException();
2288:                }
2289:
2290:                public Reader openReader() {
2291:                    throw new UnsupportedOperationException();
2292:                }
2293:
2294:                public Writer openWriter() {
2295:                    throw new UnsupportedOperationException();
2296:                }
2297:
2298:                /** @deprecated see bug 6410637 */
2299:                @Deprecated
2300:                public String getName() {
2301:                    return name.toString();
2302:                }
2303:
2304:                public long getLastModified() {
2305:                    throw new UnsupportedOperationException();
2306:                }
2307:
2308:                public boolean delete() {
2309:                    throw new UnsupportedOperationException();
2310:                }
2311:
2312:                public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
2313:                    throw new UnsupportedOperationException();
2314:                }
2315:
2316:                @Override
2317:                public boolean equals(Object other) {
2318:                    if (!(other instanceof  SourceFileObject))
2319:                        return false;
2320:                    SourceFileObject o = (SourceFileObject) other;
2321:                    return name.equals(o.name);
2322:                }
2323:
2324:                @Override
2325:                public int hashCode() {
2326:                    return name.hashCode();
2327:                }
2328:
2329:                public boolean isNameCompatible(String simpleName,
2330:                        JavaFileObject.Kind kind) {
2331:                    return true; // fail-safe mode
2332:                }
2333:
2334:                public URI toUri() {
2335:                    return URI.create(name.toString());
2336:                }
2337:
2338:                public Reader openReader(boolean ignoreEncodingErrors)
2339:                        throws IOException {
2340:                    throw new UnsupportedOperationException();
2341:                }
2342:
2343:            }
2344:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.