Source Code Cross Referenced for LayerUtils.java in  » IDE-Netbeans » api » org » netbeans » modules » apisupport » project » layers » 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 » api » org.netbeans.modules.apisupport.project.layers 
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.modules.apisupport.project.layers;
043:
044:        import java.beans.PropertyChangeEvent;
045:        import java.beans.PropertyChangeListener;
046:        import java.beans.PropertyChangeSupport;
047:        import java.beans.PropertyVetoException;
048:        import java.io.File;
049:        import java.io.IOException;
050:        import java.io.OutputStream;
051:        import java.net.URL;
052:        import java.util.ArrayList;
053:        import java.util.Arrays;
054:        import java.util.Collections;
055:        import java.util.Enumeration;
056:        import java.util.HashSet;
057:        import java.util.LinkedList;
058:        import java.util.List;
059:        import java.util.Locale;
060:        import java.util.Map;
061:        import java.util.Set;
062:        import java.util.WeakHashMap;
063:        import java.util.jar.Manifest;
064:        import java.util.regex.Matcher;
065:        import java.util.regex.Pattern;
066:        import org.netbeans.api.java.classpath.ClassPath;
067:        import org.netbeans.api.project.Project;
068:        import org.netbeans.api.project.ProjectManager;
069:        import org.netbeans.modules.apisupport.project.EditableManifest;
070:        import org.netbeans.modules.apisupport.project.ManifestManager;
071:        import org.netbeans.modules.apisupport.project.NbModuleProject;
072:        import org.netbeans.modules.apisupport.project.NbModuleProjectGenerator;
073:        import org.netbeans.modules.apisupport.project.Util;
074:        import org.netbeans.modules.apisupport.project.spi.NbModuleProvider;
075:        import org.netbeans.modules.apisupport.project.suite.SuiteProject;
076:        import org.netbeans.modules.apisupport.project.ui.customizer.SuiteProperties;
077:        import org.netbeans.modules.apisupport.project.ui.customizer.SuiteUtils;
078:        import org.netbeans.modules.apisupport.project.universe.ModuleEntry;
079:        import org.netbeans.modules.apisupport.project.universe.ModuleList;
080:        import org.netbeans.modules.apisupport.project.universe.NbPlatform;
081:        import org.netbeans.modules.xml.tax.cookies.TreeEditorCookie;
082:        import org.netbeans.modules.xml.tax.parser.XMLParsingSupport;
083:        import org.netbeans.spi.java.classpath.support.ClassPathSupport;
084:        import org.netbeans.spi.project.support.ant.PropertyEvaluator;
085:        import org.netbeans.tax.TreeDocumentRoot;
086:        import org.netbeans.tax.TreeException;
087:        import org.netbeans.tax.TreeObject;
088:        import org.netbeans.tax.io.TreeStreamResult;
089:        import org.openide.ErrorManager;
090:        import org.openide.filesystems.FileAttributeEvent;
091:        import org.openide.filesystems.FileChangeListener;
092:        import org.openide.filesystems.FileEvent;
093:        import org.openide.filesystems.FileLock;
094:        import org.openide.filesystems.FileObject;
095:        import org.openide.filesystems.FileRenameEvent;
096:        import org.openide.filesystems.FileStateInvalidException;
097:        import org.openide.filesystems.FileSystem;
098:        import org.openide.filesystems.FileUtil;
099:        import org.openide.filesystems.MultiFileSystem;
100:        import org.openide.filesystems.XMLFileSystem;
101:        import org.openide.util.Task;
102:        import org.xml.sax.InputSource;
103:        import org.xml.sax.SAXException;
104:
105:        /**
106:         * Misc support for dealing with layers.
107:         * @author Jesse Glick
108:         */
109:        public class LayerUtils {
110:
111:            private LayerUtils() {
112:            }
113:
114:            /**
115:             * Translates nbres: into nbrescurr: for internal use.
116:             * Returns an array of one or more URLs.
117:             * May just be original URL, but will try to produce URLs corresponding to real files.
118:             * If there is a suffix, may produce several, most specific first.
119:             */
120:            static URL[] currentify(URL u, String suffix, ClassPath cp) {
121:                if (cp == null) {
122:                    return new URL[] { u };
123:                }
124:                try {
125:                    if (u.getProtocol().equals("nbres")) { // NOI18N
126:                        String path = u.getFile();
127:                        if (path.startsWith("/"))
128:                            path = path.substring(1); // NOI18N
129:                        FileObject fo = cp.findResource(path);
130:                        if (fo != null) {
131:                            return new URL[] { fo.getURL() };
132:                        }
133:                    } else if (u.getProtocol().equals("nbresloc")) { // NOI18N
134:                        List<URL> urls = new ArrayList<URL>();
135:                        String path = u.getFile();
136:                        if (path.startsWith("/"))
137:                            path = path.substring(1); // NOI18N
138:                        int idx = path.lastIndexOf('/');
139:                        String folder;
140:                        String nameext;
141:                        if (idx == -1) {
142:                            folder = ""; // NOI18N
143:                            nameext = path;
144:                        } else {
145:                            folder = path.substring(0, idx + 1);
146:                            nameext = path.substring(idx + 1);
147:                        }
148:                        idx = nameext.lastIndexOf('.');
149:                        String name;
150:                        String ext;
151:                        if (idx == -1) {
152:                            name = nameext;
153:                            ext = ""; // NOI18N
154:                        } else {
155:                            name = nameext.substring(0, idx);
156:                            ext = nameext.substring(idx);
157:                        }
158:                        List<String> suffixes = new ArrayList<String>(
159:                                computeSubVariants(suffix));
160:                        suffixes.add(suffix);
161:                        Collections.reverse(suffixes);
162:                        for (String trysuffix : suffixes) {
163:                            String trypath = folder + name + trysuffix + ext;
164:                            FileObject fo = cp.findResource(trypath);
165:                            if (fo != null) {
166:                                urls.add(fo.getURL());
167:                            }
168:                        }
169:                        if (!urls.isEmpty()) {
170:                            return urls.toArray(new URL[urls.size()]);
171:                        }
172:                    }
173:                } catch (FileStateInvalidException fsie) {
174:                    Util.err.notify(ErrorManager.WARNING, fsie);
175:                }
176:                return new URL[] { u };
177:            }
178:
179:            // E.g. for name 'foo_f4j_ce_ja', should produce list:
180:            // 'foo', 'foo_ja', 'foo_f4j', 'foo_f4j_ja', 'foo_f4j_ce'
181:            // Will actually produce:
182:            // 'foo', 'foo_ja', 'foo_ce', 'foo_ce_ja', 'foo_f4j', 'foo_f4j_ja', 'foo_f4j_ce'
183:            // since impossible to distinguish locale from branding reliably.
184:            private static List<String> computeSubVariants(String name) {
185:                int idx = name.indexOf('_');
186:                if (idx == -1) {
187:                    return Collections.emptyList();
188:                } else {
189:                    String base = name.substring(0, idx);
190:                    String suffix = name.substring(idx);
191:                    List<String> l = computeSubVariants(base, suffix);
192:                    return l.subList(0, l.size() - 1);
193:                }
194:            }
195:
196:            private static List<String> computeSubVariants(String base,
197:                    String suffix) {
198:                int idx = suffix.indexOf('_', 1);
199:                if (idx == -1) {
200:                    List<String> l = new LinkedList<String>();
201:                    l.add(base);
202:                    l.add(base + suffix);
203:                    return l;
204:                } else {
205:                    String remainder = suffix.substring(idx);
206:                    List<String> l1 = computeSubVariants(base, remainder);
207:                    List<String> l2 = computeSubVariants(base
208:                            + suffix.substring(0, idx), remainder);
209:                    List<String> l = new LinkedList<String>(l1);
210:                    l.addAll(l2);
211:                    return l;
212:                }
213:            }
214:
215:            // XXX needs to hold a strong ref only when modified, probably?
216:            private static final Map<Project, LayerHandle> layerHandleCache = new WeakHashMap<Project, LayerHandle>();
217:
218:            /**
219:             * Gets a handle for one project's XML layer.
220:             */
221:            public static LayerHandle layerForProject(Project project) {
222:                LayerHandle handle = layerHandleCache.get(project);
223:                if (handle == null) {
224:                    handle = new LayerHandle(project);
225:                    layerHandleCache.put(project, handle);
226:                }
227:                return handle;
228:            }
229:
230:            private static final Set<String> XML_LIKE_TYPES = new HashSet<String>();
231:            static {
232:                XML_LIKE_TYPES.add(".settings"); // NOI18N
233:                XML_LIKE_TYPES.add(".wstcref"); // NOI18N
234:                XML_LIKE_TYPES.add(".wsmode"); // NOI18N
235:                XML_LIKE_TYPES.add(".wsgrp"); // NOI18N
236:                XML_LIKE_TYPES.add(".wsmgr"); // NOI18N
237:            }
238:
239:            /**
240:             * Find the name of the external file that will be generated for a given
241:             * layer path if it is created with contents.
242:             * @param parent parent folder, or null
243:             * @param layerPath full path in layer
244:             * @return a simple file name
245:             */
246:            public static String findGeneratedName(FileObject parent,
247:                    String layerPath) {
248:                Matcher m = Pattern.compile("(.+/)?([^/.]+)(\\.[^/]+)?")
249:                        .matcher(layerPath); // NOI18N
250:                if (!m.matches()) {
251:                    throw new IllegalArgumentException(layerPath);
252:                }
253:                String base = m.group(2);
254:                String ext = m.group(3);
255:                if (ext == null) {
256:                    ext = "";
257:                } else if (ext.equals(".java")) { // NOI18N
258:                    ext = "_java"; // NOI18N
259:                } else if (XML_LIKE_TYPES.contains(ext)) {
260:                    String upper = ext.substring(1, 2).toUpperCase(
261:                            Locale.ENGLISH);
262:                    base = base + upper + ext.substring(2);
263:                    ext = ".xml"; // NOI18N
264:                }
265:                String name = base + ext;
266:                if (parent == null || parent.getFileObject(name) == null) {
267:                    return name;
268:                } else {
269:                    for (int i = 1; true; i++) {
270:                        name = base + '_' + i + ext;
271:                        if (parent.getFileObject(name) == null) {
272:                            return name;
273:                        }
274:                    }
275:                }
276:            }
277:
278:            /**
279:             * Representation of in-memory TAX tree which can be saved upon request.
280:             */
281:            interface SavableTreeEditorCookie extends TreeEditorCookie {
282:
283:                /** property change fired when dirty flag changes */
284:                String PROP_DIRTY = "dirty"; // NOI18N
285:
286:                /** true if there are in-memory mods */
287:                boolean isDirty();
288:
289:                /** try to save any in-memory mods to disk */
290:                void save() throws IOException;
291:
292:            }
293:
294:            private static final class CookieImpl implements 
295:                    SavableTreeEditorCookie, FileChangeListener {
296:                private TreeDocumentRoot root;
297:                private boolean dirty;
298:                private Exception problem;
299:                private final FileObject f;
300:                private final PropertyChangeSupport pcs = new PropertyChangeSupport(
301:                        this );
302:                private boolean saving;
303:
304:                public CookieImpl(FileObject f) {
305:                    //System.err.println("new CookieImpl for " + f);
306:                    this .f = f;
307:                    f.addFileChangeListener(FileUtil.weakFileChangeListener(
308:                            this , f));
309:                }
310:
311:                public TreeDocumentRoot getDocumentRoot() {
312:                    return root;
313:                }
314:
315:                public int getStatus() {
316:                    if (problem != null) {
317:                        return TreeEditorCookie.STATUS_ERROR;
318:                    } else if (root != null) {
319:                        return TreeEditorCookie.STATUS_OK;
320:                    } else {
321:                        return TreeEditorCookie.STATUS_NOT;
322:                    }
323:                }
324:
325:                public TreeDocumentRoot openDocumentRoot() throws IOException,
326:                        TreeException {
327:                    if (root == null && f.isValid()) {
328:                        try {
329:                            //System.err.println("openDocumentRoot: really opening");
330:                            boolean oldDirty = dirty;
331:                            int oldStatus = getStatus();
332:                            root = new XMLParsingSupport()
333:                                    .parse(new InputSource(f.getURL()
334:                                            .toExternalForm()));
335:                            problem = null;
336:                            dirty = false;
337:                            pcs.firePropertyChange(PROP_DIRTY, oldDirty, false);
338:                            pcs.firePropertyChange(PROP_STATUS, oldStatus,
339:                                    TreeEditorCookie.STATUS_OK);
340:                            //pcs.firePropertyChange(PROP_DOCUMENT_ROOT, null, root);
341:                        } catch (IOException e) {
342:                            problem = e;
343:                            throw e;
344:                        } catch (TreeException e) {
345:                            problem = e;
346:                            throw e;
347:                        }
348:                        ((TreeObject) root)
349:                                .addPropertyChangeListener(new PropertyChangeListener() {
350:                                    public void propertyChange(
351:                                            PropertyChangeEvent evt) {
352:                                        //System.err.println("tree modified");
353:                                        modified();
354:                                    }
355:                                });
356:                    }
357:                    return root;
358:                }
359:
360:                public Task prepareDocumentRoot() {
361:                    throw new UnsupportedOperationException();
362:                }
363:
364:                public void addPropertyChangeListener(
365:                        PropertyChangeListener listener) {
366:                    pcs.addPropertyChangeListener(listener);
367:                }
368:
369:                public void removePropertyChangeListener(
370:                        PropertyChangeListener listener) {
371:                    pcs.removePropertyChangeListener(listener);
372:                }
373:
374:                private void modified() {
375:                    //System.err.println("modified(): dirty=" + dirty + " in " + Thread.currentThread().getName() + " for " + this);
376:                    if (!dirty) {
377:                        dirty = true;
378:                        pcs.firePropertyChange(PROP_DIRTY, false, true);
379:                    }
380:                }
381:
382:                public boolean isDirty() {
383:                    return dirty;
384:                }
385:
386:                public synchronized void save() throws IOException {
387:                    //System.err.println("save(): dirty=" + dirty + " in " + Thread.currentThread().getName() + " for " + this);
388:                    if (root == null || !dirty) {
389:                        return;
390:                    }
391:                    assert !saving;
392:                    saving = true;
393:                    //System.err.println("saving");
394:                    try {
395:                        FileLock lock = f.lock();
396:                        try {
397:                            OutputStream os = f.getOutputStream(lock);
398:                            try {
399:                                new TreeStreamResult(os).getWriter(root)
400:                                        .writeDocument();
401:                            } catch (TreeException e) {
402:                                throw (IOException) new IOException(e
403:                                        .toString()).initCause(e);
404:                            } finally {
405:                                os.close();
406:                            }
407:                        } finally {
408:                            lock.releaseLock();
409:                        }
410:                    } finally {
411:                        saving = false;
412:                        //System.err.println("!saving in " + Thread.currentThread().getName() + " for " + this);
413:                    }
414:                    dirty = false;
415:                    pcs.firePropertyChange(PROP_DIRTY, true, false);
416:                }
417:
418:                public void fileChanged(FileEvent fe) {
419:                    changed();
420:                }
421:
422:                public void fileDeleted(FileEvent fe) {
423:                    changed();
424:                }
425:
426:                public void fileRenamed(FileRenameEvent fe) {
427:                    changed();
428:                }
429:
430:                public void fileAttributeChanged(FileAttributeEvent fe) {
431:                    // ignore
432:                }
433:
434:                public void fileFolderCreated(FileEvent fe) {
435:                    assert false;
436:                }
437:
438:                public void fileDataCreated(FileEvent fe) {
439:                    assert false;
440:                }
441:
442:                private void changed() {
443:                    //System.err.println("changed on disk; saving=" + saving + " in " + Thread.currentThread().getName() + " for " + this);
444:                    synchronized (this ) {
445:                        if (saving) {
446:                            return;
447:                        }
448:                        problem = null;
449:                        dirty = false;
450:                        root = null;
451:                    }
452:                    pcs.firePropertyChange(PROP_DOCUMENT_ROOT, null, null);
453:                }
454:            }
455:
456:            static SavableTreeEditorCookie cookieForFile(FileObject f) {
457:                return new CookieImpl(f);
458:            }
459:
460:            /**
461:             * Manages one project's XML layer.
462:             */
463:            public static final class LayerHandle {
464:
465:                private final Project project;
466:                private FileSystem fs;
467:                private SavableTreeEditorCookie cookie;
468:                private boolean autosave;
469:
470:                LayerHandle(Project project) {
471:                    //System.err.println("new LayerHandle for " + project);
472:                    this .project = project;
473:                }
474:
475:                /**
476:                 * Get the layer as a structured filesystem.
477:                 * You can make whatever Filesystems API calls you like to it.
478:                 * Just call {@link #save} when you are done so the modified XML document is saved
479:                 * (or the user can save it explicitly if you don't).
480:                 * @param create if true, and there is no layer yet, create it now; if false, just return null
481:                 */
482:                public synchronized FileSystem layer(boolean create) {
483:                    if (fs == null) {
484:                        FileObject xml = getLayerFile();
485:                        if (xml == null) {
486:                            if (!create) {
487:                                return null;
488:                            }
489:                            try {
490:                                NbModuleProvider module = project.getLookup()
491:                                        .lookup(NbModuleProvider.class);
492:                                FileObject manifest = module.getManifestFile();
493:                                if (manifest != null) { // #121056
494:                                    // Check to see if the manifest entry is already specified.
495:                                    String layerSrcPath = ManifestManager
496:                                            .getInstance(
497:                                                    Util.getManifest(manifest),
498:                                                    false).getLayer();
499:                                    if (layerSrcPath == null) {
500:                                        layerSrcPath = newLayerPath();
501:                                        EditableManifest m = Util
502:                                                .loadManifest(manifest);
503:                                        m
504:                                                .setAttribute(
505:                                                        ManifestManager.OPENIDE_MODULE_LAYER,
506:                                                        layerSrcPath, null);
507:                                        Util.storeManifest(manifest, m);
508:                                    }
509:                                }
510:                                xml = NbModuleProjectGenerator.createLayer(
511:                                        project.getProjectDirectory(),
512:                                        module.getResourceDirectoryPath(false)
513:                                                + '/' + newLayerPath());
514:                            } catch (IOException e) {
515:                                Util.err.notify(ErrorManager.INFORMATIONAL, e);
516:                                return fs = FileUtil.createMemoryFileSystem();
517:                            }
518:                        }
519:                        try {
520:                            fs = new WritableXMLFileSystem(xml.getURL(),
521:                                    cookie = cookieForFile(xml), /*XXX*/null);
522:                        } catch (FileStateInvalidException e) {
523:                            throw new AssertionError(e);
524:                        }
525:                        cookie
526:                                .addPropertyChangeListener(new PropertyChangeListener() {
527:                                    public void propertyChange(
528:                                            PropertyChangeEvent evt) {
529:                                        //System.err.println("changed in mem");
530:                                        if (autosave
531:                                                && SavableTreeEditorCookie.PROP_DIRTY
532:                                                        .equals(evt
533:                                                                .getPropertyName())) {
534:                                            //System.err.println("  will save...");
535:                                            try {
536:                                                save();
537:                                            } catch (IOException e) {
538:                                                Util.err
539:                                                        .notify(
540:                                                                ErrorManager.INFORMATIONAL,
541:                                                                e);
542:                                            }
543:                                        }
544:                                    }
545:                                });
546:                    }
547:                    return fs;
548:                }
549:
550:                /**
551:                 * Save the layer, if it was in fact modified.
552:                 * Note that nonempty layer entries you created will already be on disk.
553:                 */
554:                public void save() throws IOException {
555:                    if (cookie == null) {
556:                        throw new IOException("Cannot save a nonexistent layer"); // NOI18N
557:                    }
558:                    cookie.save();
559:                }
560:
561:                /**
562:                 * Find the XML layer file for this project, if it exists.
563:                 * @return the layer, or null
564:                 */
565:                public FileObject getLayerFile() {
566:                    NbModuleProvider module = project.getLookup().lookup(
567:                            NbModuleProvider.class);
568:                    if (module == null) { // #126939: other project type
569:                        return null;
570:                    }
571:                    Manifest mf = Util.getManifest(module.getManifestFile());
572:                    if (mf == null) {
573:                        return null;
574:                    }
575:                    String path = ManifestManager.getInstance(mf, false)
576:                            .getLayer();
577:                    if (path == null) {
578:                        return null;
579:                    }
580:                    return Util.getResourceDirectory(project).getFileObject(
581:                            path);
582:                }
583:
584:                /**
585:                 * Set whether to automatically save changes to disk.
586:                 * @param true to save changes immediately, false to save only upon request
587:                 */
588:                public void setAutosave(boolean autosave) {
589:                    this .autosave = autosave;
590:                    if (autosave && cookie != null) {
591:                        try {
592:                            cookie.save();
593:                        } catch (IOException e) {
594:                            Util.err.notify(ErrorManager.INFORMATIONAL, e);
595:                        }
596:                    }
597:                }
598:
599:                /**
600:                 * Check whether this handle is currently in autosave mode.
601:                 */
602:                public boolean isAutosave() {
603:                    return autosave;
604:                }
605:
606:                /**
607:                 * Resource path in which to make a new XML layer.
608:                 */
609:                private String newLayerPath() {
610:                    NbModuleProvider module = project.getLookup().lookup(
611:                            NbModuleProvider.class);
612:                    FileObject manifest = module.getManifestFile();
613:                    if (manifest != null) {
614:                        String bundlePath = ManifestManager.getInstance(
615:                                Util.getManifest(manifest), false)
616:                                .getLocalizingBundle();
617:                        if (bundlePath != null) {
618:                            return bundlePath.replaceFirst("/[^/]+$",
619:                                    "/layer.xml"); // NOI18N
620:                        }
621:                    }
622:                    return module.getCodeNameBase().replace('.', '/')
623:                            + "/layer.xml"; // NOI18N
624:                }
625:
626:                public @Override
627:                String toString() {
628:                    FileObject layer = getLayerFile();
629:                    if (layer != null) {
630:                        return FileUtil.getFileDisplayName(layer);
631:                    } else {
632:                        return FileUtil.getFileDisplayName(project
633:                                .getProjectDirectory());
634:                    }
635:                }
636:
637:            }
638:
639:            /**
640:             * Get a filesystem that will look like what this project would "see".
641:             * <p>There are four possibilities:</p>
642:             * <ol>
643:             * <li><p>For a standalone module project, the filesystem will include all the XML
644:             * layers from all modules in the selected platform, plus this module's XML layer
645:             * as the writable layer (use {@link LayerHandle#save} to save changes as needed).</p></li>
646:             * <li><p>For a module suite project, the filesystem will include all the XML layers
647:             * from all modules in the selected platform which are not excluded in the current
648:             * suite configuration, plus the XML layers for modules in the suite (currently all
649:             * read-only, i.e. the filesystem is read-only).</p></li>
650:             * <li><p>For a suite component module project, the filesystem will include all XML
651:             * layers from non-excluded platform modules, plus the XML layers for modules in the
652:             * suite, with this module's layer being writable.</p></li>
653:             * <li><p>For a netbeans.org module, the filesystem will include all XML layers
654:             * from all netbeans.org modules that are not in the <code>extra</code> cluster,
655:             * plus the layer from this module (if it is in the <code>extra</code> cluster,
656:             * with this module's layer always writable.</p></li>
657:             * </ol>
658:             * <p>Does not currently attempt to cache the result,
659:             * though that could be attempted later as needed.</p>
660:             * <p>Will try to produce pleasant-looking display names and/or icons for files.</p>
661:             * <p>Note that parsing XML layers is not terribly fast so it would be wise to show
662:             * a "please wait" label or some other simple progress indication while this
663:             * is being called, if blocking the UI.</p>
664:             * @param project a project of one of the three types enumerated above
665:             * @return the effective system filesystem seen by that project
666:             * @throws IOException if there were problems loading layers, etc.
667:             * @see "#62257"
668:             */
669:            public static FileSystem getEffectiveSystemFilesystem(Project p)
670:                    throws IOException {
671:
672:                NbModuleProvider.NbModuleType type = Util.getModuleType(p);
673:                FileSystem projectLayer = layerForProject(p).layer(false);
674:                if (type == NbModuleProvider.STANDALONE) {
675:                    Set<File> jars = getPlatformJarsForStandaloneProject(p);
676:                    FileSystem[] platformLayers = getPlatformLayers(jars);
677:                    ClassPath cp = createLayerClasspath(Collections
678:                            .singleton(p), jars);
679:                    return mergeFilesystems(projectLayer, platformLayers, cp);
680:                } else if (type == NbModuleProvider.SUITE_COMPONENT) {
681:                    SuiteProject suite = SuiteUtils.findSuite(p);
682:                    if (suite == null) {
683:                        throw new IOException("Could not load suite for " + p); // NOI18N
684:                    }
685:                    List<FileSystem> readOnlyLayers = new ArrayList<FileSystem>();
686:                    Set<NbModuleProject> modules = SuiteUtils
687:                            .getSubProjects(suite);
688:                    for (NbModuleProject sister : modules) {
689:                        if (sister == p) {
690:                            continue;
691:                        }
692:                        LayerHandle handle = layerForProject(sister);
693:                        FileSystem roLayer = handle.layer(false);
694:                        if (roLayer != null) {
695:                            readOnlyLayers.add(roLayer);
696:                        }
697:                    }
698:                    Set<File> jars = getPlatformJarsForSuiteComponentProject(p,
699:                            suite);
700:                    readOnlyLayers.addAll(Arrays
701:                            .asList(getPlatformLayers(jars)));
702:                    ClassPath cp = createLayerClasspath(modules, jars);
703:                    return mergeFilesystems(projectLayer, readOnlyLayers
704:                            .toArray(new FileSystem[readOnlyLayers.size()]), cp);
705:                } else if (type == NbModuleProvider.NETBEANS_ORG) {
706:                    //it's safe to cast to NbModuleProject here.
707:                    NbModuleProject nbprj = p.getLookup().lookup(
708:                            NbModuleProject.class);
709:                    Set<NbModuleProject> projects = getProjectsForNetBeansOrgProject(nbprj);
710:                    List<URL> otherLayerURLs = new ArrayList<URL>();
711:
712:                    for (NbModuleProject p2 : projects) {
713:                        if (p2.getManifest() == null) {
714:                            //profiler for example.
715:                            continue;
716:                        }
717:                        ManifestManager mm = ManifestManager.getInstance(p2
718:                                .getManifest(), false);
719:                        String layer = mm.getLayer();
720:                        if (layer == null) {
721:                            continue;
722:                        }
723:                        FileObject src = p2.getSourceDirectory();
724:                        if (src == null) {
725:                            continue;
726:                        }
727:                        FileObject layerXml = src.getFileObject(layer);
728:                        if (layerXml == null) {
729:                            continue;
730:                        }
731:                        otherLayerURLs.add(layerXml.getURL());
732:                    }
733:                    XMLFileSystem xfs = new XMLFileSystem();
734:                    try {
735:                        xfs.setXmlUrls(otherLayerURLs
736:                                .toArray(new URL[otherLayerURLs.size()]));
737:                    } catch (PropertyVetoException ex) {
738:                        assert false : ex;
739:                    }
740:                    ClassPath cp = createLayerClasspath(projects, Collections
741:                            .<File> emptySet());
742:                    return mergeFilesystems(projectLayer,
743:                            new FileSystem[] { xfs }, cp);
744:                } else {
745:                    throw new AssertionError(type);
746:                }
747:            }
748:
749:            /**
750:             * Get the platform JARs associated with a standalone module project.
751:             */
752:            public static Set<File> getPlatformJarsForStandaloneProject(
753:                    Project project) {
754:                NbModuleProvider mod = project.getLookup().lookup(
755:                        NbModuleProvider.class);
756:                //TODO create a utility method to do this if needed in more places
757:                NbPlatform platform = null;
758:                File platformDir = mod.getActivePlatformLocation();
759:                if (platformDir != null) {
760:                    platform = NbPlatform.getPlatformByDestDir(platformDir);
761:                }
762:                if (platform == null || !platform.isValid()) {
763:                    platform = NbPlatform.getDefaultPlatform();
764:                }
765:                return getPlatformJars(platform, null, null, null);
766:            }
767:
768:            public static Set<File> getPlatformJarsForSuiteComponentProject(
769:                    Project project, SuiteProject suite) {
770:                NbPlatform platform = suite.getPlatform(true);
771:                PropertyEvaluator eval = suite.getEvaluator();
772:                String[] includedClusters = SuiteProperties.getArrayProperty(
773:                        eval, SuiteProperties.ENABLED_CLUSTERS_PROPERTY);
774:                String[] excludedClusters = SuiteProperties.getArrayProperty(
775:                        eval, SuiteProperties.DISABLED_CLUSTERS_PROPERTY);
776:                String[] excludedModules = SuiteProperties.getArrayProperty(
777:                        eval, SuiteProperties.DISABLED_MODULES_PROPERTY);
778:                return getPlatformJars(platform, includedClusters,
779:                        excludedClusters, excludedModules);
780:            }
781:
782:            public static Set<NbModuleProject> getProjectsForNetBeansOrgProject(
783:                    NbModuleProject project) throws IOException {
784:                ModuleList list = project.getModuleList();
785:                Set<NbModuleProject> projects = new HashSet<NbModuleProject>();
786:                projects.add(project);
787:                for (ModuleEntry other : list.getAllEntriesSoft()) {
788:                    if (other.getClusterDirectory().getName().equals("extra")) { // NOI18N
789:                        continue;
790:                    }
791:                    File root = other.getSourceLocation();
792:                    assert root != null : other;
793:                    NbModuleProject p2 = (NbModuleProject) ProjectManager
794:                            .getDefault().findProject(
795:                                    FileUtil.toFileObject(root));
796:                    if (p2 == null) {
797:                        continue;
798:                    }
799:                    projects.add(p2);
800:                }
801:                return projects;
802:            }
803:
804:            /**
805:             * Finds all the module JARs in the platform.
806:             * Can optionally pass non-null lists of cluster names and module CNBs to exclude, as per suite properties.
807:             */
808:            private static Set<File> getPlatformJars(NbPlatform platform,
809:                    String[] includedClusters, String[] excludedClusters,
810:                    String[] excludedModules) {
811:                if (platform == null) {
812:                    return Collections.emptySet();
813:                }
814:                Set<String> includedClustersS = (includedClusters != null) ? new HashSet<String>(
815:                        Arrays.asList(includedClusters))
816:                        : Collections.<String> emptySet();
817:                Set<String> excludedClustersS = (excludedClusters != null) ? new HashSet<String>(
818:                        Arrays.asList(excludedClusters))
819:                        : Collections.<String> emptySet();
820:                Set<String> excludedModulesS = (excludedModules != null) ? new HashSet<String>(
821:                        Arrays.asList(excludedModules))
822:                        : Collections.<String> emptySet();
823:                ModuleEntry[] entries = platform.getModules();
824:                Set<File> jars = new HashSet<File>(entries.length);
825:                for (ModuleEntry entry : entries) {
826:                    if (!includedClustersS.isEmpty()
827:                            && !includedClustersS.contains(entry
828:                                    .getClusterDirectory().getName())) {
829:                        continue;
830:                    }
831:                    if (includedClustersS.isEmpty()
832:                            && excludedClustersS.contains(entry
833:                                    .getClusterDirectory().getName())) {
834:                        continue;
835:                    }
836:                    if (excludedModulesS.contains(entry.getCodeNameBase())) {
837:                        continue;
838:                    }
839:                    jars.add(entry.getJarLocation());
840:                }
841:                return jars;
842:            }
843:
844:            /**
845:             * Constructs a list of filesystems representing the XML layers of the supplied platform module JARs.
846:             */
847:            private static FileSystem[] getPlatformLayers(Set<File> platformJars)
848:                    throws IOException {
849:                List<FileSystem> layers = new ArrayList<FileSystem>();
850:                JAR: for (File jar : platformJars) {
851:                    ManifestManager mm = ManifestManager
852:                            .getInstanceFromJAR(jar);
853:                    for (String tok : mm.getRequiredTokens()) {
854:                        if (tok.startsWith("org.openide.modules.os.")) { // NOI18N
855:                            // Best to exclude platform-specific modules, e.g. ide/applemenu, as they can cause confusion.
856:                            continue JAR;
857:                        }
858:                    }
859:                    String layer = mm.getLayer();
860:                    if (layer != null) {
861:                        URL u = new URL("jar:" + jar.toURI() + "!/" + layer);
862:                        try {
863:                            // XXX nbres: and such URL protocols may not work in platform layers
864:                            // (cf. org.openide.filesystems.ExternalUtil.findClass)
865:                            FileSystem xfs = new XMLFileSystem(u);
866:                            boolean hasMasks = false;
867:                            Enumeration e = xfs.getRoot().getChildren(true);
868:                            while (e.hasMoreElements()) {
869:                                FileObject f = (FileObject) e.nextElement();
870:                                if (f.getNameExt().endsWith("_hidden")) { // NOI18N
871:                                    // #63295: put it at the beginning. Not as good as following module deps but probably close enough.
872:                                    hasMasks = true;
873:                                    break;
874:                                }
875:                            }
876:                            if (hasMasks) {
877:                                layers.add(0, xfs);
878:                            } else {
879:                                layers.add(xfs);
880:                            }
881:                        } catch (SAXException e) {
882:                            throw (IOException) new IOException(e.toString())
883:                                    .initCause(e);
884:                        }
885:                    }
886:                }
887:                return layers.toArray(new FileSystem[layers.size()]);
888:            }
889:
890:            /**
891:             * Creates a classpath representing the source roots and platform binary JARs for a project/suite.
892:             */
893:            static ClassPath createLayerClasspath(
894:                    Set<? extends Project> moduleProjects,
895:                    Set<File> platformJars) throws IOException {
896:                List<URL> roots = new ArrayList<URL>();
897:                for (Project p : moduleProjects) {
898:                    NbModuleProvider mod = p.getLookup().lookup(
899:                            NbModuleProvider.class);
900:                    FileObject src = mod.getSourceDirectory();
901:                    if (src != null) {
902:                        roots.add(src.getURL());
903:                    }
904:                }
905:                for (File jar : platformJars) {
906:                    roots.add(FileUtil.getArchiveRoot(jar.toURI().toURL()));
907:                    File locale = new File(jar.getParentFile(), "locale"); // NOI18N
908:                    if (locale.isDirectory()) {
909:                        String n = jar.getName();
910:                        int x = n.lastIndexOf('.');
911:                        if (x == -1) {
912:                            x = n.length();
913:                        }
914:                        String base = n.substring(0, x);
915:                        String ext = n.substring(x);
916:                        String[] variants = locale.list();
917:                        if (variants != null) {
918:                            for (int i = 0; i < variants.length; i++) {
919:                                if (variants[i].startsWith(base)
920:                                        && variants[i].endsWith(ext)
921:                                        && variants[i].charAt(x) == '_') {
922:                                    roots.add(FileUtil.getArchiveRoot(new File(
923:                                            locale, variants[i]).toURI()
924:                                            .toURL()));
925:                                }
926:                            }
927:                        }
928:                    }
929:                }
930:                // XXX in principle, could add CP extensions from modules... but probably not necessary
931:                return ClassPathSupport.createClassPath(roots
932:                        .toArray(new URL[roots.size()]));
933:            }
934:
935:            /**
936:             * Create a merged filesystem from one writable layer (may be null) and some read-only layers.
937:             * You should also pass a classpath that can be used to look up resource bundles and icons.
938:             */
939:            private static FileSystem mergeFilesystems(
940:                    FileSystem writableLayer, FileSystem[] readOnlyLayers,
941:                    final ClassPath cp) {
942:                if (writableLayer == null) {
943:                    writableLayer = new XMLFileSystem();
944:                }
945:                final FileSystem[] layers = new FileSystem[readOnlyLayers.length + 1];
946:                layers[0] = writableLayer;
947:                System.arraycopy(readOnlyLayers, 0, layers, 1,
948:                        readOnlyLayers.length);
949:                class BadgingMergedFileSystem extends MultiFileSystem {
950:                    private final BadgingSupport status;
951:
952:                    public BadgingMergedFileSystem() {
953:                        super (layers);
954:                        status = new BadgingSupport(this );
955:                        status.setClasspath(cp);
956:                        status.setSuffix("_" + Locale.getDefault());
957:                        // XXX listening?
958:                    }
959:
960:                    @Override
961:                    public FileSystem.Status getStatus() {
962:                        return status;
963:                    }
964:                }
965:                return new BadgingMergedFileSystem();
966:            }
967:
968:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.