Source Code Cross Referenced for Util.java in  » IDE-Netbeans » library » org » netbeans » 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 » IDE Netbeans » library » org.netbeans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans;
043:
044:        import java.io.*;
045:        import java.util.*;
046:        import java.util.logging.Level;
047:        import java.util.logging.Logger;
048:        import org.openide.util.*;
049:        import org.openide.modules.*;
050:
051:        /** Static utility methods for use within this package.
052:         * @author Jesse Glick
053:         */
054:        public abstract class Util {
055:
056:            // Prevent accidental subclassing.
057:            private Util() {
058:            }
059:
060:            /** Log everything happening in the module system. */
061:            public static final Logger err = Logger
062:                    .getLogger("org.netbeans.core.modules"); // NOI18N
063:
064:            /**
065:             * Make a temporary copy of a JAR file.
066:             */
067:            static File makeTempJar(File moduleFile) throws IOException {
068:                String prefix = moduleFile.getName();
069:                if (prefix.endsWith(".jar") || prefix.endsWith(".JAR")) { // NOI18N
070:                    prefix = prefix.substring(0, prefix.length() - 4);
071:                }
072:                if (prefix.length() < 3)
073:                    prefix += '.';
074:                if (prefix.length() < 3)
075:                    prefix += '.';
076:                if (prefix.length() < 3)
077:                    prefix += '.';
078:                String suffix = "-test.jar"; // NOI18N
079:                File physicalModuleFile = File.createTempFile(prefix, suffix);
080:                physicalModuleFile.deleteOnExit();
081:                InputStream is = new FileInputStream(moduleFile);
082:                try {
083:                    OutputStream os = new FileOutputStream(physicalModuleFile);
084:                    try {
085:                        byte[] buf = new byte[4096];
086:                        int i;
087:                        while ((i = is.read(buf)) != -1) {
088:                            os.write(buf, 0, i);
089:                        }
090:                    } finally {
091:                        os.close();
092:                    }
093:                } finally {
094:                    is.close();
095:                }
096:                err.fine("Made " + physicalModuleFile);
097:                return physicalModuleFile;
098:            }
099:
100:            /**
101:             * Find existing locale variants of f, in search order.
102:             */
103:            static List<File> findLocaleVariantsOf(File f) {
104:                List<FileWithSuffix> result = findLocaleVariantsWithSuffixesOf(f);
105:                List<File> l = new ArrayList<File>(result.size());
106:                for (FileWithSuffix fws : result) {
107:                    l.add(fws.file);
108:                }
109:                return l;
110:            }
111:
112:            static final class FileWithSuffix {
113:                public final File file;
114:                public final String suffix;
115:
116:                FileWithSuffix(File file, String suffix) {
117:                    this .file = file;
118:                    this .suffix = suffix;
119:                }
120:            }
121:
122:            /**
123:             * Find existing locale variants of f, in search order.
124:             */
125:            static List<FileWithSuffix> findLocaleVariantsWithSuffixesOf(File f) {
126:                if (!f.isFile()) {
127:                    return Collections.emptyList();
128:                }
129:                String logicalDir = null;
130:                {
131:                    // #34069: we have to consider that e.g. modules/locale/foo_branding.jar might be
132:                    // located in a different root of ${netbeans.dirs}, so need to use IFL. Here the
133:                    // logical path would be "modules/foo.jar" for the base module.
134:                    String logicalPath = findLogicalPath(f);
135:                    if (logicalPath != null) {
136:                        int slash = logicalPath.lastIndexOf('/');
137:                        if (slash != -1) {
138:                            logicalDir = logicalPath.substring(0, slash + 1)
139:                                    + "locale/"; // NOI18N
140:                        } else {
141:                            logicalDir = "locale/"; // NOI18N
142:                        }
143:                    }
144:                }
145:                List<FileWithSuffix> l = new ArrayList<FileWithSuffix>(7);
146:                String nameExt = f.getName();
147:                int idx = nameExt.lastIndexOf('.'); // NOI18N
148:                String name, ext;
149:                if (idx != -1) {
150:                    name = nameExt.substring(0, idx);
151:                    ext = nameExt.substring(idx);
152:                } else {
153:                    name = nameExt;
154:                    ext = ""; // NOI18N
155:                }
156:                if (logicalDir != null) {
157:                    for (String suffix : getLocalizingSuffixesFast()) {
158:                        String path = logicalDir + name + suffix + ext;
159:                        File v = InstalledFileLocator.getDefault().locate(path,
160:                                null, false);
161:                        if (v != null) {
162:                            l.add(new FileWithSuffix(v, suffix));
163:                        }
164:                    }
165:                } else {
166:                    File dir = new File(f.getParentFile(), "locale"); // NOI18N
167:                    if (dir.exists()) {
168:                        for (String suffix : getLocalizingSuffixesFast()) {
169:                            File v = new File(dir, name + suffix + ext);
170:                            if (v.isFile()) {
171:                                l.add(new FileWithSuffix(v, suffix));
172:                            }
173:                        }
174:                    }
175:                }
176:                return l;
177:            }
178:
179:            /** Similar to {@link NbBundle#getLocalizingSuffixes} but optimized. 
180:             * @since JST-PENDING: Called from InstalledFileLocatorImpl
181:             */
182:            public static synchronized String[] getLocalizingSuffixesFast() {
183:                if (suffixes == null
184:                        || Locale.getDefault() != lastLocale
185:                        || !Utilities.compareObjects(NbBundle.getBranding(),
186:                                lastBranding)) {
187:                    List<String> _suffixes = new ArrayList<String>();
188:                    Iterator<String> it = NbBundle.getLocalizingSuffixes();
189:                    while (it.hasNext()) {
190:                        _suffixes.add(it.next());
191:                    }
192:                    suffixes = _suffixes.toArray(new String[_suffixes.size()]);
193:                    lastLocale = Locale.getDefault();
194:                    lastBranding = NbBundle.getBranding();
195:                }
196:                return suffixes;
197:            }
198:
199:            private static String[] suffixes = null;
200:            private static Locale lastLocale = null;
201:            private static String lastBranding = null;
202:
203:            /**
204:             * Find a path such that InstalledFileLocator.getDefault().locate(path, null, false)
205:             * yields the given file. Only guaranteed to work in case the logical path is a suffix of
206:             * the file's absolute path (after converting path separators); otherwise there is no
207:             * general way to invert locate(...) so this heuristic may fail. However for the IFL
208:             * implementation used in a plain NB installation (i.e.
209:             * org.netbeans.core.modules.InstalledFileLocatorImpl), this condition will in fact hold.
210:             * @return the inverse of locate(...), or null if there is no such path
211:             * @see "#34069"
212:             */
213:            private static String findLogicalPath(File f) {
214:                InstalledFileLocator l = InstalledFileLocator.getDefault();
215:                String path = f.getName();
216:                File parent = f.getParentFile();
217:                while (parent != null) {
218:                    File probe = l.locate(path, null, false);
219:                    //System.err.println("Util.fLP: f=" + f + " parent=" + parent + " probe=" + probe + " f.equals(probe)=" + f.equals(probe));
220:                    if (f.equals(probe)) {
221:                        return path;
222:                    }
223:                    path = parent.getName() + '/' + path;
224:                    parent = parent.getParentFile();
225:                }
226:                return null;
227:            }
228:
229:            // XXX ought to be some way to get localized messages for these...
230:
231:            /** Check whether a simple dependency is met.
232:             * Only applicable to Java dependencies.
233:             */
234:            static boolean checkJavaDependency(Dependency dep)
235:                    throws IllegalArgumentException {
236:                // Note that "any" comparison is not possible for this type.
237:                if (dep.getType() == Dependency.TYPE_JAVA) {
238:                    if (dep.getName().equals(Dependency.JAVA_NAME)) {
239:                        if (dep.getComparison() == Dependency.COMPARE_SPEC) {
240:                            return new SpecificationVersion(dep.getVersion())
241:                                    .compareTo(Dependency.JAVA_SPEC) <= 0;
242:                        } else {
243:                            return dep.getVersion()
244:                                    .equals(Dependency.JAVA_IMPL);
245:                        }
246:                    } else {
247:                        if (dep.getComparison() == Dependency.COMPARE_SPEC) {
248:                            return new SpecificationVersion(dep.getVersion())
249:                                    .compareTo(Dependency.VM_SPEC) <= 0;
250:                        } else {
251:                            return dep.getVersion().equals(Dependency.VM_IMPL);
252:                        }
253:                    }
254:                } else {
255:                    throw new IllegalArgumentException();
256:                }
257:            }
258:
259:            /** Check whether a package dependency is met.
260:             * A classloader must be supplied to check in.
261:             */
262:            static boolean checkPackageDependency(Dependency dep, ClassLoader cl)
263:                    throws IllegalArgumentException {
264:                if (dep.getType() != Dependency.TYPE_PACKAGE) {
265:                    throw new IllegalArgumentException(
266:                            "Not a package dependency"); // NOI18N
267:                }
268:                if (!(cl instanceof  Util.PackageAccessibleClassLoader)
269:                        && cl != Util.class.getClassLoader()) {
270:                    throw new IllegalArgumentException(
271:                            "Not a package-accessible classloader: " + cl); // NOI18N
272:                }
273:                String name = dep.getName();
274:                String version = dep.getVersion();
275:                int comparison = dep.getComparison();
276:                String packageName, sampleName;
277:                int idx = name.indexOf('[');
278:                if (idx == -1) {
279:                    packageName = name;
280:                    sampleName = null;
281:                } else if (idx == 0) {
282:                    packageName = null;
283:                    sampleName = name.substring(1, name.length() - 1);
284:                } else {
285:                    packageName = name.substring(0, idx);
286:                    sampleName = name.substring(idx + 1, name.length() - 1);
287:                    if (sampleName.indexOf('.') == -1) {
288:                        // Unqualified class name; prefix it automatically.
289:                        sampleName = packageName + '.' + sampleName;
290:                    }
291:                }
292:                if (sampleName != null) {
293:                    try {
294:                        cl.loadClass(sampleName);
295:                    } catch (ClassNotFoundException cnfe) {
296:                        if (packageName == null) {
297:                            // This was all we were relying on, so it is an error.
298:                            err.log(Level.WARNING, null, cnfe);
299:                            err.fine("Probed class could not be found");
300:                            return false;
301:                        }
302:                        // Else let the regular package check take care of it;
303:                        // this was only run to enforce that the package defs were loaded.
304:                    } catch (RuntimeException e) {
305:                        // SecurityException, etc. Package exists but is corrupt.
306:                        err.log(Level.WARNING, null, e);
307:                        err.fine("Assuming package " + packageName
308:                                + " is corrupt");
309:                        return false;
310:                    } catch (LinkageError le) {
311:                        // NoClassDefFoundError, etc. Package exists but is corrupt.
312:                        err.log(Level.WARNING, null, le);
313:                        err.fine("Assuming package " + packageName
314:                                + " is corrupt");
315:                        return false;
316:                    }
317:                }
318:                if (packageName != null) {
319:                    Package pkg;
320:                    if (cl instanceof  Util.PackageAccessibleClassLoader) {
321:                        pkg = ((Util.PackageAccessibleClassLoader) cl)
322:                                .getPackageAccessibly(packageName);
323:                    } else {
324:                        pkg = Package.getPackage(packageName);
325:                    }
326:                    if (pkg == null) {
327:                        err.fine("No package with the name " + packageName
328:                                + " found");
329:                        return false;
330:                    }
331:                    if (comparison == Dependency.COMPARE_ANY) {
332:                        return true;
333:                    } else if (comparison == Dependency.COMPARE_SPEC) {
334:                        if (pkg.getSpecificationVersion() == null) {
335:                            err.fine("Package " + packageName
336:                                    + " did not give a specification version");
337:                            return false;
338:                        } else {
339:                            try {
340:                                SpecificationVersion versionSpec = new SpecificationVersion(
341:                                        version);
342:                                SpecificationVersion pkgSpec = new SpecificationVersion(
343:                                        pkg.getSpecificationVersion().trim());
344:                                if (versionSpec.compareTo(pkgSpec) <= 0) {
345:                                    return true;
346:                                } else {
347:                                    err.fine("Loaded package " + packageName
348:                                            + " was only of version " + pkgSpec
349:                                            + " but " + versionSpec
350:                                            + " was requested");
351:                                    return false;
352:                                }
353:                            } catch (NumberFormatException nfe) {
354:                                err.log(Level.WARNING, null, nfe);
355:                                err
356:                                        .fine("Will not honor a dependency on non-numeric package spec version");
357:                                return false;
358:                            }
359:                        }
360:                    } else {
361:                        // COMPARE_IMPL
362:                        if (pkg.getImplementationVersion() == null) {
363:                            err.fine("Package " + packageName
364:                                    + " had no implementation version");
365:                            return false;
366:                        } else if (!pkg.getImplementationVersion().trim()
367:                                .equals(version)) {
368:                            err.fine("Package " + packageName
369:                                    + " had the wrong impl version: "
370:                                    + pkg.getImplementationVersion());
371:                            return false;
372:                        } else {
373:                            return true;
374:                        }
375:                    }
376:                } else {
377:                    // Satisfied sample class.
378:                    return true;
379:                }
380:            }
381:
382:            /**
383:             * Interface to permit a couple of methods in ClassLoader to be made public. 
384:             * @since 2.1
385:             */
386:            public interface PackageAccessibleClassLoader {
387:                /** @see ClassLoader#getPackage */
388:                Package getPackageAccessibly(String name);
389:
390:                /** @see ClassLoader#getPackages */
391:                Package[] getPackagesAccessibly();
392:            }
393:
394:            /** 
395:             * Interface for a classloader to declare that it comes from a module. 
396:             * @since 2.1
397:             */
398:            public interface ModuleProvider {
399:                Module getModule();
400:            }
401:
402:            /**
403:             * Enumerate (direct) interdependencies among a set of modules.
404:             * If used in a topological sort, the result will be a reverse-order
405:             * list of modules (suitable for disabling; reverse for enabling).
406:             * @param modules some modules
407:             * @param modulesByName map from module cnbs to modules (may contain unrelated modules)
408:             * @param providersOf map from tokens to sets of modules providing them (may mention unrelated modules)
409:             * @return a map from modules to lists of modules they depend on
410:             * @see Utilities#topologicalSort
411:             * JST-PENDING needed from tests
412:             */
413:            public static Map<Module, List<Module>> moduleDependencies(
414:                    Collection<Module> modules,
415:                    Map<String, Module> modulesByName,
416:                    Map<String, Set<Module>> _providersOf) {
417:                Set<Module> modulesSet = (modules instanceof  Set) ? (Set<Module>) modules
418:                        : new HashSet<Module>(modules);
419:                Map<String, List<Module>> providersOf = new HashMap<String, List<Module>>(
420:                        _providersOf.size() * 2 + 1);
421:                for (Map.Entry<String, Set<Module>> entry : _providersOf
422:                        .entrySet()) {
423:                    Set<Module> providers = entry.getValue();
424:                    if (providers != null) {
425:                        List<Module> availableProviders = new LinkedList<Module>(
426:                                providers);
427:                        availableProviders.retainAll(modulesSet);
428:                        if (!availableProviders.isEmpty()) {
429:                            providersOf.put(entry.getKey(), availableProviders);
430:                        }
431:                    }
432:                }
433:                Map<Module, List<Module>> m = new HashMap<Module, List<Module>>();
434:                for (Module m1 : modules) {
435:                    List<Module> l = null;
436:                    for (Dependency dep : m1.getDependenciesArray()) {
437:                        if (dep.getType() == Dependency.TYPE_REQUIRES) {
438:                            List<Module> providers = providersOf.get(dep
439:                                    .getName());
440:
441:                            if (providers != null) {
442:                                if (l == null) {
443:                                    l = new LinkedList<Module>();
444:                                }
445:                                l.addAll(providers);
446:                            }
447:                        } else if (dep.getType() == Dependency.TYPE_MODULE) {
448:                            String cnb = (String) parseCodeName(dep.getName())[0];
449:                            Module m2 = modulesByName.get(cnb);
450:
451:                            if (m2 != null && modulesSet.contains(m2)) {
452:                                if (l == null) {
453:                                    l = new LinkedList<Module>();
454:                                }
455:                                l.add(m2);
456:                            }
457:                        }
458:                    }
459:                    if (l != null) {
460:                        m.put(m1, l);
461:                    }
462:                }
463:                return m;
464:            }
465:
466:            /**
467:             * Get dependencies forward or backwards starting from one module.
468:             * @see #moduleDependencies
469:             * @see ModuleManager#getModuleInterdependencies
470:             */
471:            static Set<Module> moduleInterdependencies(Module m,
472:                    boolean reverse, boolean transitive, Set<Module> modules,
473:                    Map<String, Module> modulesByName,
474:                    Map<String, Set<Module>> providersOf) {
475:                // XXX these algorithms could surely be made faster using standard techniques
476:                // for now the speed is not critical however
477:                if (reverse) {
478:                    Set<Module> s = new HashSet<Module>();
479:                    for (Module m2 : modules) {
480:                        if (m2 == m) {
481:                            continue;
482:                        }
483:                        if (moduleInterdependencies(m2, false, transitive,
484:                                modules, modulesByName, providersOf)
485:                                .contains(m)) {
486:                            s.add(m2);
487:                        }
488:                    }
489:                    return s;
490:                } else {
491:                    Set<Module> s = new HashSet<Module>();
492:                    for (Dependency dep : m.getDependenciesArray()) {
493:                        if (dep.getType() == Dependency.TYPE_REQUIRES
494:                                || dep.getType() == Dependency.TYPE_NEEDS) {
495:                            Set<Module> providers = providersOf.get(dep
496:                                    .getName());
497:                            if (providers != null) {
498:                                s.addAll(providers);
499:                            }
500:                        } else if (dep.getType() == Dependency.TYPE_MODULE) {
501:                            String cnb = (String) parseCodeName(dep.getName())[0];
502:                            Module m2 = modulesByName.get(cnb);
503:                            if (m2 != null) {
504:                                s.add(m2);
505:                            }
506:                        }
507:                    }
508:                    s.remove(m);
509:                    if (transitive) {
510:                        Set<Module> toAdd;
511:                        do {
512:                            toAdd = new HashSet<Module>();
513:                            for (Module m2 : s) {
514:                                Set<Module> s2 = moduleInterdependencies(m2,
515:                                        false, false, modules, modulesByName,
516:                                        providersOf);
517:                                s2.remove(m);
518:                                s2.removeAll(s);
519:                                toAdd.addAll(s2);
520:                            }
521:                            s.addAll(toAdd);
522:                        } while (!toAdd.isEmpty());
523:                    }
524:                    return s;
525:                }
526:            }
527:
528:            /** Find the most human-presentable message present in an exception.
529:             * At worst, the detail message, but preferably a localized message
530:             * if different, or the first localized annotation found.
531:             * If returning the detail message is not OK, returns null instead.
532:             * @since JST-PENDING: used from NbProblemDisplayer
533:             */
534:            public static String findLocalizedMessage(Throwable t,
535:                    boolean detailOK) {
536:                String locmsg = t.getLocalizedMessage();
537:                if (Utilities.compareObjects(locmsg, t.getMessage())) {
538:                    locmsg = Exceptions.findLocalizedMessage(t);
539:                    if (!detailOK) {
540:                        return null;
541:                    }
542:                }
543:                return locmsg;
544:            }
545:
546:            /** Get a filter for JAR files. */
547:            static FilenameFilter jarFilter() {
548:                return new JarFilter();
549:            }
550:
551:            private static final class JarFilter implements  FilenameFilter {
552:                JarFilter() {
553:                }
554:
555:                public boolean accept(File dir, String name) {
556:                    String n = name.toLowerCase(Locale.US);
557:                    return n.endsWith(".jar"); // NOI18N
558:                }
559:            }
560:
561:            /** Convert a class file name to a resource name suitable for Beans.instantiate.
562:             * @param name resource name of class file
563:             * @return class name without the <code>.class</code>/<code>.ser</code> extension, and using dots as package separator
564:             * @throws IllegalArgumentException if the name did not have a valid extension, or originally contained dots outside the extension, etc.
565:             * @since JST-PENDING: used from NbInstaller
566:             */
567:            public static String createPackageName(String name)
568:                    throws IllegalArgumentException {
569:                String clExt = ".class"; // NOI18N
570:                if (!name.endsWith(clExt)) {
571:                    // try different extension
572:                    clExt = ".ser"; // NOI18N
573:                }
574:                if (name.endsWith(clExt)) {
575:                    String bareName = name.substring(0, name.length()
576:                            - clExt.length());
577:                    if (bareName.length() == 0) { // ".class" // NOI18N
578:                        throw new IllegalArgumentException(
579:                                "Bad class file name: " + name); // NOI18N
580:                    }
581:                    if (bareName.charAt(0) == '/') { // "/foo/bar.class" // NOI18N
582:                        throw new IllegalArgumentException(
583:                                "Bad class file name: " + name); // NOI18N
584:                    }
585:                    if (bareName.charAt(bareName.length() - 1) == '/') { // "foo/bar/.class" // NOI18N
586:                        throw new IllegalArgumentException(
587:                                "Bad class file name: " + name); // NOI18N
588:                    }
589:                    if (bareName.indexOf('.') != -1) { // "foo.bar.class" // NOI18N
590:                        throw new IllegalArgumentException(
591:                                "Bad class file name: " + name); // NOI18N
592:                    }
593:                    return bareName.replace('/', '.'); // NOI18N
594:                } else { // "foo/bar" or "foo.bar" // NOI18N
595:                    throw new IllegalArgumentException("Bad class file name: "
596:                            + name); // NOI18N
597:                }
598:            }
599:
600:            /** A lookup implementation specialized for modules.
601:             * Its primary advantage over e.g. AbstractLookup is that
602:             * it is possible to add modules to the set at one time and
603:             * fire changes in the set of modules later on. ModuleManager
604:             * uses this to add modules immediately in create() and destroy(),
605:             * but only fire lookup events later and asynchronously, from the
606:             * read mutex.
607:             */
608:            static final class ModuleLookup extends Lookup {
609:                ModuleLookup() {
610:                }
611:
612:                private final Set<Module> modules = new HashSet<Module>(100);
613:                private final Set<ModuleResult> results = new WeakSet<ModuleResult>(
614:                        10);
615:
616:                /** Add a module to the set. */
617:                public void add(Module m) {
618:                    synchronized (modules) {
619:                        modules.add(m);
620:                    }
621:                }
622:
623:                /** Remove a module from the set. */
624:                public void remove(Module m) {
625:                    synchronized (modules) {
626:                        modules.remove(m);
627:                    }
628:                }
629:
630:                /** Fire changes to all result listeners. */
631:                public void changed() {
632:                    synchronized (results) {
633:                        Iterator it = results.iterator();
634:                        while (it.hasNext()) {
635:                            ((ModuleResult) it.next()).changed();
636:                        }
637:                    }
638:                }
639:
640:                public <T> T lookup(Class<T> clazz) {
641:                    if ((clazz == Module.class || clazz == ModuleInfo.class
642:                            || clazz == Object.class || clazz == null)
643:                            && !modules.isEmpty()) {
644:                        synchronized (modules) {
645:                            return clazz.cast(modules.iterator().next());
646:                        }
647:                    } else {
648:                        return null;
649:                    }
650:                }
651:
652:                @SuppressWarnings("unchecked")
653:                public <T> Lookup.Result<T> lookup(Lookup.Template<T> t) {
654:                    Class<T> clazz = t.getType();
655:                    if (clazz == Module.class || clazz == ModuleInfo.class
656:                            || clazz == Object.class || clazz == null) {
657:                        return (Lookup.Result<T>) (Object) new ModuleResult(
658:                                (Lookup.Template<Module>) t);
659:                    } else {
660:                        return Lookup.EMPTY.lookup(t);
661:                    }
662:                }
663:
664:                public @Override
665:                String toString() {
666:                    synchronized (modules) {
667:                        return "ModuleLookup" + modules; // NOI18N
668:                    }
669:                }
670:
671:                private final class ModuleResult extends Lookup.Result<Module> {
672:                    private final Lookup.Template<? super  Module> t;
673:                    private final Set<LookupListener> listeners = new HashSet<LookupListener>(
674:                            10);
675:
676:                    public ModuleResult(Lookup.Template<? super  Module> t) {
677:                        this .t = t;
678:                        synchronized (results) {
679:                            results.add(this );
680:                        }
681:                    }
682:
683:                    public void addLookupListener(LookupListener l) {
684:                        synchronized (listeners) {
685:                            listeners.add(l);
686:                        }
687:                    }
688:
689:                    public void removeLookupListener(LookupListener l) {
690:                        synchronized (listeners) {
691:                            listeners.remove(l);
692:                        }
693:                    }
694:
695:                    public void changed() {
696:                        LookupListener[] _listeners;
697:                        synchronized (listeners) {
698:                            if (listeners.isEmpty()) {
699:                                return;
700:                            }
701:                            _listeners = listeners
702:                                    .toArray(new LookupListener[listeners
703:                                            .size()]);
704:                        }
705:                        LookupEvent ev = new LookupEvent(this );
706:                        for (int i = 0; i < _listeners.length; i++) {
707:                            _listeners[i].resultChanged(ev);
708:                        }
709:                    }
710:
711:                    public Collection<Module> allInstances() {
712:                        synchronized (modules) {
713:                            String id = t.getId();
714:                            Object inst = t.getInstance();
715:                            if (id != null) {
716:                                Iterator<Module> it = modules.iterator();
717:                                while (it.hasNext()) {
718:                                    Module m = it.next();
719:                                    if (id.equals(ModuleItem.PREFIX
720:                                            + m.getCodeNameBase())) {
721:                                        if (inst == null || inst == m) {
722:                                            return Collections
723:                                                    .<Module> singleton(m);
724:                                        }
725:                                    }
726:                                }
727:                                return Collections.<Module> emptySet();
728:                            } else if (inst != null) {
729:                                return modules.contains(inst) ? Collections
730:                                        .<Module> singleton(Module.class
731:                                                .cast(inst)) : Collections
732:                                        .<Module> emptySet();
733:                            } else {
734:                                // Regular lookup based on type.
735:                                return new HashSet<Module>(modules);
736:                            }
737:                        }
738:                    }
739:
740:                    public @Override
741:                    Set<Class<? extends Module>> allClasses() {
742:                        return Collections
743:                                .<Class<? extends Module>> singleton(Module.class);
744:                    }
745:
746:                    public @Override
747:                    Collection<? extends Lookup.Item<Module>> allItems() {
748:                        Collection<Module> insts = allInstances();
749:                        ArrayList<ModuleItem> list = new ArrayList<ModuleItem>(
750:                                Math.max(1, insts.size()));
751:                        for (Module m : insts) {
752:                            list.add(new ModuleItem(m));
753:                        }
754:                        return list;
755:                    }
756:
757:                    public @Override
758:                    String toString() {
759:                        return "ModuleResult:" + t; // NOI18N
760:                    }
761:                }
762:
763:                private static final class ModuleItem extends
764:                        Lookup.Item<Module> {
765:                    public static final String PREFIX = "Module["; // NOI18N
766:                    private final Module item;
767:
768:                    public ModuleItem(Module item) {
769:                        this .item = item;
770:                    }
771:
772:                    public Module getInstance() {
773:                        return item;
774:                    }
775:
776:                    public Class<? extends Module> getType() {
777:                        return Module.class;
778:                    }
779:
780:                    public String getId() {
781:                        return PREFIX + item.getCodeNameBase();
782:                    }
783:
784:                    public String getDisplayName() {
785:                        return item.getDisplayName();
786:                    }
787:                }
788:            }
789:
790:            // OK to not release this memory; module deletion is rare: holds 45kB for 173 modules (June 2005)
791:            private static final Map<String, Object[]> codeNameParseCache = new HashMap<String, Object[]>(
792:                    200); // Map<String,[String,int]>
793:
794:            /** Find the code name base and major release version from a code name.
795:             * Caches these parses. Thread-safe (i.e. OK from read mutex).
796:             * @return an array consisting of the code name base (String) followed by the release version (Integer or null)
797:             *         followed by another end-range version (Integer or null)
798:             * @throws NumberFormatException if the release version is mangled
799:             * @since JST-PENDING: used from NbInstaller
800:             */
801:            public static Object[] parseCodeName(String cn)
802:                    throws NumberFormatException {
803:                synchronized (codeNameParseCache) {
804:                    Object[] r = codeNameParseCache.get(cn);
805:                    if (r == null) {
806:                        r = new Object[3];
807:                        int i = cn.lastIndexOf('/');
808:                        if (i == -1) {
809:                            r[0] = cn;
810:                        } else {
811:                            r[0] = cn.substring(0, i).intern();
812:                            String end = cn.substring(i + 1);
813:                            int j = end.indexOf('-');
814:                            if (j == -1) {
815:                                r[1] = new Integer(end);
816:                            } else {
817:                                r[1] = new Integer(end.substring(0, j));
818:                                r[2] = new Integer(end.substring(j + 1));
819:                            }
820:                        }
821:                        codeNameParseCache.put(cn.intern(), r);
822:                    }
823:                    return r;
824:                }
825:            }
826:
827:            /** Get API module dependency, if any, for a module.
828:             * @param dependencies module dependencies
829:             * @param cnb code name base of API module
830:             * @return a fake spec version (0.x.y if x.y w/ no major release, else r.x.y); or null if no dep
831:             * @since JST-PENDING: used from NbInstaller
832:             */
833:            public static SpecificationVersion getModuleDep(
834:                    Set<Dependency> dependencies, String cnb) {
835:                for (Dependency d : dependencies) {
836:                    if (d.getType() == Dependency.TYPE_MODULE
837:                            && d.getComparison() == Dependency.COMPARE_SPEC) {
838:                        try {
839:                            Object[] p = parseCodeName(d.getName());
840:                            if (!p[0].equals(cnb)) {
841:                                continue;
842:                            }
843:                            int rel = ((Integer) p[1]).intValue(); // ignore any end range, consider only start
844:                            if (rel == -1)
845:                                rel = 0; // XXX will this lead to incorrect semantics?
846:                            return new SpecificationVersion("" + rel + "."
847:                                    + d.getVersion()); // NOI18N
848:                        } catch (NumberFormatException nfe) {
849:                            Util.err.log(Level.WARNING, null, nfe);
850:                            return null;
851:                        }
852:                    }
853:                }
854:                return null;
855:            }
856:
857:            /**
858:             * Transitively fill out a set of modules with all of its module dependencies.
859:             * Dependencies on missing modules are silently ignored, but dependencies
860:             * on present but uninstallable (problematic) modules are included.
861:             * @param mgr the manager
862:             * @param modules a mutable set of modules
863:             * @since JST-PENDING: used from NbInstaller
864:             */
865:            public static void transitiveClosureModuleDependencies(
866:                    ModuleManager mgr, Set<Module> modules) {
867:                Set<Module> nue = null; // Set of newly appended modules
868:                while (nue == null || !nue.isEmpty()) {
869:                    nue = new HashSet<Module>();
870:                    for (Module m : modules) {
871:                        for (Dependency dep : m.getDependenciesArray()) {
872:                            if (dep.getType() != Dependency.TYPE_MODULE) {
873:                                continue;
874:                            }
875:                            Module other = mgr.get((String) parseCodeName(dep
876:                                    .getName())[0]);
877:                            if (other != null && !modules.contains(other)) {
878:                                nue.add(other);
879:                            }
880:                        }
881:                    }
882:                    modules.addAll(nue);
883:                }
884:            }
885:
886:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.