Source Code Cross Referenced for ClassTable.java in  » UML » jrefactory » org » acm » seguin » completer » info » 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 » UML » jrefactory » org.acm.seguin.completer.info 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  ClassTable.java - part of the CodeAid plugin.
003:         *  Copyright (C) 1999 Jason Ginchereau
004:         *
005:         *  This program is free software; you can redistribute it and/or
006:         *  modify it under the terms of the GNU General Public License
007:         *  as published by the Free Software Foundation; either version 2
008:         *  of the License, or any later version.
009:         *
010:         *  This program is distributed in the hope that it will be useful,
011:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
012:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013:         *  GNU General Public License for more details.
014:         *
015:         *  You should have received a copy of the GNU General Public License
016:         *  along with this program; if not, write to the Free Software
017:         *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
018:         */
019:        package org.acm.seguin.completer.info;
020:
021:        // Collections API
022:        import org.acm.seguin.completer.*;
023:        import java.util.StringTokenizer; //import anthelper.ClassNameCache;
024:        import org.acm.seguin.ide.jedit.Navigator.NavigatorLogger;
025:        import org.acm.seguin.completer.Completer;
026:        import gnu.regexp.RE;
027:        import java.io.EOFException;
028:        import java.io.IOException;
029:        import java.io.ObjectInputStream;
030:        import java.io.ObjectOutputStream;
031:        import java.lang.reflect.Modifier;
032:        import java.net.URL;
033:        import java.net.URLClassLoader;
034:        import java.util.ArrayList;
035:        import java.util.Collection;
036:        import java.util.Enumeration;
037:        import java.util.HashMap;
038:        import java.util.HashSet;
039:        import java.util.Iterator;
040:        import java.util.LinkedList;
041:        import java.util.List;
042:        import java.util.Map;
043:        import java.util.Set;
044:        import java.util.SortedMap;
045:        import java.util.TreeMap;
046:        import java.util.TreeSet;
047:        import java.util.zip.ZipEntry;
048:        import java.util.zip.ZipFile;
049:        import java.util.zip.ZipInputStream;
050:        import java.util.zip.ZipOutputStream;
051:
052:        /**
053:         * Maps class names to information that is known about those classes.
054:         * Information about each class is stored in a <code>ClassInfo</code> object.
055:         * All methods are thread-safe.
056:         *
057:         * @author    Jason Ginchereau
058:         * @created   December 12, 2002
059:         * @see       ClassInfo
060:         */
061:        public final class ClassTable implements  java.io.Serializable {
062:            /**
063:             * Description of the Field
064:             */
065:            public final static String UNNAMED_PACKAGE = "<unnamed package>";
066:
067:            private static Map staticInstanceTable = new HashMap();
068:            private final static Object DEFAULT_KEY = new String();
069:
070:            final static NavigatorLogger logger = Completer
071:                    .getLogger(ClassTable.class);
072:            final static boolean DEBUG = true;
073:
074:            /**
075:             * Gets a static instance of a <code>ClassTable</code> that can be shared by
076:             * everyone with the same key.
077:             *
078:             * @param key  Description of the Parameter
079:             * @return     The instance value
080:             */
081:            private static synchronized ClassTable getInstance(Object key) {
082:                ClassTable instance = (ClassTable) staticInstanceTable.get(key);
083:                if (instance == null) {
084:                    instance = new ClassTable();
085:                    staticInstanceTable.put(key, instance);
086:                }
087:                return instance;
088:            }
089:
090:            /**
091:             * Gets the existingInstance attribute of the ClassTable class
092:             *
093:             * @param argSource  the class path src
094:             * @return        The existingInstance value
095:             */
096:            public static synchronized ClassTable getExistingInstance(
097:                    ClassPathSrc argSource) {
098:                return (ClassTable) staticInstanceTable.get(argSource.getKey());
099:            }
100:
101:            /**
102:             * Remove the instance
103:             *
104:             * @param argSource  the class path src
105:             * @return        The existingInstance value
106:             */
107:            public static synchronized ClassTable removeInstance(
108:                    ClassPathSrc argSource) {
109:                ClassTable ct = (ClassTable) staticInstanceTable
110:                        .remove(argSource.getKey());
111:                //printAll();
112:                return ct;
113:            }
114:
115:            /**
116:             * Gets a static instance of a <code>ClassTable</code> that can be shared by
117:             * everyone with the same key.
118:             *
119:             * @param argSource  the class path src
120:             * @return           The instance value
121:             */
122:            public static synchronized ClassTable getInstance(
123:                    ClassPathSrc argSource) {
124:                ClassTable instance = (ClassTable) staticInstanceTable
125:                        .get(argSource.getKey());
126:                if (instance == null) {
127:                    ClassNameCache cnc = argSource.getCNC();
128:                    // this will be a very verbose message...but helpful
129:                    //logger.debug("** Creating ClassTable for ClassNameCache: ", cnc.toString());
130:                    instance = new ClassTable(getInstance(), cnc
131:                            .getAllClassInfos(), createClassLoader(cnc));
132:                    staticInstanceTable.put(argSource.getKey(), instance);
133:                }
134:                //printAll();
135:                return instance;
136:            }
137:
138:            static void printAll() {
139:                Object objKey;
140:                Object objVal;
141:                ClassNameCache cnc = null;
142:                for (Iterator it = staticInstanceTable.keySet().iterator(); it
143:                        .hasNext();) {
144:                    objKey = it.next();
145:                    objVal = staticInstanceTable.get(objKey);
146:                    if (objKey instanceof  ClassNameCache) {
147:                        cnc = (ClassNameCache) objKey;
148:                        logger.debug("cnc=" + cnc.getName(), "ct="
149:                                + objVal.hashCode());
150:                    } else {
151:                        logger.debug("cnc=" + objKey.toString(), "ct="
152:                                + objVal.hashCode());
153:                    }
154:
155:                }
156:            }
157:
158:            private static ClassLoader createClassLoader(ClassNameCache argCNC) {
159:                // 1 arg cons will make system class loader parent
160:                // which do we want?
161:                URLClassLoader classLoader = new URLClassLoader(argCNC
162:                        .getClassPathAsURLs(), Completer.class.getClassLoader());
163:                return classLoader;
164:            }
165:
166:            /**
167:             * Gets a static instance of a <code>ClassTable</code> using the default
168:             * key.
169:             *
170:             * @return   The instance value
171:             */
172:            public static ClassTable getInstance() {
173:                return getInstance(DEFAULT_KEY);
174:            }
175:
176:            private transient ClassTable parent;
177:            private transient SortedMap arrays;
178:            private SortedMap packages;
179:            private SortedMap classes;
180:            private ClassLoader _classLoader = null;
181:
182:            /**
183:             * Creates a new <code>ClassTable</code>.
184:             */
185:            public ClassTable() {
186:                // by default, use
187:                this (null, ClassNameCache.getBootClassList(), Completer.class
188:                        .getClassLoader());
189:
190:            }
191:
192:            /**
193:             * Creates a new <code>ClassTable</code> which will delegate to a parent
194:             * <code>ClassTable</code> for unrecognized classes.
195:             *
196:             * @param argParent             Description of the Parameter
197:             * @param argListCNCClassInfos  Description of the Parameter
198:             * @param argClassLoader        Description of the Parameter
199:             */
200:
201:            /**
202:             * Constructor for the ClassTable object
203:             *
204:             * @param argParent             Description of the Parameter
205:             * @param argListCNCClassInfos  Description of the Parameter
206:             * @param argClassLoader        Description of the Parameter
207:             */
208:            public ClassTable(ClassTable argParent, List argListCNCClassInfos,
209:                    ClassLoader argClassLoader) {
210:                this .parent = argParent;
211:                arrays = new TreeMap(new StringComparator());
212:                packages = new TreeMap(new StringComparator());
213:                classes = new TreeMap(new StringComparator());
214:                // load all classes
215:                init(argListCNCClassInfos, argClassLoader);
216:            }
217:
218:            /**
219:             * Description of the Method
220:             *
221:             * @param argCNC  Description of the Parameter
222:             */
223:            public synchronized void reinit(ClassPathSrc argSource) {
224:                ClassNameCache cnc = argSource.getCNC();
225:                List listAll = cnc.getAllClassInfos();
226:                logger.msg("reinit", listAll.size());
227:                arrays.clear();
228:                packages.clear();
229:                classes.clear();
230:                init(listAll, createClassLoader(cnc));
231:            }
232:
233:            private void init(List argListCNCClassInfos,
234:                    ClassLoader argClassLoader) {
235:                preLoad(argListCNCClassInfos);
236:                _classLoader = argClassLoader;
237:
238:            }
239:
240:            /**
241:             * Gets the parent <code>ClassTable</code>, which is be queried for classes
242:             * that are not recognized by this <code>ClassTable</code>.
243:             *
244:             * @return   The parent value
245:             */
246:            public ClassTable getParent() {
247:                return parent;
248:            }
249:
250:            /**
251:             * Sets the parent <code>ClassTable</code>, which will be queried for
252:             * classes that are not recognized by this <code>ClassTable</code>.
253:             *
254:             * @param parent  The new parent value
255:             */
256:            public synchronized void setParent(ClassTable parent) {
257:                this .parent = parent;
258:            }
259:
260:            /**
261:             * Gets a list of all packages in the database.
262:             *
263:             * @return   a sorted <code>List</code> of <code>Strings</code>, where each
264:             *      <code>String</code> is a name of a package in the database. This
265:             *      <code>List</code> may be safely modified by the user, as it is no
266:             *      longer connected to the database after it is returned.
267:             */
268:            public synchronized List getPackages() {
269:                return new LinkedList(packages.keySet());
270:            }
271:
272:            /**
273:             * Gets a list of all known classes in a package.
274:             *
275:             * @param packageName  the name of the package, using the java . notation.
276:             * @return             a sorted <code>List</code> of <code>String</code>
277:             *      names, or <code>null</code> if the package is unknown. This <code>List</code>
278:             *      may be safely modified by the user, as it is no longer connected to
279:             *      the database after it is returned.
280:             */
281:            public synchronized List getClassesInPackage(String packageName) {
282:                Map pmap = (Map) packages.get(packageName);
283:                if (pmap != null) {
284:                    return new LinkedList(pmap.keySet());
285:                } else if (parent != null) {
286:                    return parent.getClassesInPackage(packageName);
287:                } else {
288:                    return null;
289:                }
290:            }
291:
292:            /**
293:             * Returns a list of all classes in the given package. Items in this list
294:             * may not have been fully loaded into the class table yet. The list
295:             * contains _full_ class names
296:             *
297:             * @param argPackage  The package name (java.util) or (java.util.*)
298:             * @return            The allClassesInPackage value
299:             */
300:            public synchronized List getAllClassesInPackage(String argPackage) {
301:                List listClasses = new ArrayList();
302:                String strPkg = argPackage;
303:                if (strPkg.endsWith(".*")) {
304:                    strPkg = strPkg.substring(0, strPkg.length() - 2);
305:                }
306:                String strFullName;
307:                for (Iterator it = classes.keySet().iterator(); it.hasNext();) {
308:                    strFullName = it.next().toString();
309:                    if (strFullName.startsWith(strPkg)
310:                            && strFullName.indexOf(".", strPkg.length() + 1) == -1) {
311:                        listClasses.add(strFullName);
312:                    }
313:                }
314:                if (parent != null) {
315:                    listClasses.addAll(parent.getAllClassesInPackage(strPkg));
316:                }
317:                return listClasses;
318:            }
319:
320:            int _iLastClassCount = -1;
321:            Set _setClassNames = null;
322:            String _strExclusionRE = null;
323:
324:            /**
325:             * Returns a set of all class names in this table except classes whose full
326:             * names match the given regexp.
327:             *
328:             * @param argExclusionRE  a regexp
329:             * @return                The allClassNames valuere
330:             */
331:            public synchronized Set getAllClassNames(String argExclusionRE) {
332:
333:                if (_setClassNames == null
334:                        || _setClassNames.size() != _iLastClassCount
335:                        || !argExclusionRE.equals(_strExclusionRE)) {
336:
337:                    RE reExclude = null;
338:                    try {
339:                        reExclude = new RE(argExclusionRE);
340:                    } catch (Exception e) {
341:                        logger
342:                                .error("Error filtering on: " + argExclusionRE,
343:                                        e);
344:                    }
345:                    _setClassNames = new HashSet();
346:
347:                    logger.msg("Creating new class list with RE",
348:                            argExclusionRE);
349:                    if (reExclude == null) {
350:                        // reexp failed...return all
351:                        for (Iterator it = classes.keySet().iterator(); it
352:                                .hasNext();) {
353:                            _setClassNames.add(it.next().toString());
354:                        }
355:                    } else {
356:                        String strCN;
357:                        for (Iterator it = classes.keySet().iterator(); it
358:                                .hasNext();) {
359:                            strCN = it.next().toString();
360:                            if (!reExclude.isMatch(strCN)) {
361:                                _setClassNames.add(strCN);
362:                            }
363:                        }
364:
365:                    }
366:                    if (parent != null) {
367:                        // get parent's classes
368:                        _setClassNames.addAll(this .parent
369:                                .getAllClassNames(argExclusionRE));
370:                    }
371:                    _iLastClassCount = _setClassNames.size();
372:                    _strExclusionRE = argExclusionRE;
373:                }
374:                return _setClassNames;
375:            }
376:
377:            /**
378:             * The main program for the ClassTable class
379:             *
380:             * @param args  The command line arguments
381:             */
382:            public static void main(String[] args) {
383:                try {
384:
385:                    ClassTable ct = new ClassTable();
386:                    //ClassNameCache cnc = new ClassNameCache(System.getProperty("sun.boot.class.path"));
387:
388:                } catch (Throwable t) {
389:                    t.printStackTrace();
390:                }
391:            }
392:
393:            static void oldTest() {
394:                try {
395:                    /*
396:                     *  ClassTable ct = new ClassTable();
397:                     *  List list = ct.getAllClassesInPackage("java.util.*");
398:                     *  for (Iterator it = list.iterator(); it.hasNext(); ) {
399:                     *  logger.msg(it.next().toString());
400:                     *  }
401:                     */
402:                    ClassTable ct = new ClassTable();
403:                    Set setClasses = null;
404:                    for (int i = 0; i < 1; i++) {
405:                        long lStart = System.currentTimeMillis();
406:                        setClasses = ct
407:                                .getAllClassNames("^sun\\..*|^COM\\.rsa\\..*|^com\\.sun\\..*|^org\\.omg\\.CORBA\\..*");
408:                        logger.msg("time(ms)", ""
409:                                + (System.currentTimeMillis() - lStart));
410:                    }
411:                    int iMax = 0;
412:                    String str = null;
413:                    ArrayList listMaxes = new ArrayList();
414:                    for (Iterator it = setClasses.iterator(); it.hasNext();) {
415:                        str = it.next().toString();
416:                        //if (str.length() > iMax){
417:                        if (str.length() > 40) {
418:                            iMax = str.length();
419:                            listMaxes.add(str);
420:                        }
421:                    }
422:                    logger.msg("max size", iMax);
423:                    String strCN = null;
424:                    String strPkg = null;
425:                    String strFN = null;
426:                    for (Iterator it = listMaxes.iterator(); it.hasNext();) {
427:                        strFN = it.next().toString();
428:                        strPkg = strFN.substring(0, strFN.lastIndexOf(".") + 1);
429:                        if (strPkg.endsWith(".")) {
430:                            //strPkg = strPkg.substring(0, strPkg.length() - 1);
431:                        }
432:                        StringTokenizer st = new StringTokenizer(strPkg, ".");
433:                        int iN = st.countTokens();
434:                        if (iN <= 2) {
435:                            // skip stuff liek java.util.Vector
436:                        } else {
437:                            // remove parts, 3-> N-1
438:                            StringBuffer sbPkg = new StringBuffer();
439:                            sbPkg.append(st.nextToken()).append(".");
440:                            sbPkg.append(st.nextToken()).append(".");
441:                            for (; st.hasMoreTokens(); st.nextToken()) {
442:                                if (st.hasMoreTokens()) {
443:                                    sbPkg.append("~");
444:                                } else {
445:                                    sbPkg.append(".");
446:                                }
447:                            }
448:                            strPkg = sbPkg.toString();
449:                        }
450:                        strCN = strFN.substring(strFN.lastIndexOf(".") + 1);
451:                        logger.msg(strPkg + strCN);
452:                    }
453:                    int iSize = setClasses.size();
454:                    logger.msg("size", iSize);
455:                    int i = 0;
456:                    /*
457:                     *  for (Iterator it = setClasses.iterator();
458:                     *  i < 10 && it.hasNext(); i++) {
459:                     *  logger.msg(it.next().toString());
460:                     *  }
461:                     */
462:                } catch (Throwable t) {
463:                    t.printStackTrace();
464:                }
465:            }
466:
467:            /**
468:             * Gets information about a class, given a class name.
469:             *
470:             * @param fullClassName  a fully-qualified class name. Note that for inner
471:             *      classes, the <code>$</code> notation is used in the class name.
472:             *      Example: <code>java.lang.Character$Subset</code>
473:             * @return               the <code>ClassInfo</code> object for the class, or
474:             *      <code>null</code> if the class is not in the database.
475:             */
476:            public synchronized ClassInfo get(String fullClassName) {
477:                if (fullClassName.endsWith("[]")) {
478:                    ClassInfo aci = (ClassInfo) arrays.get(fullClassName);
479:
480:                    if (aci == null) {
481:                        String originalName = fullClassName;
482:                        int dimensions = 0;
483:                        do {
484:                            fullClassName = fullClassName.substring(0,
485:                                    fullClassName.length() - 2);
486:                            dimensions++;
487:                        } while (fullClassName.endsWith("[]"));
488:
489:                        ClassInfo ci = get(fullClassName);
490:                        if (ci != null) {
491:                            aci = new ArrayClassInfo(ci, dimensions);
492:                            arrays.put(originalName, aci);
493:                        }
494:                    }
495:                    return aci;
496:                } else {
497:                    ClassInfo ci = getAndLazyLoad(fullClassName);
498:                    if (ci == null && parent != null) {
499:                        // try parent
500:                        return parent.get(fullClassName);
501:                    } else {
502:                        return ci;
503:                    }
504:
505:                    /*
506:                     *  OLD code
507:                     *  Object o = classes.get(fullClassName);
508:                     *  /logger.msg("[" + fullClassName + "] o is a ", o == null ? "null" : o.getClass().getName());
509:                     *  if (o instanceof ClassNameCache.ClassInfo) {
510:                     *  ClassNameCache.ClassInfo ci = (ClassNameCache.ClassInfo) o;
511:                     *  logger.debug("Loading class" + ci.getClassName());
512:                     *  load(fullClassName);
513:                     *  o = classes.get(fullClassName);
514:                     *  if (o instanceof ClassNameCache.ClassInfo) {
515:                     *  logger.debug("ClassInfo could not be created for (" + ci.getClassName() +
516:                     *  ") found in (" + ci.getSrc() + ")");
517:                     *  }
518:                     *  }
519:                     *  /logger.msg("now, o is a", o.getClass().getName());
520:                     *  if (o != null && o instanceof ClassInfo) {
521:                     *  return (ClassInfo) o;
522:                     *  } else if (parent != null) {
523:                     *  return parent.get(fullClassName);
524:                     *  } else {
525:                     *  return null;
526:                     *  }
527:                     */
528:                }
529:            }
530:
531:            /**
532:             * Attempts to get the ClassInfo object for the given class name. This
533:             * method does the lazy loading that will convert a ClassNameCache.ClassInfo
534:             * into ClassInfo. If not ClassInfo can be loaded, null is returned.
535:             *
536:             * @param argFullClassName  Description of the Parameter
537:             * @return                  The andLazyLoad value
538:             */
539:            public ClassInfo getAndLazyLoad(String argFullClassName) {
540:                ClassInfo ciResult = null;
541:                Object o = classes.get(argFullClassName);
542:                if (o == null) {
543:                    //logger.msg("Class !found, class (" + argFullClassName + "), parent (" + parent + ")");
544:                } else if (o instanceof  ClassNameCache.ClassInfo) {
545:                    //logger.msg("Lazy loading, class", argFullClassName);
546:                    ClassNameCache.ClassInfo ci = (ClassNameCache.ClassInfo) o;
547:
548:                    load(argFullClassName);
549:                    o = classes.get(argFullClassName);
550:                    if (o instanceof  ClassNameCache.ClassInfo) {
551:                        if (Completer.DEBUG) {
552:                            logger
553:                                    .debug("## ClassInfo could not be created for ("
554:                                            + ci.getFullClassName()
555:                                            + ") found in ("
556:                                            + ci.getSrc()
557:                                            + ")");
558:                        }
559:                    } else {
560:                        ciResult = (ClassInfo) o;
561:                    }
562:                } else {
563:                    //if (o instanceof ClassInfo){g
564:                    ciResult = (ClassInfo) o;
565:                }
566:                return ciResult;
567:            }
568:
569:            /**
570:             * Enters class information into the database.
571:             *
572:             * @param classInfo  a <code>ClassInfo</code> object that information about
573:             *      a class to be put in the database. This object should not be
574:             *      modified after it is put in the database.
575:             */
576:            public synchronized void put(ClassInfo classInfo) {
577:                if (classInfo instanceof  ArrayClassInfo) {
578:                    throw new IllegalArgumentException(
579:                            "Can't put array classes in ClassTable.");
580:                }
581:                //logger.msg("putting", classInfo.getFullName());
582:                // Don't put inner classes in the package map.
583:                if (classInfo.getDeclaringClass() == null) {
584:                    String packageName = classInfo.getPackage();
585:                    if (packageName == null) {
586:                        packageName = UNNAMED_PACKAGE;
587:                    }
588:                    Map pmap = (Map) packages.get(packageName);
589:                    if (pmap == null) {
590:                        packages.put(packageName, pmap = new TreeMap(
591:                                new StringComparator()));
592:                    }
593:                    pmap.put(classInfo.getName(), classInfo);
594:                } else {
595:                    //if (DEBUG)logger.msg("----INNER: ", classInfo.getFullName());
596:                }
597:                String strFN = classInfo.getFullName();
598:                classes.put(classInfo.getFullName(), classInfo);
599:            }
600:
601:            /**
602:             * Removes a class from the database.
603:             *
604:             * @param fullClassName  a fully-qualified class name. Note that for inner
605:             *      classes, the <code>$</code> notation is used in the class name.
606:             * @return               the <code>ClassInfo</code> object that was removed
607:             *      from the database, or <code>null</code> if there was not one.
608:             */
609:            public synchronized ClassInfo remove(String fullClassName) {
610:                logger.msg("Removing", fullClassName);
611:
612:                ClassInfo ci = (ClassInfo) classes.remove(fullClassName);
613:                if (ci != null) {
614:                    String packageName = ci.getPackage();
615:                    if (packageName == null) {
616:                        packageName = UNNAMED_PACKAGE;
617:                    }
618:                    Map pmap = (Map) packages.get(packageName);
619:                    if (pmap != null) {
620:                        pmap.remove(ci.getName());
621:                        if (pmap.isEmpty()) {
622:                            packages.remove(packageName);
623:                        }
624:                    }
625:                }
626:                return ci;
627:            }
628:
629:            /**
630:             * Tests if a class is contained in the database.
631:             *
632:             * @param fullClassName  a fully-qualified class name. Note that for inner
633:             *      classes, the <code>$</code> notation is used in the class name.
634:             * @return               <code>true</code> if information about the class is
635:             *      in the database.
636:             */
637:            public synchronized boolean contains(String fullClassName) {
638:                return classes.containsKey(fullClassName);
639:            }
640:
641:            /**
642:             * Gets the assignableTo attribute of the ClassTable object
643:             *
644:             * @param fromClass      Description of the Parameter
645:             * @param toClass        Description of the Parameter
646:             * @param defaultAnswer  Description of the Parameter
647:             * @return               The assignableTo value
648:             */
649:            public boolean isAssignableTo(String fromClass, String toClass,
650:                    boolean defaultAnswer) {
651:                ClassInfo fci = get(fromClass);
652:                ClassInfo tci = get(toClass);
653:
654:                // return defaultAnswer when one or both classes are unrecognized
655:                if (fci == null || tci == null) {
656:                    return defaultAnswer;
657:                }
658:
659:                // a class is assignable to itself
660:                if (fci.equals(tci)) {
661:                    return true;
662:                }
663:
664:                // handling arrays
665:                if (fci instanceof  ArrayClassInfo
666:                        && tci instanceof  ArrayClassInfo) {
667:                    ArrayClassInfo afci = (ArrayClassInfo) fci;
668:                    ArrayClassInfo atci = (ArrayClassInfo) tci;
669:                    if (afci.getDimensions() != atci.getDimensions()) {
670:                        return false;
671:                    }
672:                    return isAssignableTo(afci.getArrayType().getFullName(),
673:                            atci.getArrayType().getFullName(), defaultAnswer);
674:                }
675:
676:                // a class is assignable if its superclass is assignable
677:                if (fci.getSuperclass() != null
678:                        && isAssignableTo(fci.getSuperclass(), toClass,
679:                                defaultAnswer)) {
680:                    return true;
681:                }
682:
683:                // a class is assignable if any of its interfaces are assignable
684:                String[] ifs = fci.getInterfaces();
685:                for (int i = 0; i < ifs.length; i++) {
686:                    if (isAssignableTo(ifs[i], toClass, defaultAnswer)) {
687:                        return true;
688:                    }
689:                }
690:
691:                return false;
692:            }
693:
694:            /**
695:             * Gets the accessAllowed attribute of the ClassTable object
696:             *
697:             * @param in             Description of the Parameter
698:             * @param target         Description of the Parameter
699:             * @param requireStatic  Description of the Parameter
700:             * @param defaultAnswer  Description of the Parameter
701:             * @return               The accessAllowed value
702:             */
703:            public boolean isAccessAllowed(ClassInfo in, MemberInfo target,
704:                    boolean requireStatic, boolean defaultAnswer) {
705:                int mods = target.getModifiers();
706:                if (requireStatic && (mods & Modifier.STATIC) == 0) {
707:                    return false;
708:                }
709:
710:                String dc = target.getDeclaringClass();
711:                ClassInfo dci = (dc != null ? (ClassInfo) get(dc) : null);
712:                if (dci != null) {
713:                    if (!isAccessAllowed(in, dci, false, defaultAnswer)) {
714:                        return false;
715:                    }
716:                } else if (dc != null) {
717:                    if (!defaultAnswer) {
718:                        return false;
719:                    }
720:                }
721:
722:                if (target instanceof  ClassInfo && dc == null) {
723:                    // top-level class
724:                    if ((mods & Modifier.PUBLIC) != 0) {
725:                        return true;
726:                    } else {
727:                        String ip = (in != null ? in.getPackage() : null);
728:                        String cp = ((ClassInfo) target).getPackage();
729:                        if ((ip == null && cp == null)
730:                                || (ip != null && cp != null && ip.equals(cp))) {
731:                            return true;
732:                        }
733:                    }
734:                    return false;
735:                }
736:
737:                if ((mods & Modifier.PUBLIC) != 0) {
738:                    // public access
739:                    return true;
740:                }
741:
742:                if (in != null && dci != null) {
743:                    String cn = dci.getFullName();
744:                    String cp = dci.getPackage();
745:                    String icn = in.getFullName();
746:                    String icp = in.getPackage();
747:
748:                    if ((mods & Modifier.PROTECTED) != 0) {
749:                        // protected access
750:                        if (isAssignableTo(icn, cn, false)
751:                                || (cp == null && icp == null)
752:                                || (cp != null && icp != null && cp.equals(icp))) {
753:                            return true;
754:                        }
755:                    } else if ((mods & Modifier.PRIVATE) == 0) {
756:                        // package access
757:                        if ((cp == null && icp == null)
758:                                || (cp != null && icp != null && cp.equals(icp))) {
759:                            return true;
760:                        }
761:                    } else {
762:                        // private access
763:                        if (cn.equals(icn)) {
764:                            return true;
765:                        }
766:                    }
767:
768:                    // Allow inner classes to access anything that their declaring
769:                    // classes can access.. is this correct?
770:                    String idc = in.getDeclaringClass();
771:                    if (idc != null) {
772:                        ClassInfo idci = (ClassInfo) get(idc);
773:                        if (idci != null) {
774:                            return isAccessAllowed(idci, target, requireStatic,
775:                                    defaultAnswer);
776:                        }
777:                    }
778:                }
779:
780:                return defaultAnswer;
781:            }
782:
783:            /**
784:             * Gets the size of the database.
785:             *
786:             * @return   the number of classes in the database.
787:             */
788:            public synchronized int size() {
789:                return classes.size();
790:            }
791:
792:            private void load(String name) {
793:
794:                ClassNameCache.ClassInfo cncCI = (ClassNameCache.ClassInfo) classes
795:                        .get(name);
796:                Class cls = null;
797:
798:                // 1st try the cnc class loader
799:                try {
800:                    cls = _classLoader.loadClass(cncCI.getFullClassName());
801:                } catch (Exception ex) {
802:                    logger.msg("Could not load class via cnc class loader: "
803:                            + ex.toString());
804:
805:                }
806:
807:                // 2nd, try the parent
808:                if (cls == null && parent != null) {
809:                    logger.msg("Calling parent.load");
810:                    parent.load(name);
811:                    return;
812:                }
813:
814:                if (cls != null) {
815:                    Class clsDec = null;
816:                    try {
817:                        clsDec = cls.getDeclaringClass();
818:                    } catch (IllegalAccessError err) {
819:                        logger
820:                                .warning("Encountered IllegalAccessError getting declaring class for: ("
821:                                        + name + ")");
822:                    }
823:                    ClassInfo ci = new ClassInfo(cls, clsDec);
824:                    put(ci);
825:                    // put all inner classes
826:                    Set setInnerClasses = ci.getClasses();
827:                    for (Iterator it = setInnerClasses.iterator(); it.hasNext();) {
828:                        put((ClassInfo) it.next());
829:                    }
830:
831:                    //if (DEBUG)logger.msg("*********LOAD success", ci.getFullName());
832:                }
833:            }
834:
835:            /**
836:             * Loads <code>ClassInfo</code> entry information out of a <code>ClassNameCache</code>
837:             * . The entries themselves will not actually be loaded into memory until
838:             * they are needed.
839:             *
840:             * @param argListCNCClassInfos  Description of the Parameter
841:             */
842:            public synchronized void preLoad(List argListCNCClassInfos) {
843:                List listAll = argListCNCClassInfos;
844:                String name;
845:                String packageName;
846:                int i = 0;
847:                Map pmap;
848:                ClassNameCache.ClassInfo ci = null;
849:                for (Iterator it = listAll.iterator(); it.hasNext();) {
850:                    ci = (ClassNameCache.ClassInfo) it.next();
851:                    name = ci.getFullClassName();
852:                    packageName = UNNAMED_PACKAGE;
853:                    i = name.lastIndexOf('.');
854:                    if (i >= 0) {
855:                        packageName = name.substring(0, i);
856:                    }
857:                    pmap = (Map) packages.get(packageName);
858:                    if (pmap == null) {
859:                        packages.put(packageName, pmap = new TreeMap(
860:                                new StringComparator()));
861:                    }
862:                    classes.put(name, ci);
863:                }
864:            }
865:
866:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.